feat(Inputbar, MCPToolsButton, AssistantMCPSettings): integrate active MCP server handling and UI updates
- Added active MCP server filtering in Inputbar for message sending. - Updated MCPToolsButton to reflect availability of enabled MCPs. - Refactored AssistantMCPSettings to streamline MCP server updates and adjusted UI styles for consistency.
This commit is contained in:
parent
8b9929cc7b
commit
bfbfba13fe
@ -13,6 +13,7 @@ import TranslateButton from '@renderer/components/TranslateButton'
|
|||||||
import { isFunctionCallingModel, isGenerateImageModel, isVisionModel, isWebSearchModel } from '@renderer/config/models'
|
import { isFunctionCallingModel, isGenerateImageModel, isVisionModel, isWebSearchModel } from '@renderer/config/models'
|
||||||
import db from '@renderer/databases'
|
import db from '@renderer/databases'
|
||||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||||
|
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||||
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
|
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
|
||||||
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
||||||
import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
|
import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
|
||||||
@ -101,6 +102,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
const isVision = useMemo(() => isVisionModel(model), [model])
|
const isVision = useMemo(() => isVisionModel(model), [model])
|
||||||
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])
|
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const { activedMcpServers } = useMCPServers()
|
||||||
|
|
||||||
const showKnowledgeIcon = useSidebarIconShow('knowledge')
|
const showKnowledgeIcon = useSidebarIconShow('knowledge')
|
||||||
const showMCPToolsIcon = isFunctionCallingModel(model)
|
const showMCPToolsIcon = isFunctionCallingModel(model)
|
||||||
@ -148,7 +150,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
// Reset to assistant knowledge mcp servers
|
// Reset to assistant knowledge mcp servers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setEnabledMCPs(assistant.mcpServers || [])
|
setEnabledMCPs(assistant.mcpServers || [])
|
||||||
}, [assistant])
|
}, [assistant.mcpServers])
|
||||||
|
|
||||||
const sendMessage = useCallback(async () => {
|
const sendMessage = useCallback(async () => {
|
||||||
if (inputEmpty || loading) {
|
if (inputEmpty || loading) {
|
||||||
@ -179,8 +181,12 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
userMessage.mentions = mentionModels
|
userMessage.mentions = mentionModels
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabledMCPs) {
|
if (isFunctionCallingModel(model)) {
|
||||||
userMessage.enabledMCPs = enabledMCPs
|
if (!isEmpty(assistant.mcpServers) && !isEmpty(activedMcpServers)) {
|
||||||
|
userMessage.enabledMCPs = activedMcpServers.filter((server) =>
|
||||||
|
assistant.mcpServers?.some((s) => s.id === server.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userMessage.usage = await estimateMessageUsage(userMessage)
|
userMessage.usage = await estimateMessageUsage(userMessage)
|
||||||
@ -202,13 +208,14 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
|||||||
console.error('Failed to send message:', error)
|
console.error('Failed to send message:', error)
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
|
activedMcpServers,
|
||||||
assistant,
|
assistant,
|
||||||
dispatch,
|
dispatch,
|
||||||
enabledMCPs,
|
|
||||||
files,
|
files,
|
||||||
inputEmpty,
|
inputEmpty,
|
||||||
loading,
|
loading,
|
||||||
mentionModels,
|
mentionModels,
|
||||||
|
model,
|
||||||
resizeTextArea,
|
resizeTextArea,
|
||||||
selectedKnowledgeBases,
|
selectedKnowledgeBases,
|
||||||
text,
|
text,
|
||||||
|
|||||||
@ -19,6 +19,10 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, toggelEnableMCP, ToolbarButton
|
|||||||
const menuRef = useRef<HTMLDivElement>(null)
|
const menuRef = useRef<HTMLDivElement>(null)
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const availableMCPs = activedMcpServers.filter((server) => enabledMCPs.some((s) => s.id === server.id))
|
||||||
|
|
||||||
|
const buttonEnabled = availableMCPs.length > 0
|
||||||
|
|
||||||
const truncateText = (text: string, maxLength: number = 50) => {
|
const truncateText = (text: string, maxLength: number = 50) => {
|
||||||
if (!text || text.length <= maxLength) return text
|
if (!text || text.length <= maxLength) return text
|
||||||
return text.substring(0, maxLength) + '...'
|
return text.substring(0, maxLength) + '...'
|
||||||
@ -102,7 +106,7 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, toggelEnableMCP, ToolbarButton
|
|||||||
overlayClassName="mention-models-dropdown">
|
overlayClassName="mention-models-dropdown">
|
||||||
<Tooltip placement="top" title={t('settings.mcp.title')} arrow>
|
<Tooltip placement="top" title={t('settings.mcp.title')} arrow>
|
||||||
<ToolbarButton type="text" ref={dropdownRef}>
|
<ToolbarButton type="text" ref={dropdownRef}>
|
||||||
<CodeOutlined style={{ color: enabledMCPs.length > 0 ? 'var(--color-primary)' : 'var(--color-icon)' }} />
|
<CodeOutlined style={{ color: buttonEnabled ? 'var(--color-primary)' : 'var(--color-icon)' }} />
|
||||||
</ToolbarButton>
|
</ToolbarButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|||||||
@ -25,14 +25,14 @@ interface Props {
|
|||||||
|
|
||||||
const AssistantMCPSettings: React.FC<Props> = ({ assistant, updateAssistant }) => {
|
const AssistantMCPSettings: React.FC<Props> = ({ assistant, updateAssistant }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { mcpServers: allMcpServers } = useMCPServers()
|
const { mcpServers: allMcpServers } = useMCPServers()
|
||||||
|
|
||||||
const onUpdate = (ids: string[]) => {
|
const onUpdate = (ids: string[]) => {
|
||||||
const mcpServers = ids
|
const mcpServers = ids
|
||||||
.map((id) => allMcpServers.find((server) => server.id === id))
|
.map((id) => allMcpServers.find((server) => server.id === id))
|
||||||
.filter((server): server is MCPServer => server !== undefined && server.isActive)
|
.filter((server): server is MCPServer => server !== undefined && server.isActive)
|
||||||
const _assistant = { ...assistant, mcpServers }
|
|
||||||
updateAssistant(_assistant)
|
updateAssistant({ ...assistant, mcpServers })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleServerToggle = (serverId: string) => {
|
const handleServerToggle = (serverId: string) => {
|
||||||
@ -52,7 +52,7 @@ const AssistantMCPSettings: React.FC<Props> = ({ assistant, updateAssistant }) =
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<HeaderContainer>
|
<HeaderContainer>
|
||||||
<Box style={{ fontWeight: 'bold', fontSize: '16px' }}>
|
<Box style={{ fontWeight: 'bold', fontSize: '14px' }}>
|
||||||
{t('assistants.settings.mcp.title')}
|
{t('assistants.settings.mcp.title')}
|
||||||
<Tooltip title={t('assistants.settings.mcp.description', 'Select MCP servers to use with this assistant')}>
|
<Tooltip title={t('assistants.settings.mcp.description', 'Select MCP servers to use with this assistant')}>
|
||||||
<InfoIcon />
|
<InfoIcon />
|
||||||
@ -111,9 +111,6 @@ const Container = styled.div`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 12px;
|
|
||||||
background-color: ${(props) => props.theme.colors?.background || '#f9f9f9'};
|
|
||||||
border-radius: 8px;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const HeaderContainer = styled.div`
|
const HeaderContainer = styled.div`
|
||||||
@ -126,13 +123,13 @@ const HeaderContainer = styled.div`
|
|||||||
const InfoIcon = styled(InfoCircleOutlined)`
|
const InfoIcon = styled(InfoCircleOutlined)`
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: ${(props) => props.theme.colors?.textSecondary || '#8c8c8c'};
|
color: var(--color-text-2);
|
||||||
cursor: help;
|
cursor: help;
|
||||||
`
|
`
|
||||||
|
|
||||||
const EnabledCount = styled.span`
|
const EnabledCount = styled.span`
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: ${(props) => props.theme.colors?.textSecondary || '#8c8c8c'};
|
color: var(--color-text-2);
|
||||||
`
|
`
|
||||||
|
|
||||||
const EmptyContainer = styled.div`
|
const EmptyContainer = styled.div`
|
||||||
@ -148,7 +145,6 @@ const ServerList = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 4px;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const ServerItem = styled.div<{ isEnabled: boolean }>`
|
const ServerItem = styled.div<{ isEnabled: boolean }>`
|
||||||
@ -157,15 +153,9 @@ const ServerItem = styled.div<{ isEnabled: boolean }>`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: ${(props) => props.theme.colors?.cardBackground || '#fff'};
|
background-color: var(--color-background-mute);
|
||||||
border: 1px solid ${(props) => props.theme.colors?.border || '#e6e6e6'};
|
border: 1px solid var(--color-border);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
opacity: ${(props) => (props.isEnabled ? 1 : 0.7)};
|
opacity: ${(props) => (props.isEnabled ? 1 : 0.7)};
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user