'use client' import type { FC } from 'react' import React, { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' import produce from 'immer' import { RiAddLine, RiCloseLine, } from '@remixicon/react' import { useMount } from 'ahooks' import type { Collection, CustomCollectionBackend, Tool } from '../types' import Type from './type' import Category from './category' import Tools from './tools' import cn from '@/utils/classnames' import I18n from '@/context/i18n' import { getLanguage } from '@/i18n/language' import Drawer from '@/app/components/base/drawer' import Button from '@/app/components/base/button' import Loading from '@/app/components/base/loading' import Input from '@/app/components/base/input' import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal' import ConfigCredential from '@/app/components/tools/setting/build-in/config-credentials' import { createCustomCollection, fetchAllBuiltInTools, fetchAllCustomTools, fetchAllWorkflowTools, removeBuiltInToolCredential, updateBuiltInToolCredential, } from '@/service/tools' import type { ToolWithProvider } from '@/app/components/workflow/types' import Toast from '@/app/components/base/toast' import ConfigContext from '@/context/debug-configuration' import type { ModelConfig } from '@/models/debug' type Props = { onHide: () => void } // Add and Edit const AddToolModal: FC = ({ onHide, }) => { const { t } = useTranslation() const { locale } = useContext(I18n) const language = getLanguage(locale) const [currentType, setCurrentType] = useState('builtin') const [currentCategory, setCurrentCategory] = useState('') const [keywords, setKeywords] = useState('') const handleKeywordsChange = (value: string) => { setKeywords(value) } const [toolList, setToolList] = useState([]) const [listLoading, setListLoading] = useState(true) const getAllTools = async () => { setListLoading(true) const buildInTools = await fetchAllBuiltInTools() const customTools = await fetchAllCustomTools() const workflowTools = await fetchAllWorkflowTools() const mergedToolList = [ ...buildInTools, ...customTools, ...workflowTools.filter((toolWithProvider) => { return !toolWithProvider.tools.some((tool) => { return !!tool.parameters.find(item => item.name === '__image') }) }), ] setToolList(mergedToolList) setListLoading(false) } const filteredList = useMemo(() => { return toolList.filter((toolWithProvider) => { if (currentType === 'all') return true else return toolWithProvider.type === currentType }).filter((toolWithProvider) => { if (!currentCategory) return true else return toolWithProvider.labels.includes(currentCategory) }).filter((toolWithProvider) => { return toolWithProvider.tools.some((tool) => { return Object.values(tool.label).some((label) => { return label.toLowerCase().includes(keywords.toLowerCase()) }) }) }) }, [currentType, currentCategory, toolList, keywords, language]) const { modelConfig, setModelConfig, } = useContext(ConfigContext) const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false) const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => { await createCustomCollection(data) Toast.notify({ type: 'success', message: t('common.api.actionSuccess'), }) setIsShowEditCustomCollectionModal(false) getAllTools() } const [showSettingAuth, setShowSettingAuth] = useState(false) const [collection, setCollection] = useState() const toolSelectHandle = (collection: Collection, tool: Tool) => { const parameters: Record = {} if (tool.parameters) { tool.parameters.forEach((item) => { parameters[item.name] = '' }) } const nexModelConfig = produce(modelConfig, (draft: ModelConfig) => { draft.agentConfig.tools.push({ provider_id: collection.id || collection.name, provider_type: collection.type, provider_name: collection.name, tool_name: tool.name, tool_label: tool.label[locale] || tool.label[locale.replaceAll('-', '_')], tool_parameters: parameters, enabled: true, }) }) setModelConfig(nexModelConfig) } const authSelectHandle = (provider: Collection) => { setCollection(provider) setShowSettingAuth(true) } const updateBuiltinAuth = async (value: Record) => { if (!collection) return await updateBuiltInToolCredential(collection.name, value) Toast.notify({ type: 'success', message: t('common.api.actionSuccess'), }) await getAllTools() setShowSettingAuth(false) } const removeBuiltinAuth = async () => { if (!collection) return await removeBuiltInToolCredential(collection.name) Toast.notify({ type: 'success', message: t('common.api.actionSuccess'), }) await getAllTools() setShowSettingAuth(false) } useMount(() => { getAllTools() }) return ( <>
{t('tools.addTool')}
handleKeywordsChange(e.target.value)} onClear={() => handleKeywordsChange('')} />
{listLoading && (
)} {!listLoading && ( )}
{isShowEditCollectionToolModal && ( setIsShowEditCustomCollectionModal(false)} onAdd={doCreateCustomToolCollection} /> )} {showSettingAuth && collection && ( setShowSettingAuth(false)} onSaved={updateBuiltinAuth} onRemove={removeBuiltinAuth} /> )} ) } export default React.memo(AddToolModal)