mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-11 08:19:01 +08:00
feat(agents): add api server check and warning for agent features
- Add api server enabled check in multiple components - Show warning alert when api server is disabled - Add dismissable warning in AgentSection - Disable send button when api server is disabled - Add iknow state to store dismissed warnings
This commit is contained in:
parent
9425437480
commit
3c12f9052e
@ -1,3 +1,4 @@
|
|||||||
|
import { Alert } from '@heroui/react'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { ContentSearch, ContentSearchRef } from '@renderer/components/ContentSearch'
|
import { ContentSearch, ContentSearchRef } from '@renderer/components/ContentSearch'
|
||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
@ -49,6 +50,7 @@ const Chat: FC<Props> = (props) => {
|
|||||||
const chatMaxWidth = useChatMaxWidth()
|
const chatMaxWidth = useChatMaxWidth()
|
||||||
const { chat } = useRuntime()
|
const { chat } = useRuntime()
|
||||||
const { activeTopicOrSession, activeAgentId, activeSessionId } = chat
|
const { activeTopicOrSession, activeAgentId, activeSessionId } = chat
|
||||||
|
const { apiServer } = useSettings()
|
||||||
|
|
||||||
const mainRef = React.useRef<HTMLDivElement>(null)
|
const mainRef = React.useRef<HTMLDivElement>(null)
|
||||||
const contentSearchRef = React.useRef<ContentSearchRef>(null)
|
const contentSearchRef = React.useRef<ContentSearchRef>(null)
|
||||||
@ -149,8 +151,15 @@ const Chat: FC<Props> = (props) => {
|
|||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
return () => <div> Active Session ID is invalid.</div>
|
return () => <div> Active Session ID is invalid.</div>
|
||||||
}
|
}
|
||||||
|
if (!apiServer.enabled) {
|
||||||
|
return () => (
|
||||||
|
<div>
|
||||||
|
<Alert color="warning" title={t('agent.warning.enable_server')} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
return () => <AgentSessionMessages agentId={activeAgentId} sessionId={sessionId} />
|
return () => <AgentSessionMessages agentId={activeAgentId} sessionId={sessionId} />
|
||||||
}, [activeAgentId, activeSessionId])
|
}, [activeAgentId, activeSessionId, apiServer.enabled, t])
|
||||||
|
|
||||||
const SessionInputBar = useMemo(() => {
|
const SessionInputBar = useMemo(() => {
|
||||||
if (activeAgentId === null) {
|
if (activeAgentId === null) {
|
||||||
|
|||||||
@ -36,6 +36,7 @@ const AgentSessionInputbar: FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
const [text, setText] = useState(_text)
|
const [text, setText] = useState(_text)
|
||||||
const [inputFocus, setInputFocus] = useState(false)
|
const [inputFocus, setInputFocus] = useState(false)
|
||||||
const { session } = useSession(agentId, sessionId)
|
const { session } = useSession(agentId, sessionId)
|
||||||
|
const { apiServer } = useSettings()
|
||||||
|
|
||||||
const { sendMessageShortcut, fontSize, enableSpellCheck } = useSettings()
|
const { sendMessageShortcut, fontSize, enableSpellCheck } = useSettings()
|
||||||
const textareaRef = useRef<TextAreaRef>(null)
|
const textareaRef = useRef<TextAreaRef>(null)
|
||||||
@ -52,6 +53,7 @@ const AgentSessionInputbar: FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const inputEmpty = isEmpty(text)
|
const inputEmpty = isEmpty(text)
|
||||||
|
const sendDisabled = inputEmpty || !apiServer.enabled
|
||||||
|
|
||||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
//to check if the SendMessage key is pressed
|
//to check if the SendMessage key is pressed
|
||||||
@ -96,7 +98,7 @@ const AgentSessionInputbar: FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = useCallback(async () => {
|
const sendMessage = useCallback(async () => {
|
||||||
if (inputEmpty) {
|
if (sendDisabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ const AgentSessionInputbar: FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
}, [
|
}, [
|
||||||
agentId,
|
agentId,
|
||||||
dispatch,
|
dispatch,
|
||||||
inputEmpty,
|
sendDisabled,
|
||||||
session?.agent_id,
|
session?.agent_id,
|
||||||
session?.instructions,
|
session?.instructions,
|
||||||
session?.model,
|
session?.model,
|
||||||
@ -231,7 +233,7 @@ const AgentSessionInputbar: FC<Props> = ({ agentId, sessionId }) => {
|
|||||||
onBlur={() => setInputFocus(false)}
|
onBlur={() => setInputFocus(false)}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end px-1">
|
<div className="flex justify-end px-1">
|
||||||
<SendMessageButton sendMessage={sendMessage} disabled={inputEmpty} />
|
<SendMessageButton sendMessage={sendMessage} disabled={sendDisabled} />
|
||||||
</div>
|
</div>
|
||||||
</InputBarContainer>
|
</InputBarContainer>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Assistant } from '@renderer/types'
|
|||||||
import { FC, useRef } from 'react'
|
import { FC, useRef } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { Agents } from './components/Agents'
|
import { AgentSection } from './components/AgentSection'
|
||||||
import Assistants from './components/Assistants'
|
import Assistants from './components/Assistants'
|
||||||
|
|
||||||
interface AssistantsTabProps {
|
interface AssistantsTabProps {
|
||||||
@ -17,7 +17,7 @@ const AssistantsTab: FC<AssistantsTabProps> = (props) => {
|
|||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
return (
|
return (
|
||||||
<Container className="assistants-tab" ref={containerRef}>
|
<Container className="assistants-tab" ref={containerRef}>
|
||||||
<Agents />
|
<AgentSection />
|
||||||
<Assistants {...props} />
|
<Assistants {...props} />
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Spinner } from '@heroui/react'
|
import { Alert, Spinner } from '@heroui/react'
|
||||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||||
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { AnimatePresence, motion } from 'framer-motion'
|
import { AnimatePresence, motion } from 'framer-motion'
|
||||||
import { FC, memo } from 'react'
|
import { FC, memo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -12,6 +13,15 @@ const SessionsTab: FC<SessionsTabProps> = () => {
|
|||||||
const { chat } = useRuntime()
|
const { chat } = useRuntime()
|
||||||
const { activeAgentId } = chat
|
const { activeAgentId } = chat
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { apiServer } = useSettings()
|
||||||
|
|
||||||
|
if (!apiServer.enabled) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Alert color="warning" title={t('agent.warning.enable_server')} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
|
|||||||
39
src/renderer/src/pages/home/Tabs/components/AgentSection.tsx
Normal file
39
src/renderer/src/pages/home/Tabs/components/AgentSection.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Alert } from '@heroui/react'
|
||||||
|
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||||
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
|
import { useAppDispatch } from '@renderer/store'
|
||||||
|
import { addIknowAction } from '@renderer/store/runtime'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import { Agents } from './Agents'
|
||||||
|
import { SectionName } from './SectionName'
|
||||||
|
|
||||||
|
const ALERT_KEY = 'enable_api_server_to_use_agent'
|
||||||
|
|
||||||
|
export const AgentSection = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { apiServer } = useSettings()
|
||||||
|
const { iknow } = useRuntime()
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
|
if (!apiServer.enabled) {
|
||||||
|
if (iknow[ALERT_KEY]) return null
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
color="warning"
|
||||||
|
title={t('agent.warning.enable_server')}
|
||||||
|
isClosable
|
||||||
|
onClose={() => {
|
||||||
|
dispatch(addIknowAction(ALERT_KEY))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="agents-tab h-full w-full">
|
||||||
|
<SectionName name={t('common.agent_other')} />
|
||||||
|
<Agents />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -9,7 +9,6 @@ import { FC, useCallback, useEffect } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import AgentItem from './AgentItem'
|
import AgentItem from './AgentItem'
|
||||||
import { SectionName } from './SectionName'
|
|
||||||
|
|
||||||
interface AssistantsTabProps {}
|
interface AssistantsTabProps {}
|
||||||
|
|
||||||
@ -35,8 +34,7 @@ export const Agents: FC<AssistantsTabProps> = () => {
|
|||||||
}, [isLoading, agents, activeAgentId, setActiveAgentId])
|
}, [isLoading, agents, activeAgentId, setActiveAgentId])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="agents-tab h-full w-full">
|
<>
|
||||||
<SectionName name={t('common.agent_other')} />
|
|
||||||
{isLoading && <Spinner />}
|
{isLoading && <Spinner />}
|
||||||
{error && <Alert color="danger" title={t('agent.list.error.failed')} />}
|
{error && <Alert color="danger" title={t('agent.list.error.failed')} />}
|
||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
@ -65,6 +63,6 @@ export const Agents: FC<AssistantsTabProps> = () => {
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,7 @@ export interface RuntimeState {
|
|||||||
export: ExportState
|
export: ExportState
|
||||||
chat: ChatState
|
chat: ChatState
|
||||||
websearch: WebSearchState
|
websearch: WebSearchState
|
||||||
|
iknow: Record<string, boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExportState {
|
export interface ExportState {
|
||||||
@ -93,7 +94,8 @@ const initialState: RuntimeState = {
|
|||||||
},
|
},
|
||||||
websearch: {
|
websearch: {
|
||||||
activeSearches: {}
|
activeSearches: {}
|
||||||
}
|
},
|
||||||
|
iknow: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const runtimeSlice = createSlice({
|
const runtimeSlice = createSlice({
|
||||||
@ -179,6 +181,9 @@ const runtimeSlice = createSlice({
|
|||||||
delete state.websearch.activeSearches[requestId]
|
delete state.websearch.activeSearches[requestId]
|
||||||
}
|
}
|
||||||
state.websearch.activeSearches[requestId] = status
|
state.websearch.activeSearches[requestId] = status
|
||||||
|
},
|
||||||
|
addIknowAction: (state, action: PayloadAction<string>) => {
|
||||||
|
state.iknow[action.payload] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -197,6 +202,7 @@ export const {
|
|||||||
setResourcesPath,
|
setResourcesPath,
|
||||||
setUpdateState,
|
setUpdateState,
|
||||||
setExportState,
|
setExportState,
|
||||||
|
addIknowAction,
|
||||||
// Chat related actions
|
// Chat related actions
|
||||||
toggleMultiSelectMode,
|
toggleMultiSelectMode,
|
||||||
setSelectedMessageIds,
|
setSelectedMessageIds,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user