mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 01:18:05 +08:00
refactor(web): align MCP availability context migration
- move MCP availability context to block-selector/context and update imports - preserve sandbox gating, parent-provider inheritance, and blockedBy semantics - add context tests on top of refactor baseline cases - regenerate and prune eslint suppressions
This commit is contained in:
@ -0,0 +1,88 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { renderHook } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { MCPToolAvailabilityProvider, useMCPToolAvailability } from '../mcp-tool-availability-context'
|
||||
|
||||
describe('useMCPToolAvailability', () => {
|
||||
it('returns allowed=true without provider', () => {
|
||||
const { result } = renderHook(() => useMCPToolAvailability())
|
||||
|
||||
expect(result.current).toEqual({ allowed: true })
|
||||
})
|
||||
|
||||
it('returns allowed=true when version is not provided to provider', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: true })
|
||||
})
|
||||
|
||||
it('returns allowed=false when version is not supported', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider versionSupported={false}>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: false, blockedBy: 'version' })
|
||||
})
|
||||
|
||||
it('returns allowed=true when version is supported', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider versionSupported={true}>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: true })
|
||||
})
|
||||
|
||||
it('returns allowed=false when sandbox is not enabled', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider sandboxEnabled={false}>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: false, blockedBy: 'sandbox' })
|
||||
})
|
||||
|
||||
it('inherits parent provider values when child omits them', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider sandboxEnabled={false}>
|
||||
<MCPToolAvailabilityProvider versionSupported={true}>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: false, blockedBy: 'sandbox' })
|
||||
})
|
||||
|
||||
it('allows access when child provider overrides parent sandbox value', () => {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MCPToolAvailabilityProvider sandboxEnabled={false}>
|
||||
<MCPToolAvailabilityProvider versionSupported={true} sandboxEnabled={true}>
|
||||
{children}
|
||||
</MCPToolAvailabilityProvider>
|
||||
</MCPToolAvailabilityProvider>
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => useMCPToolAvailability(), { wrapper })
|
||||
|
||||
expect(result.current).toEqual({ allowed: true })
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,63 @@
|
||||
'use client'
|
||||
import type { ReactNode } from 'react'
|
||||
import { createContext, useContext, useMemo } from 'react'
|
||||
|
||||
type MCPToolAvailabilityContextValue = {
|
||||
versionSupported?: boolean
|
||||
sandboxEnabled?: boolean
|
||||
}
|
||||
|
||||
const MCPToolAvailabilityContext = createContext<MCPToolAvailabilityContextValue | undefined>(undefined)
|
||||
|
||||
export type MCPToolAvailability = {
|
||||
allowed: boolean
|
||||
blockedBy?: 'version' | 'sandbox'
|
||||
}
|
||||
|
||||
type ProviderProps = {
|
||||
versionSupported?: boolean
|
||||
sandboxEnabled?: boolean
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export function MCPToolAvailabilityProvider({
|
||||
versionSupported,
|
||||
sandboxEnabled,
|
||||
children,
|
||||
}: ProviderProps): ReactNode {
|
||||
const parent = useContext(MCPToolAvailabilityContext)
|
||||
|
||||
const value = useMemo<MCPToolAvailabilityContextValue>(() => ({
|
||||
versionSupported: versionSupported ?? parent?.versionSupported,
|
||||
sandboxEnabled: sandboxEnabled ?? parent?.sandboxEnabled,
|
||||
}), [versionSupported, sandboxEnabled, parent])
|
||||
|
||||
return (
|
||||
<MCPToolAvailabilityContext.Provider value={value}>
|
||||
{children}
|
||||
</MCPToolAvailabilityContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export function useMCPToolAvailability(): MCPToolAvailability {
|
||||
const context = useContext(MCPToolAvailabilityContext)
|
||||
|
||||
if (!context)
|
||||
return { allowed: true }
|
||||
|
||||
const versionAllowed = context.versionSupported ?? true
|
||||
const sandboxAllowed = context.sandboxEnabled ?? true
|
||||
const allowed = versionAllowed && sandboxAllowed
|
||||
|
||||
let blockedBy: MCPToolAvailability['blockedBy']
|
||||
if (!versionAllowed)
|
||||
blockedBy = 'version'
|
||||
else if (!sandboxAllowed)
|
||||
blockedBy = 'sandbox'
|
||||
|
||||
if (blockedBy)
|
||||
return { allowed, blockedBy }
|
||||
|
||||
return { allowed }
|
||||
}
|
||||
Reference in New Issue
Block a user