mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-23 10:00:08 +08:00
添加智能体订阅功能 (#5954)
* 添加智能体订阅功能 * 修改图标 * 修改hook点 修改图标 * 优雅的引用图标 * feat(i18n): add settings title for agents in multiple languages * fix(i18n): update translations for improved clarity * Merge branch 'main' into Subscribe --------- Co-authored-by: VM 96 <eov@88.com> Co-authored-by: suyao <sy20010504@gmail.com>
This commit is contained in:
parent
8bd38ccd86
commit
71cd2def2e
@ -44,6 +44,9 @@
|
||||
"my_agents": "My Agents",
|
||||
"search.no_results": "No results found",
|
||||
"sorting.title": "Sorting",
|
||||
"settings": {
|
||||
"title": "Agent Setting"
|
||||
},
|
||||
"tag.agent": "Agent",
|
||||
"tag.default": "Default",
|
||||
"tag.new": "New",
|
||||
|
||||
@ -48,7 +48,10 @@
|
||||
"tag.default": "デフォルト",
|
||||
"tag.new": "新規",
|
||||
"tag.system": "システム",
|
||||
"title": "エージェント"
|
||||
"title": "エージェント",
|
||||
"settings": {
|
||||
"title": "エージェント設定"
|
||||
}
|
||||
},
|
||||
"assistants": {
|
||||
"title": "アシスタント",
|
||||
|
||||
@ -48,6 +48,9 @@
|
||||
},
|
||||
"export": {
|
||||
"agent": "Экспорт агента"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки агента"
|
||||
}
|
||||
},
|
||||
"assistants": {
|
||||
|
||||
@ -48,7 +48,10 @@
|
||||
"tag.default": "默认",
|
||||
"tag.new": "新建",
|
||||
"tag.system": "系统",
|
||||
"title": "智能体"
|
||||
"title": "智能体",
|
||||
"settings": {
|
||||
"title": "智能体配置"
|
||||
}
|
||||
},
|
||||
"assistants": {
|
||||
"title": "助手",
|
||||
|
||||
@ -48,7 +48,10 @@
|
||||
"tag.default": "預設",
|
||||
"tag.new": "新增",
|
||||
"tag.system": "系統",
|
||||
"title": "智慧代理人"
|
||||
"title": "智慧代理人",
|
||||
"settings": {
|
||||
"title": "智慧代理人設定"
|
||||
}
|
||||
},
|
||||
"assistants": {
|
||||
"title": "助手",
|
||||
|
||||
@ -2,6 +2,8 @@ import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { Agent } from '@renderer/types'
|
||||
import { useEffect, useState } from 'react'
|
||||
import store from '@renderer/store'
|
||||
|
||||
let _agents: Agent[] = []
|
||||
|
||||
export const getAgentsFromSystemAgents = (systemAgents: any) => {
|
||||
@ -19,27 +21,44 @@ export function useSystemAgents() {
|
||||
const { defaultAgent } = useSettings()
|
||||
const [agents, setAgents] = useState<Agent[]>([])
|
||||
const { resourcesPath } = useRuntime()
|
||||
const { agentssubscribeUrl } = store.getState().settings
|
||||
|
||||
useEffect(() => {
|
||||
const loadAgents = async () => {
|
||||
try {
|
||||
// 始终加载本地 agents
|
||||
// 检查是否使用远程数据源
|
||||
if (agentssubscribeUrl && agentssubscribeUrl.startsWith('http')) {
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
const response = await fetch(agentssubscribeUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
const agentsData = await response.json() as Agent[];
|
||||
setAgents(agentsData);
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error("Failed to load remote agents:", error);
|
||||
// 远程加载失败,继续尝试加载本地数据
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有远程配置或获取失败,加载本地代理
|
||||
if (resourcesPath && _agents.length === 0) {
|
||||
const localAgentsData = await window.api.fs.read(resourcesPath + '/data/agents.json')
|
||||
_agents = JSON.parse(localAgentsData) as Agent[]
|
||||
}
|
||||
|
||||
// 如果没有远程配置或获取失败,使用本地 agents
|
||||
|
||||
setAgents(_agents)
|
||||
} catch (error) {
|
||||
console.error('Failed to load agents:', error)
|
||||
// 发生错误时使用本地 agents
|
||||
// 发生错误时使用已加载的本地 agents
|
||||
setAgents(_agents)
|
||||
}
|
||||
}
|
||||
|
||||
loadAgents()
|
||||
}, [defaultAgent, resourcesPath])
|
||||
}, [defaultAgent, resourcesPath, agentssubscribeUrl])
|
||||
|
||||
return agents
|
||||
}
|
||||
|
||||
47
src/renderer/src/pages/settings/DataSettings/AgentsSubscribeUrlSettings.tsx
Executable file
47
src/renderer/src/pages/settings/DataSettings/AgentsSubscribeUrlSettings.tsx
Executable file
@ -0,0 +1,47 @@
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setAgentssubscribeUrl } from '@renderer/store/settings'
|
||||
import Input from 'antd/es/input/Input'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
||||
|
||||
const AgentsSubscribeUrlSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const { agentssubscribeUrl } = useSettings()
|
||||
|
||||
const handleAgentChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setAgentssubscribeUrl(e.target.value))
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle>
|
||||
{t('agents.tag.agent')}
|
||||
{t('settings.websearch.subscribe_add')}
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.websearch.subscribe_url')}</SettingRowTitle>
|
||||
<HStack alignItems="center" gap="5px" style={{ width: 315 }}>
|
||||
<Input
|
||||
type="text"
|
||||
value={agentssubscribeUrl || ''}
|
||||
onChange={handleAgentChange}
|
||||
style={{ width: 315 }}
|
||||
placeholder={t('settings.websearch.subscribe_name.placeholder')}
|
||||
/>
|
||||
</HStack>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
</SettingGroup>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentsSubscribeUrlSettings
|
||||
@ -17,12 +17,13 @@ import { reset } from '@renderer/services/BackupService'
|
||||
import { AppInfo } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Typography } from 'antd'
|
||||
import { FileText, FolderCog, FolderInput } from 'lucide-react'
|
||||
import { FileText, FolderCog, FolderInput, Sparkle } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
||||
import AgentsSubscribeUrlSettings from './AgentsSubscribeUrlSettings'
|
||||
import ExportMenuOptions from './ExportMenuSettings'
|
||||
import JoplinSettings from './JoplinSettings'
|
||||
import MarkdownExportSettings from './MarkdownExportSettings'
|
||||
@ -81,6 +82,7 @@ const DataSettings: FC = () => {
|
||||
title: 'settings.data.markdown_export.title',
|
||||
icon: <FileText size={16} />
|
||||
},
|
||||
|
||||
{ key: 'divider_3', isDivider: true, text: t('settings.data.divider.third_party') },
|
||||
{ key: 'notion', title: 'settings.data.notion.title', icon: <i className="iconfont icon-notion" /> },
|
||||
{
|
||||
@ -102,6 +104,11 @@ const DataSettings: FC = () => {
|
||||
key: 'siyuan',
|
||||
title: 'settings.data.siyuan.title',
|
||||
icon: <SiyuanIcon />
|
||||
},
|
||||
{
|
||||
key: 'agentssubscribe_url',
|
||||
title: 'agents.settings.title',
|
||||
icon: <Sparkle size={16} className="icon" />
|
||||
}
|
||||
]
|
||||
|
||||
@ -253,6 +260,7 @@ const DataSettings: FC = () => {
|
||||
{menu === 'joplin' && <JoplinSettings />}
|
||||
{menu === 'obsidian' && <ObsidianSettings />}
|
||||
{menu === 'siyuan' && <SiyuanSettings />}
|
||||
{menu === 'agentssubscribe_url' && <AgentsSubscribeUrlSettings />}
|
||||
</SettingContainer>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@ -111,6 +111,8 @@ export interface SettingsState {
|
||||
siyuanToken: string | null
|
||||
siyuanBoxId: string | null
|
||||
siyuanRootPath: string | null
|
||||
// 订阅的助手地址
|
||||
agentssubscribeUrl: string | null
|
||||
// MinApps
|
||||
maxKeepAliveMinapps: number
|
||||
showOpenedMinappsInSidebar: boolean
|
||||
@ -218,6 +220,7 @@ export const initialState: SettingsState = {
|
||||
siyuanToken: null,
|
||||
siyuanBoxId: null,
|
||||
siyuanRootPath: null,
|
||||
agentssubscribeUrl: '',
|
||||
// MinApps
|
||||
maxKeepAliveMinapps: 3,
|
||||
showOpenedMinappsInSidebar: true,
|
||||
@ -493,6 +496,9 @@ const settingsSlice = createSlice({
|
||||
setSiyuanRootPath: (state, action: PayloadAction<string>) => {
|
||||
state.siyuanRootPath = action.payload
|
||||
},
|
||||
setAgentssubscribeUrl: (state, action: PayloadAction<string>) => {
|
||||
state.agentssubscribeUrl = action.payload
|
||||
},
|
||||
setMaxKeepAliveMinapps: (state, action: PayloadAction<number>) => {
|
||||
state.maxKeepAliveMinapps = action.payload
|
||||
},
|
||||
@ -599,6 +605,7 @@ export const {
|
||||
setSiyuanApiUrl,
|
||||
setSiyuanToken,
|
||||
setSiyuanBoxId,
|
||||
setAgentssubscribeUrl,
|
||||
setSiyuanRootPath,
|
||||
setMaxKeepAliveMinapps,
|
||||
setShowOpenedMinappsInSidebar,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user