fix(MCPSettings, OpenAIProvider): Update settings and content handling

- Prevent modal from closing on mask click in MCPSettings
- Ensure tool call response content is properly formatted as a string in OpenAIProvider
This commit is contained in:
kangfenmao 2025-03-13 00:25:07 +08:00
parent 7122d44b13
commit fb27be0f59
4 changed files with 24 additions and 21 deletions

View File

@ -712,7 +712,11 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
disabled={files.length > 0} disabled={files.length > 0}
/> />
)} )}
<MCPToolsButton enabledMCPs={enabledMCPs} onEnableMCP={toggelEnableMCP} ToolbarButton={ToolbarButton} /> <MCPToolsButton
enabledMCPs={enabledMCPs}
toggelEnableMCP={toggelEnableMCP}
ToolbarButton={ToolbarButton}
/>
<AttachmentButton model={model} files={files} setFiles={setFiles} ToolbarButton={ToolbarButton} /> <AttachmentButton model={model} files={files} setFiles={setFiles} ToolbarButton={ToolbarButton} />
<Tooltip placement="top" title={t('chat.input.clear', { Command: cleanTopicShortcut })} arrow> <Tooltip placement="top" title={t('chat.input.clear', { Command: cleanTopicShortcut })} arrow>
<Popconfirm <Popconfirm

View File

@ -2,20 +2,20 @@ import { CodeOutlined } from '@ant-design/icons'
import { useMCPServers } from '@renderer/hooks/useMCPServers' import { useMCPServers } from '@renderer/hooks/useMCPServers'
import { MCPServer } from '@renderer/types' import { MCPServer } from '@renderer/types'
import { Dropdown, Switch, Tooltip } from 'antd' import { Dropdown, Switch, Tooltip } from 'antd'
import { FC, useEffect, useRef, useState } from 'react' import { every } from 'lodash'
import { FC, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
interface Props { interface Props {
enabledMCPs: MCPServer[] enabledMCPs: MCPServer[]
onEnableMCP: (server: MCPServer) => void toggelEnableMCP: (server: MCPServer) => void
ToolbarButton: any ToolbarButton: any
} }
const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton }) => { const MCPToolsButton: FC<Props> = ({ enabledMCPs, toggelEnableMCP, ToolbarButton }) => {
const { mcpServers } = useMCPServers() const { mcpServers } = useMCPServers()
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
const [enableAll, setEnableAll] = useState(false)
const dropdownRef = useRef<any>(null) const dropdownRef = useRef<any>(null)
const menuRef = useRef<HTMLDivElement>(null) const menuRef = useRef<HTMLDivElement>(null)
const { t } = useTranslation() const { t } = useTranslation()
@ -28,19 +28,11 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
// Check if all active servers are enabled // Check if all active servers are enabled
const activeServers = mcpServers.filter((s) => s.isActive) const activeServers = mcpServers.filter((s) => s.isActive)
// This effect only runs when enableAll changes, not on every render const enableAll = every(activeServers, (server) =>
useEffect(() => { enabledMCPs.some((enabledServer) => enabledServer.name === server.name)
if (activeServers.length > 0) { )
activeServers.forEach((server) => {
const isServerEnabled = enabledMCPs.includes(server) const setEnableAll = () => activeServers.forEach((s) => toggelEnableMCP(s))
if (enableAll && !isServerEnabled) {
onEnableMCP(server) // Enable server if enableAll is true and server is disabled
} else if (!enableAll && isServerEnabled) {
onEnableMCP(server) // Disable server if enableAll is false and server is enabled
}
})
}
}, [enableAll]) // Only depend on enableAll, not on enabledMCPs
const menu = ( const menu = (
<div ref={menuRef} className="ant-dropdown-menu"> <div ref={menuRef} className="ant-dropdown-menu">
@ -67,7 +59,11 @@ const MCPToolsButton: FC<Props> = ({ enabledMCPs, onEnableMCP, ToolbarButton })
)} )}
{server.baseUrl && <div className="server-url">{server.baseUrl}</div>} {server.baseUrl && <div className="server-url">{server.baseUrl}</div>}
</div> </div>
<Switch size="small" checked={enabledMCPs.includes(server)} onChange={() => onEnableMCP(server)} /> <Switch
size="small"
checked={enabledMCPs.some((s) => s.name === server.name)}
onChange={() => toggelEnableMCP(server)}
/>
</McpServerItems> </McpServerItems>
)) ))
) : ( ) : (

View File

@ -291,6 +291,7 @@ const MCPSettings: FC = () => {
onCancel={handleCancel} onCancel={handleCancel}
onOk={handleSubmit} onOk={handleSubmit}
confirmLoading={loading} confirmLoading={loading}
maskClosable={false}
width={600}> width={600}>
<Form form={form} layout="vertical"> <Form form={form} layout="vertical">
<Form.Item <Form.Item

View File

@ -33,7 +33,7 @@ import {
openAIToolsToMcpTool, openAIToolsToMcpTool,
upsertMCPToolResponse upsertMCPToolResponse
} from '@renderer/utils/mcp-tools' } from '@renderer/utils/mcp-tools'
import { takeRight } from 'lodash' import { isString, takeRight } from 'lodash'
import OpenAI, { AzureOpenAI } from 'openai' import OpenAI, { AzureOpenAI } from 'openai'
import { import {
ChatCompletionAssistantMessageParam, ChatCompletionAssistantMessageParam,
@ -400,7 +400,9 @@ export default class OpenAIProvider extends BaseProvider {
reqMessages.push({ reqMessages.push({
role: 'tool', role: 'tool',
content: toolCallResponse.content, content: isString(toolCallResponse.content)
? toolCallResponse.content
: JSON.stringify(toolCallResponse.content),
tool_call_id: toolCall.id tool_call_id: toolCall.id
} as ChatCompletionToolMessageParam) } as ChatCompletionToolMessageParam)