mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-31 08:29:07 +08:00
refactor(agents): extract update agent logic into separate hook
Move update agent functionality from useAgent and useAgents hooks into a dedicated useUpdateAgent hook to improve code organization and maintainability
This commit is contained in:
parent
043a4fb5ca
commit
7b96900726
@ -19,6 +19,7 @@ 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 { 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'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -78,7 +79,8 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
|
||||
const { t } = useTranslation()
|
||||
const loadingRef = useRef(false)
|
||||
// const { setTimeoutTimer } = useTimer()
|
||||
const { addAgent, updateAgent } = useAgents()
|
||||
const { addAgent } = useAgents()
|
||||
const updateAgent = useUpdateAgent()
|
||||
// hard-coded. We only support anthropic for now.
|
||||
const { models } = useModels({ providerType: 'anthropic' })
|
||||
const isEditing = (agent?: AgentEntity) => agent !== undefined
|
||||
@ -348,7 +350,7 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
|
||||
/>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
<span className="font-medium text-foreground text-sm">
|
||||
{t('agent.session.accessible_paths.label')}
|
||||
</span>
|
||||
<Button size="sm" variant="flat" onPress={addAccessiblePath}>
|
||||
@ -371,7 +373,7 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-foreground-400">{t('agent.session.accessible_paths.empty')}</p>
|
||||
<p className="text-foreground-400 text-sm">{t('agent.session.accessible_paths.empty')}</p>
|
||||
)}
|
||||
</div>
|
||||
<Textarea label={t('common.prompt')} value={form.instructions ?? ''} onValueChange={onInstChange} />
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
import { UpdateAgentForm } from '@renderer/types'
|
||||
import { formatErrorMessageWithPrefix } from '@renderer/utils/error'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useSWR from 'swr'
|
||||
|
||||
import { useAgentClient } from './useAgentClient'
|
||||
|
||||
export const useAgent = (id: string | null) => {
|
||||
const { t } = useTranslation()
|
||||
const client = useAgentClient()
|
||||
const key = id ? client.agentPaths.withId(id) : null
|
||||
const fetcher = useCallback(async () => {
|
||||
@ -17,26 +13,11 @@ export const useAgent = (id: string | null) => {
|
||||
const result = await client.getAgent(id)
|
||||
return result
|
||||
}, [client, id])
|
||||
const { data, error, isLoading, mutate } = useSWR(key, id ? fetcher : null)
|
||||
|
||||
const updateAgent = useCallback(
|
||||
async (form: UpdateAgentForm) => {
|
||||
try {
|
||||
// may change to optimistic update
|
||||
const result = await client.updateAgent(form)
|
||||
mutate(result)
|
||||
window.toast.success(t('common.update_success'))
|
||||
} catch (error) {
|
||||
window.toast.error(formatErrorMessageWithPrefix(error, t('agent.update.error.failed')))
|
||||
}
|
||||
},
|
||||
[client, mutate, t]
|
||||
)
|
||||
const { data, error, isLoading } = useSWR(key, id ? fetcher : null)
|
||||
|
||||
return {
|
||||
agent: data,
|
||||
error,
|
||||
isLoading,
|
||||
updateAgent
|
||||
isLoading
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { AddAgentForm, UpdateAgentForm } from '@renderer/types'
|
||||
import { AddAgentForm } from '@renderer/types'
|
||||
import { formatErrorMessageWithPrefix } from '@renderer/utils/error'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -12,6 +12,7 @@ export const useAgents = () => {
|
||||
const key = client.agentPaths.base
|
||||
const fetcher = useCallback(async () => {
|
||||
const result = await client.listAgents()
|
||||
// NOTE: We only use the array for now. useUpdateAgent depends on this behavior.
|
||||
return result.data
|
||||
}, [client])
|
||||
const { data, error, isLoading, mutate } = useSWR(key, fetcher)
|
||||
@ -29,20 +30,6 @@ export const useAgents = () => {
|
||||
[client, mutate, t]
|
||||
)
|
||||
|
||||
const updateAgent = useCallback(
|
||||
async (form: UpdateAgentForm) => {
|
||||
try {
|
||||
// may change to optimistic update
|
||||
const result = await client.updateAgent(form)
|
||||
mutate((prev) => prev?.map((a) => (a.id === result.id ? result : a)) ?? [])
|
||||
window.toast.success(t('common.update_success'))
|
||||
} catch (error) {
|
||||
window.toast.error(formatErrorMessageWithPrefix(error, t('agent.update.error.failed')))
|
||||
}
|
||||
},
|
||||
[client, mutate, t]
|
||||
)
|
||||
|
||||
const deleteAgent = useCallback(
|
||||
async (id: string) => {
|
||||
try {
|
||||
@ -69,7 +56,6 @@ export const useAgents = () => {
|
||||
error,
|
||||
isLoading,
|
||||
addAgent,
|
||||
updateAgent,
|
||||
deleteAgent,
|
||||
getAgent
|
||||
}
|
||||
|
||||
31
src/renderer/src/hooks/agents/useUpdateAgent.ts
Normal file
31
src/renderer/src/hooks/agents/useUpdateAgent.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { ListAgentsResponse, UpdateAgentForm } from '@renderer/types'
|
||||
import { formatErrorMessageWithPrefix } from '@renderer/utils/error'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { mutate } from 'swr'
|
||||
|
||||
import { useAgentClient } from './useAgentClient'
|
||||
|
||||
export const useUpdateAgent = () => {
|
||||
const { t } = useTranslation()
|
||||
const client = useAgentClient()
|
||||
const listKey = client.agentPaths.base
|
||||
|
||||
const updateAgent = useCallback(
|
||||
async (form: UpdateAgentForm) => {
|
||||
try {
|
||||
const itemKey = client.agentPaths.withId(form.id)
|
||||
// may change to optimistic update
|
||||
const result = await client.updateAgent(form)
|
||||
mutate<ListAgentsResponse['data']>(listKey, (prev) => prev?.map((a) => (a.id === result.id ? result : a)) ?? [])
|
||||
mutate(itemKey, result)
|
||||
window.toast.success(t('common.update_success'))
|
||||
} catch (error) {
|
||||
window.toast.error(formatErrorMessageWithPrefix(error, t('agent.update.error.failed')))
|
||||
}
|
||||
},
|
||||
[client, listKey, t]
|
||||
)
|
||||
|
||||
return updateAgent
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import CodeEditor from '@renderer/components/CodeEditor'
|
||||
import { Box, HSpaceBetweenStack, HStack } from '@renderer/components/Layout'
|
||||
import { RichEditorRef } from '@renderer/components/RichEditor/types'
|
||||
import { useAgent } from '@renderer/hooks/agents/useAgent'
|
||||
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||
import { usePromptProcessor } from '@renderer/hooks/usePromptProcessor'
|
||||
import { estimateTextTokens } from '@renderer/services/TokenService'
|
||||
import { AgentEntity, UpdateAgentForm } from '@renderer/types'
|
||||
@ -16,7 +16,7 @@ import { SettingDivider } from '..'
|
||||
|
||||
interface AgentEssentialSettingsProps {
|
||||
agent: AgentEntity | undefined | null
|
||||
update: ReturnType<typeof useAgent>['updateAgent']
|
||||
update: ReturnType<typeof useUpdateAgent>
|
||||
}
|
||||
|
||||
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update }) => {
|
||||
|
||||
@ -3,6 +3,7 @@ import { HStack } from '@renderer/components/Layout'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { getAgentAvatar } from '@renderer/config/agent'
|
||||
import { useAgent } from '@renderer/hooks/agents/useAgent'
|
||||
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||
import { Menu, Modal } from 'antd'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -26,7 +27,8 @@ const AgentSettingPopupContainer: React.FC<AgentSettingPopupParams> = ({ tab, ag
|
||||
const { t } = useTranslation()
|
||||
const [menu, setMenu] = useState<AgentSettingPopupTab>(tab || 'essential')
|
||||
|
||||
const { agent, updateAgent } = useAgent(agentId)
|
||||
const { agent } = useAgent(agentId)
|
||||
const updateAgent = useUpdateAgent()
|
||||
|
||||
const onOk = () => {
|
||||
setOpen(false)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user