mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-31 08:29:07 +08:00
feat: add AgentSettingsTab component and integrate into HomeTabs (#10668)
- Introduced the AgentSettingsTab component for managing agent settings. - Integrated AgentSettingsTab into HomeTabs, allowing access to agent settings based on the active session or topic. - Updated AgentEssentialSettings to conditionally render the ModelSetting based on props. - Adjusted styles in various components for consistency and improved layout.
This commit is contained in:
parent
88f7e6a854
commit
0d760ffa2e
40
src/renderer/src/pages/home/Tabs/AgentSettingsTab.tsx
Normal file
40
src/renderer/src/pages/home/Tabs/AgentSettingsTab.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { Button, Divider } from '@heroui/react'
|
||||||
|
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||||
|
import { AgentSettingsPopup } from '@renderer/pages/settings/AgentSettings'
|
||||||
|
import AdvancedSettings from '@renderer/pages/settings/AgentSettings/AdvancedSettings'
|
||||||
|
import AgentEssentialSettings from '@renderer/pages/settings/AgentSettings/AgentEssentialSettings'
|
||||||
|
import { GetAgentResponse } from '@renderer/types/agent'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
agent: GetAgentResponse | undefined | null
|
||||||
|
update: ReturnType<typeof useUpdateAgent>['updateAgent']
|
||||||
|
}
|
||||||
|
|
||||||
|
const AgentSettingsTab: FC<Props> = ({ agent, update }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const onMoreSetting = () => {
|
||||||
|
if (agent?.id) {
|
||||||
|
AgentSettingsPopup.show({ agentId: agent.id! })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!agent) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-[var(--assistants-width)] p-2 px-3 pt-4">
|
||||||
|
<AgentEssentialSettings agent={agent} update={update} showModelSetting={false} />
|
||||||
|
<AdvancedSettings agentBase={agent} update={update} />
|
||||||
|
<Divider className="my-2" />
|
||||||
|
<Button size="sm" fullWidth onPress={onMoreSetting}>
|
||||||
|
{t('settings.moresetting.label')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AgentSettingsTab
|
||||||
@ -116,8 +116,6 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<UnifiedAddButton onCreateAssistant={onCreateAssistant} />
|
|
||||||
|
|
||||||
{agentsLoading && <Spinner />}
|
{agentsLoading && <Spinner />}
|
||||||
{apiServer.enabled && agentsError && <Alert color="danger" title={t('agent.list.error.failed')} />}
|
{apiServer.enabled && agentsError && <Alert color="danger" title={t('agent.list.error.failed')} />}
|
||||||
|
|
||||||
@ -165,6 +163,8 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<UnifiedAddButton onCreateAssistant={onCreateAssistant} />
|
||||||
|
|
||||||
{!dragging && <div style={{ minHeight: 10 }}></div>}
|
{!dragging && <div style={{ minHeight: 10 }}></div>}
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const AddButton: FC<Props> = ({ children, className, ...props }) => {
|
|||||||
{...props}
|
{...props}
|
||||||
onPress={props.onPress}
|
onPress={props.onPress}
|
||||||
className={cn(
|
className={cn(
|
||||||
'h-9 w-[calc(var(--assistants-width)-20px)] justify-start rounded-full bg-transparent px-3 text-[13px] text-[var(--color-text-2)] hover:bg-[var(--color-list-item)]',
|
'h-9 w-[calc(var(--assistants-width)-20px)] justify-start rounded-lg bg-transparent px-3 text-[13px] text-[var(--color-text-2)] hover:bg-[var(--color-list-item)]',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
startContent={<PlusIcon size={16} className="shrink-0" />}>
|
startContent={<PlusIcon size={16} className="shrink-0" />}>
|
||||||
|
|||||||
@ -45,19 +45,12 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
|||||||
</AgentNameWrapper>
|
</AgentNameWrapper>
|
||||||
</AssistantNameRow>
|
</AssistantNameRow>
|
||||||
<MenuButton>
|
<MenuButton>
|
||||||
{isActive ? <SessionCount>{sessions.length}</SessionCount> : <Bot size={12} className="text-primary" />}
|
{isActive ? <SessionCount>{sessions.length}</SessionCount> : <Bot size={14} className="text-primary" />}
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
</Container>
|
</Container>
|
||||||
</ContextMenuTrigger>
|
</ContextMenuTrigger>
|
||||||
<ContextMenuContent>
|
<ContextMenuContent>
|
||||||
<ContextMenuItem
|
<ContextMenuItem key="edit" onClick={() => AgentSettingsPopup.show({ agentId: agent.id })}>
|
||||||
key="edit"
|
|
||||||
onClick={async () => {
|
|
||||||
// onOpen()
|
|
||||||
await AgentSettingsPopup.show({
|
|
||||||
agentId: agent.id
|
|
||||||
})
|
|
||||||
}}>
|
|
||||||
<EditIcon size={14} />
|
<EditIcon size={14} />
|
||||||
{t('common.edit')}
|
{t('common.edit')}
|
||||||
</ContextMenuItem>
|
</ContextMenuItem>
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
||||||
|
import { useAgent } from '@renderer/hooks/agents/useAgent'
|
||||||
|
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
|
||||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||||
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings'
|
||||||
@ -11,6 +13,7 @@ import { FC, useEffect, useState } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import AgentSettingsTab from './AgentSettingsTab'
|
||||||
import Assistants from './AssistantsTab'
|
import Assistants from './AssistantsTab'
|
||||||
import Settings from './SettingsTab'
|
import Settings from './SettingsTab'
|
||||||
import Topics from './TopicsTab'
|
import Topics from './TopicsTab'
|
||||||
@ -41,11 +44,12 @@ const HomeTabs: FC<Props> = ({
|
|||||||
const { defaultAssistant } = useDefaultAssistant()
|
const { defaultAssistant } = useDefaultAssistant()
|
||||||
const { toggleShowTopics } = useShowTopics()
|
const { toggleShowTopics } = useShowTopics()
|
||||||
const { isLeftNavbar } = useNavbarPosition()
|
const { isLeftNavbar } = useNavbarPosition()
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { chat } = useRuntime()
|
const { chat } = useRuntime()
|
||||||
const { activeTopicOrSession } = chat
|
const { activeTopicOrSession, activeAgentId } = chat
|
||||||
|
const { agent } = useAgent(activeAgentId)
|
||||||
|
const { updateAgent } = useUpdateAgent()
|
||||||
|
|
||||||
const isSessionView = activeTopicOrSession === 'session'
|
const isSessionView = activeTopicOrSession === 'session'
|
||||||
const isTopicView = activeTopicOrSession === 'topic'
|
const isTopicView = activeTopicOrSession === 'topic'
|
||||||
|
|
||||||
@ -61,7 +65,6 @@ const HomeTabs: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showTab = position === 'left' && topicPosition === 'left'
|
const showTab = position === 'left' && topicPosition === 'left'
|
||||||
const shouldShowSettingsTab = !isSessionView
|
|
||||||
|
|
||||||
const onCreateAssistant = async () => {
|
const onCreateAssistant = async () => {
|
||||||
const assistant = await AddAssistantPopup.show()
|
const assistant = await AddAssistantPopup.show()
|
||||||
@ -104,12 +107,6 @@ const HomeTabs: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}, [position, tab, topicPosition, forceToSeeAllTab])
|
}, [position, tab, topicPosition, forceToSeeAllTab])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (activeTopicOrSession === 'session' && tab === 'settings') {
|
|
||||||
setTab('topic')
|
|
||||||
}
|
|
||||||
}, [activeTopicOrSession, tab])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
style={{ ...border, ...style }}
|
style={{ ...border, ...style }}
|
||||||
@ -120,13 +117,11 @@ const HomeTabs: FC<Props> = ({
|
|||||||
{t('assistants.abbr')}
|
{t('assistants.abbr')}
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem active={tab === 'topic'} onClick={() => setTab('topic')}>
|
<TabItem active={tab === 'topic'} onClick={() => setTab('topic')}>
|
||||||
{isTopicView ? t('common.topics') : t('agent.session.label_other')}
|
{t('common.topics')}
|
||||||
|
</TabItem>
|
||||||
|
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
||||||
|
{t('settings.title')}
|
||||||
</TabItem>
|
</TabItem>
|
||||||
{shouldShowSettingsTab && (
|
|
||||||
<TabItem active={tab === 'settings'} onClick={() => setTab('settings')}>
|
|
||||||
{t('settings.title')}
|
|
||||||
</TabItem>
|
|
||||||
)}
|
|
||||||
</CustomTabs>
|
</CustomTabs>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -158,7 +153,8 @@ const HomeTabs: FC<Props> = ({
|
|||||||
position={position}
|
position={position}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{tab === 'settings' && shouldShowSettingsTab && <Settings assistant={activeAssistant} />}
|
{tab === 'settings' && isTopicView && <Settings assistant={activeAssistant} />}
|
||||||
|
{tab === 'settings' && isSessionView && <AgentSettingsTab agent={agent} update={updateAgent} />}
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
@ -214,7 +210,7 @@ const CustomTabs = styled.div`
|
|||||||
|
|
||||||
const TabItem = styled.button<{ active: boolean }>`
|
const TabItem = styled.button<{ active: boolean }>`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 32px;
|
height: 30px;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: ${(props) => (props.active ? 'var(--color-text)' : 'var(--color-text-secondary)')};
|
color: ${(props) => (props.active ? 'var(--color-text)' : 'var(--color-text-secondary)')};
|
||||||
@ -239,7 +235,7 @@ const TabItem = styled.button<{ active: boolean }>`
|
|||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -9px;
|
bottom: -8px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: ${(props) => (props.active ? '30px' : '0')};
|
width: ${(props) => (props.active ? '30px' : '0')};
|
||||||
|
|||||||
@ -71,11 +71,11 @@ export const AccessibleDirsSetting: React.FC<AccessibleDirsSettingProps> = ({ ba
|
|||||||
}>
|
}>
|
||||||
{t('agent.session.accessible_paths.label')}
|
{t('agent.session.accessible_paths.label')}
|
||||||
</SettingsTitle>
|
</SettingsTitle>
|
||||||
<ul className="mt-2 flex flex-col gap-2 rounded-xl border p-2">
|
<ul className="flex flex-col gap-2">
|
||||||
{base.accessible_paths.map((path) => (
|
{base.accessible_paths.map((path) => (
|
||||||
<li
|
<li
|
||||||
key={path}
|
key={path}
|
||||||
className="flex items-center justify-between gap-2 rounded-medium border border-default-200 px-3 py-2">
|
className="flex items-center justify-between gap-2 rounded-medium border border-default-200 px-2 py-1">
|
||||||
<span className="w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-sm" title={path}>
|
<span className="w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-sm" title={path}>
|
||||||
{path}
|
{path}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -18,9 +18,10 @@ import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
|||||||
interface AgentEssentialSettingsProps {
|
interface AgentEssentialSettingsProps {
|
||||||
agent: GetAgentResponse | undefined | null
|
agent: GetAgentResponse | undefined | null
|
||||||
update: ReturnType<typeof useUpdateAgent>['updateAgent']
|
update: ReturnType<typeof useUpdateAgent>['updateAgent']
|
||||||
|
showModelSetting?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update }) => {
|
const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update, showModelSetting = true }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
if (!agent) return null
|
if (!agent) return null
|
||||||
@ -36,7 +37,7 @@ const AgentEssentialSettings: FC<AgentEssentialSettingsProps> = ({ agent, update
|
|||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
<AvatarSetting agent={agent} update={update} />
|
<AvatarSetting agent={agent} update={update} />
|
||||||
<NameSetting base={agent} update={update} />
|
<NameSetting base={agent} update={update} />
|
||||||
<ModelSetting base={agent} update={update} />
|
{showModelSetting && <ModelSetting base={agent} update={update} />}
|
||||||
<AccessibleDirsSetting base={agent} update={update} />
|
<AccessibleDirsSetting base={agent} update={update} />
|
||||||
<DescriptionSetting base={agent} update={update} />
|
<DescriptionSetting base={agent} update={update} />
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export const NameSetting: React.FC<NameSettingsProps> = ({ base, update }) => {
|
|||||||
<Input
|
<Input
|
||||||
placeholder={t('common.agent_one') + t('common.name')}
|
placeholder={t('common.agent_one') + t('common.name')}
|
||||||
value={name}
|
value={name}
|
||||||
|
size="sm"
|
||||||
onValueChange={(value) => setName(value)}
|
onValueChange={(value) => setName(value)}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (name !== base.name) {
|
if (name !== base.name) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user