'use client' import type { FC } from 'react' import React, { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import ToolTrigger from '@/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger' import ToolPicker from '@/app/components/workflow/block-selector/tool-picker' import Button from '@/app/components/base/button' import Indicator from '@/app/components/header/indicator' import ToolCredentialForm from '@/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form' import Toast from '@/app/components/base/toast' import { useAppContext } from '@/context/app-context' import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools, useInvalidateAllBuiltInTools, useUpdateProviderCredentials, } from '@/service/use-tools' import { CollectionType } from '@/app/components/tools/types' import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types' import type { OffsetOptions, Placement, } from '@floating-ui/react' import cn from '@/utils/classnames' type Props = { value?: { provider: string tool_name: string } disabled?: boolean placement?: Placement offset?: OffsetOptions onSelect: (tool: { provider: string tool_name: string }) => void supportAddCustomTool?: boolean } const ToolSelector: FC = ({ value, disabled, placement = 'bottom', offset = 4, onSelect, }) => { const { t } = useTranslation() const [isShow, onShowChange] = useState(false) const handleTriggerClick = () => { if (disabled) return onShowChange(true) } const { data: buildInTools } = useAllBuiltInTools() const { data: customTools } = useAllCustomTools() const { data: workflowTools } = useAllWorkflowTools() const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools() const currentProvider = useMemo(() => { const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])] return mergedTools.find((toolWithProvider) => { return toolWithProvider.id === value?.provider && toolWithProvider.tools.some(tool => tool.name === value?.tool_name) }) }, [value, buildInTools, customTools, workflowTools]) const [isShowChooseTool, setIsShowChooseTool] = useState(false) const handleSelectTool = (tool: ToolDefaultValue) => { const toolValue = { provider: tool.provider_id, tool_name: tool.tool_name, } onSelect(toolValue) setIsShowChooseTool(false) if (tool.provider_type === CollectionType.builtIn && tool.is_team_authorization) onShowChange(false) } const { isCurrentWorkspaceManager } = useAppContext() const [isShowSettingAuth, setShowSettingAuth] = useState(false) const handleCredentialSettingUpdate = () => { invalidateAllBuiltinTools() Toast.notify({ type: 'success', message: t('common.api.actionSuccess'), }) setShowSettingAuth(false) onShowChange(false) } const { mutate: updatePermission } = useUpdateProviderCredentials({ onSuccess: handleCredentialSettingUpdate, }) return ( <>
{t('tools.toolSelector.label')}
} isShow={isShowChooseTool} onShowChange={setIsShowChooseTool} disabled={false} supportAddCustomTool onSelect={handleSelectTool} />
{/* authorization panel */} {isShowSettingAuth && currentProvider && (
setShowSettingAuth(false)} onSaved={async value => updatePermission({ providerName: currentProvider.name, credentials: value, })} />
)} {!isShowSettingAuth && currentProvider && currentProvider.type === CollectionType.builtIn && currentProvider.is_team_authorization && currentProvider.allow_delete && (
{t('tools.toolSelector.auth')}
{isCurrentWorkspaceManager && ( )}
)} {!isShowSettingAuth && currentProvider && currentProvider.type === CollectionType.builtIn && !currentProvider.is_team_authorization && currentProvider.allow_delete && (
)}
) } export default React.memo(ToolSelector)