chore: add toggle loading sever MCP (#5225)
* chore: add toggle loading sever mcp * chore: remove duplicate classname * chore: remove log * chore: remove log * fix: save server config --------- Co-authored-by: Louis <louis@jan.ai>
This commit is contained in:
parent
891c149f1b
commit
8ba4b0be36
@ -2,20 +2,27 @@ import * as React from 'react'
|
||||
import * as SwitchPrimitive from '@radix-ui/react-switch'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { IconLoader2 } from '@tabler/icons-react'
|
||||
|
||||
function Switch({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
||||
type SwitchProps = React.ComponentProps<typeof SwitchPrimitive.Root> & {
|
||||
loading?: boolean
|
||||
}
|
||||
function Switch({ loading, className, ...props }: SwitchProps) {
|
||||
return (
|
||||
<SwitchPrimitive.Root
|
||||
data-slot="switch"
|
||||
className={cn(
|
||||
'peer cursor-pointer data-[state=checked]:bg-accent data-[state=unchecked]:bg-main-view-fg/20 focus-visible:border-none inline-flex h-[18px] w-8.5 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'relative peer cursor-pointer data-[state=checked]:bg-accent data-[state=unchecked]:bg-main-view-fg/20 focus-visible:border-none inline-flex h-[18px] w-8.5 shrink-0 items-center rounded-full border border-transparent shadow-xs outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50 transition-all',
|
||||
loading && 'w-4.5 pointer-events-none',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{loading && (
|
||||
<div className="absolute inset-0 flex items-center justify-center z-10 size-3.5 top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2">
|
||||
<IconLoader2 className="animate-spin text-main-view-fg/50" />
|
||||
</div>
|
||||
)}
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
className={cn(
|
||||
|
||||
@ -216,7 +216,6 @@ const DropdownModelProvider = ({
|
||||
// Add the filtered items to their respective groups
|
||||
filteredItems.forEach((item) => {
|
||||
const providerKey = item.provider.provider
|
||||
console.log(providerKey, 'providerKey')
|
||||
if (!groups[providerKey]) {
|
||||
groups[providerKey] = []
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ type MCPServerStoreState = {
|
||||
mcpServers: MCPServers
|
||||
loading: boolean
|
||||
deletedServerKeys: string[]
|
||||
getServerConfig: (key: string) => MCPServerConfig | undefined
|
||||
setLeftPanel: (value: boolean) => void
|
||||
addServer: (key: string, config: MCPServerConfig) => void
|
||||
editServer: (key: string, config: MCPServerConfig) => void
|
||||
@ -34,7 +35,11 @@ export const useMCPServers = create<MCPServerStoreState>()((set, get) => ({
|
||||
loading: false,
|
||||
deletedServerKeys: [],
|
||||
setLeftPanel: (value) => set({ open: value }),
|
||||
|
||||
getServerConfig: (key) => {
|
||||
const mcpServers = get().mcpServers
|
||||
// Return the server configuration if it exists, otherwise return undefined
|
||||
return mcpServers[key] ? mcpServers[key] : undefined
|
||||
},
|
||||
// Add a new MCP server or update if the key already exists
|
||||
addServer: (key, config) =>
|
||||
set((state) => {
|
||||
|
||||
@ -35,6 +35,7 @@ function MCPServers() {
|
||||
deleteServer,
|
||||
syncServers,
|
||||
syncServersAndRestart,
|
||||
getServerConfig,
|
||||
} = useMCPServers()
|
||||
const { allowAllMCPPermissions, setAllowAllMCPPermissions } =
|
||||
useToolApproval()
|
||||
@ -56,6 +57,9 @@ function MCPServers() {
|
||||
MCPServerConfig | Record<string, MCPServerConfig> | undefined
|
||||
>(undefined)
|
||||
const [connectedServers, setConnectedServers] = useState<string[]>([])
|
||||
const [loadingServers, setLoadingServers] = useState<{
|
||||
[key: string]: boolean
|
||||
}>({})
|
||||
|
||||
const handleOpenDialog = (serverKey?: string) => {
|
||||
if (serverKey) {
|
||||
@ -70,10 +74,13 @@ function MCPServers() {
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleSaveServer = (name: string, config: MCPServerConfig) => {
|
||||
const handleSaveServer = async (name: string, config: MCPServerConfig) => {
|
||||
try {
|
||||
await toggleServer(name, false)
|
||||
} catch (error) {
|
||||
console.error('Error deactivating server:', error)
|
||||
}
|
||||
if (editingKey) {
|
||||
// Edit existing server
|
||||
|
||||
// If server name changed, delete old one and add new one
|
||||
if (editingKey !== name) {
|
||||
deleteServer(editingKey)
|
||||
@ -85,7 +92,9 @@ function MCPServers() {
|
||||
// Add new server
|
||||
addServer(name, config)
|
||||
}
|
||||
syncServersAndRestart()
|
||||
|
||||
syncServers()
|
||||
await toggleServer(name, true)
|
||||
}
|
||||
|
||||
const handleEdit = (serverKey: string) => {
|
||||
@ -105,7 +114,7 @@ function MCPServers() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpenJsonEditor = (serverKey?: string) => {
|
||||
const handleOpenJsonEditor = async (serverKey?: string) => {
|
||||
if (serverKey) {
|
||||
// Edit single server JSON
|
||||
setJsonServerName(serverKey)
|
||||
@ -118,12 +127,19 @@ function MCPServers() {
|
||||
setJsonEditorOpen(true)
|
||||
}
|
||||
|
||||
const handleSaveJson = (
|
||||
const handleSaveJson = async (
|
||||
data: MCPServerConfig | Record<string, MCPServerConfig>
|
||||
) => {
|
||||
if (jsonServerName) {
|
||||
try {
|
||||
await toggleServer(jsonServerName, false)
|
||||
} catch (error) {
|
||||
console.error('Error deactivating server:', error)
|
||||
}
|
||||
// Save single server
|
||||
editServer(jsonServerName, data as MCPServerConfig)
|
||||
syncServers()
|
||||
toggleServer(jsonServerName, true)
|
||||
} else {
|
||||
// Save all servers
|
||||
// Clear existing servers first
|
||||
@ -138,23 +154,24 @@ function MCPServers() {
|
||||
}
|
||||
)
|
||||
}
|
||||
syncServersAndRestart()
|
||||
}
|
||||
|
||||
const toggleServer = (serverKey: string, active: boolean) => {
|
||||
if (serverKey)
|
||||
if (active)
|
||||
if (serverKey) {
|
||||
setLoadingServers((prev) => ({ ...prev, [serverKey]: true }))
|
||||
const config = getServerConfig(serverKey)
|
||||
if (active && config) {
|
||||
invoke('activate_mcp_server', {
|
||||
name: serverKey,
|
||||
config: {
|
||||
...(mcpServers[serverKey] as MCPServerConfig),
|
||||
...(config ?? (mcpServers[serverKey] as MCPServerConfig)),
|
||||
active,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
// Save single server
|
||||
editServer(serverKey, {
|
||||
...(mcpServers[serverKey] as MCPServerConfig),
|
||||
...(config ?? (mcpServers[serverKey] as MCPServerConfig)),
|
||||
active,
|
||||
})
|
||||
syncServers()
|
||||
@ -164,25 +181,30 @@ function MCPServers() {
|
||||
getConnectedServers().then(setConnectedServers)
|
||||
})
|
||||
.catch((error) => {
|
||||
editServer(serverKey, {
|
||||
...(config ?? (mcpServers[serverKey] as MCPServerConfig)),
|
||||
active: false,
|
||||
})
|
||||
toast.error(error, {
|
||||
description:
|
||||
'Please check the parameters according to the tutorial.',
|
||||
})
|
||||
})
|
||||
else {
|
||||
.finally(() => {
|
||||
setLoadingServers((prev) => ({ ...prev, [serverKey]: false }))
|
||||
})
|
||||
} else {
|
||||
editServer(serverKey, {
|
||||
...(mcpServers[serverKey] as MCPServerConfig),
|
||||
...(config ?? (mcpServers[serverKey] as MCPServerConfig)),
|
||||
active,
|
||||
})
|
||||
syncServers()
|
||||
invoke('deactivate_mcp_server', { name: serverKey })
|
||||
.catch((error) => {
|
||||
toast.error(`Failed to deactivate server ${serverKey}: ${error}`)
|
||||
})
|
||||
.finally(() => {
|
||||
getConnectedServers().then(setConnectedServers)
|
||||
})
|
||||
invoke('deactivate_mcp_server', { name: serverKey }).finally(() => {
|
||||
getConnectedServers().then(setConnectedServers)
|
||||
setLoadingServers((prev) => ({ ...prev, [serverKey]: false }))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -334,7 +356,8 @@ function MCPServers() {
|
||||
</div>
|
||||
<div className="ml-2">
|
||||
<Switch
|
||||
checked={config.active === false ? false : true}
|
||||
checked={config.active}
|
||||
loading={!!loadingServers[key]}
|
||||
onCheckedChange={(checked) =>
|
||||
toggleServer(key, checked)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user