mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
fix: activate assistant/agent when creating new (#11009)
* refactor: remove unused SWITCH_ASSISTANT event and related code Clean up unused event and associated listener in HomePage component * feat(agents): improve agent handling and state management - Return result from useUpdateAgent hook - Update useActiveTopic to handle null assistantId - Add state management for active agent and topic in Tabs - Implement afterSubmit callback in AgentModal - Refactor agent press handling in AssistantsTab - Clean up HomePage state management logic - Add afterCreate callback in UnifiedAddButton * refactor(agent): update agent and session update functions to return entities Modify update functions in useUpdateAgent and useUpdateSession hooks to return updated entities. Update related components to handle the new return types and adjust type definitions accordingly. * refactor(hooks): simplify active topic hook by using useAssistant * refactor(agent): consolidate agent update types and functions Move UpdateAgentBaseOptions and related function types from hooks/agents/types.ts to types/agent.ts Update components to use new UpdateAgentFunctionUnion type Simplify component props by removing redundant type definitions * refactor(agent): update type for plugin settings update function * refactor(AgentSettings): simplify tooling settings type definitions Remove unused hooks and use direct type imports instead of ReturnType
This commit is contained in:
parent
d792bf7fe0
commit
c1fd23742f
@ -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<Props> = ({ agent, isOpen: _isOpen, onClose: _onClose }) => {
|
||||
export const AgentModal: React.FC<Props> = ({ 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<Props> = ({ 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<Props> = ({ 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<Props> = ({ 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
|
||||
]
|
||||
)
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
export type UpdateAgentBaseOptions = {
|
||||
/** Whether to show success toast after updating. Defaults to true. */
|
||||
showSuccessToast?: boolean
|
||||
}
|
||||
@ -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<AgentEntity | undefined> => {
|
||||
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]
|
||||
|
||||
@ -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<AgentSessionEntity | undefined> => {
|
||||
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]
|
||||
|
||||
@ -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<SetStateAction<Topic>>
|
||||
|
||||
// const logger = loggerService.withContext('useTopic')
|
||||
|
||||
|
||||
@ -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<Assistant>(
|
||||
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 (
|
||||
<Container id="home-page">
|
||||
{isLeftNavbar && (
|
||||
|
||||
@ -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<AssistantsTabProps> = (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 (
|
||||
<Container className="assistants-tab" ref={containerRef}>
|
||||
{!apiServerConfig.enabled && !apiServerRunning && !iknow[ALERT_KEY] && (
|
||||
@ -126,7 +150,11 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<UnifiedAddButton onCreateAssistant={onCreateAssistant} />
|
||||
<UnifiedAddButton
|
||||
onCreateAssistant={onCreateAssistant}
|
||||
setActiveAssistant={setActiveAssistant}
|
||||
setActiveAgentId={setActiveAgentId}
|
||||
/>
|
||||
|
||||
{assistantsTabSortType === 'tags' ? (
|
||||
<UnifiedTagGroups
|
||||
@ -162,7 +190,7 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
||||
onAssistantSwitch={setActiveAssistant}
|
||||
onAssistantDelete={onDeleteAssistant}
|
||||
onAgentDelete={deleteAgent}
|
||||
onAgentPress={setActiveAgentId}
|
||||
onAgentPress={handleAgentPress}
|
||||
addPreset={addAssistantPreset}
|
||||
copyAssistant={copyAssistant}
|
||||
onCreateDefaultAssistant={onCreateDefaultAssistant}
|
||||
|
||||
@ -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<UnifiedAddButtonProps> = ({ onCreateAssistant }) => {
|
||||
const UnifiedAddButton: FC<UnifiedAddButtonProps> = ({ 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<UnifiedAddButtonProps> = ({ 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 (
|
||||
<div className="mb-1">
|
||||
<Popover
|
||||
@ -53,7 +84,7 @@ const UnifiedAddButton: FC<UnifiedAddButtonProps> = ({ onCreateAssistant }) => {
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
<AgentModal isOpen={isAgentModalOpen} onClose={onAgentModalClose} />
|
||||
<AgentModal isOpen={isAgentModalOpen} onClose={onAgentModalClose} afterSubmit={afterCreate} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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<Props> = ({
|
||||
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<Props> = ({
|
||||
|
||||
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(() => {
|
||||
|
||||
@ -62,7 +62,12 @@ const ChatNavbarContent: FC<Props> = ({ assistant }) => {
|
||||
)}
|
||||
{activeSession && (
|
||||
<BreadcrumbItem>
|
||||
<SelectAgentBaseModelButton agentBase={activeSession} onSelect={handleUpdateModel} />
|
||||
<SelectAgentBaseModelButton
|
||||
agentBase={activeSession}
|
||||
onSelect={async (model) => {
|
||||
await handleUpdateModel(model)
|
||||
}}
|
||||
/>
|
||||
</BreadcrumbItem>
|
||||
)}
|
||||
{activeAgent && activeSession && (
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunctionUnion
|
||||
}
|
||||
|
||||
const logger = loggerService.withContext('AccessibleDirsSetting')
|
||||
|
||||
export const AccessibleDirsSetting: React.FC<AccessibleDirsSettingProps> = ({ base, update }) => {
|
||||
export const AccessibleDirsSetting = ({ base, update }: AccessibleDirsSettingProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const updateAccessiblePaths = useCallback(
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunction
|
||||
}
|
||||
|
||||
// const logger = loggerService.withContext('AvatarSetting')
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunctionUnion
|
||||
}
|
||||
|
||||
export const DescriptionSetting: React.FC<DescriptionSettingProps> = ({ base, update }) => {
|
||||
export const DescriptionSetting = ({ base, update }: DescriptionSettingProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [description, setDescription] = useState<string | undefined>(base?.description?.trim())
|
||||
|
||||
|
||||
@ -46,7 +46,9 @@ const EssentialSettings: FC<EssentialSettingsProps> = ({ agentBase, update, show
|
||||
</div>
|
||||
</SettingsItem>
|
||||
)}
|
||||
{isAgent && <AvatarSetting agent={agentBase} update={update} />}
|
||||
{isAgent && (
|
||||
<AvatarSetting agent={agentBase} update={update as ReturnType<typeof useUpdateAgent>['updateAgent']} />
|
||||
)}
|
||||
<NameSetting base={agentBase} update={update} />
|
||||
{showModelSetting && <ModelSetting base={agentBase} update={update} />}
|
||||
<AccessibleDirsSetting base={agentBase} update={update} />
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunctionUnion
|
||||
isDisabled?: boolean
|
||||
}
|
||||
|
||||
export const ModelSetting: React.FC<ModelSettingProps> = ({ 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<ModelSettingProps> = ({ base, update, isDisa
|
||||
return (
|
||||
<SettingsItem inline>
|
||||
<SettingsTitle id="model">{t('common.model')}</SettingsTitle>
|
||||
<SelectAgentBaseModelButton agentBase={base} onSelect={updateModel} isDisabled={isDisabled} />
|
||||
<SelectAgentBaseModelButton
|
||||
agentBase={base}
|
||||
onSelect={async (model) => {
|
||||
await updateModel(model)
|
||||
}}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</SettingsItem>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunctionUnion
|
||||
}
|
||||
|
||||
export const NameSetting: React.FC<NameSettingsProps> = ({ base, update }) => {
|
||||
export const NameSetting = ({ base, update }: NameSettingsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [name, setName] = useState<string | undefined>(base?.name?.trim())
|
||||
const updateName = async (name: UpdateAgentBaseForm['name']) => {
|
||||
|
||||
@ -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<void>
|
||||
update: UpdateAgentFunctionUnion
|
||||
}
|
||||
|
||||
const PluginSettings: FC<PluginSettingsProps> = ({ agentBase }) => {
|
||||
|
||||
@ -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> | void
|
||||
update: UpdateAgentFunction
|
||||
}
|
||||
| {
|
||||
agentBase: GetAgentSessionResponse | undefined | null
|
||||
update: (form: UpdateSessionForm) => Promise<void> | void
|
||||
update: UpdateAgentSessionFunction
|
||||
}
|
||||
|
||||
type AgentConfigurationState = AgentConfiguration & Record<string, unknown>
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -227,6 +227,25 @@ export type SessionForm = CreateSessionForm | UpdateSessionForm
|
||||
|
||||
export type UpdateAgentBaseForm = Partial<AgentBase> & { 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<AgentEntity | undefined>
|
||||
|
||||
export type UpdateAgentSessionFunction = (
|
||||
form: UpdateSessionForm,
|
||||
options?: UpdateAgentBaseOptions
|
||||
) => Promise<AgentSessionEntity | undefined>
|
||||
|
||||
export type UpdateAgentFunctionUnion = UpdateAgentFunction | UpdateAgentSessionFunction
|
||||
|
||||
// ------------------ API data transfer objects ------------------
|
||||
export interface CreateAgentRequest extends AgentBase {
|
||||
type: AgentType
|
||||
|
||||
Loading…
Reference in New Issue
Block a user