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:
亢奋猫 2025-10-13 22:34:27 +08:00 committed by GitHub
parent 88f7e6a854
commit 0d760ffa2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 66 additions and 35 deletions

View 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

View File

@ -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>
) )

View File

@ -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" />}>

View File

@ -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>

View File

@ -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')};

View File

@ -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>

View File

@ -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>

View File

@ -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) {