'use client' import type { FC } from 'react' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import cn from 'classnames' import Button from '../base/button' import { Plus } from '../base/icons/src/vender/line/general' import Toast from '../base/toast' import type { Collection, CustomCollectionBackend, Tool } from './types' import { CollectionType, LOC } from './types' import ToolNavList from './tool-nav-list' import Search from './search' import Contribute from './contribute' import ToolList from './tool-list' import EditCustomToolModal from './edit-custom-collection-modal' import NoCustomTool from './info/no-custom-tool' import NoSearchRes from './info/no-search-res' import NoCustomToolPlaceholder from './no-custom-tool-placeholder' import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import TabSlider from '@/app/components/base/tab-slider' import { createCustomCollection, fetchCollectionList as doFetchCollectionList, fetchBuiltInToolList, fetchCustomToolList, fetchModelToolList } from '@/service/tools' import type { AgentTool } from '@/types/app' type Props = { loc: LOC addedTools?: AgentTool[] onAddTool?: (collection: Collection, payload: Tool) => void selectedProviderId?: string } const Tools: FC = ({ loc, addedTools, onAddTool, selectedProviderId, }) => { const { t } = useTranslation() const isInToolsPage = loc === LOC.tools const isInDebugPage = !isInToolsPage const [collectionList, setCollectionList] = useState([]) const [currCollectionIndex, setCurrCollectionIndex] = useState(null) const [isDetailLoading, setIsDetailLoading] = useState(false) const fetchCollectionList = async () => { const list = await doFetchCollectionList() setCollectionList(list) if (list.length > 0 && currCollectionIndex === null) { let index = 0 if (selectedProviderId) index = list.findIndex(item => item.id === selectedProviderId) setCurrCollectionIndex(index || 0) } } useEffect(() => { fetchCollectionList() }, []) const collectionTypeOptions = (() => { const res = [ { value: CollectionType.builtIn, text: t('tools.type.builtIn') }, { value: CollectionType.custom, text: t('tools.type.custom') }, ] if (!isInToolsPage) res.unshift({ value: CollectionType.all, text: t('tools.type.all') }) return res })() const [query, setQuery] = useState('') const [toolPageCollectionType, setToolPageCollectionType] = useTabSearchParams({ defaultTab: collectionTypeOptions[0].value, }) const [appPageCollectionType, setAppPageCollectionType] = useState(collectionTypeOptions[0].value) const { collectionType, setCollectionType } = (() => { if (isInToolsPage) { return { collectionType: toolPageCollectionType, setCollectionType: setToolPageCollectionType, } } return { collectionType: appPageCollectionType, setCollectionType: setAppPageCollectionType, } })() const showCollectionList = (() => { let typeFilteredList: Collection[] = [] if (collectionType === CollectionType.all) typeFilteredList = collectionList.filter(item => item.type !== CollectionType.model) else if (collectionType === CollectionType.builtIn) typeFilteredList = collectionList.filter(item => item.type === CollectionType.builtIn) else if (collectionType === CollectionType.custom) typeFilteredList = collectionList.filter(item => item.type === CollectionType.custom) if (query) return typeFilteredList.filter(item => item.name.includes(query)) return typeFilteredList })() const hasNoCustomCollection = !collectionList.find(item => item.type === CollectionType.custom) useEffect(() => { setCurrCollectionIndex(0) }, [collectionType]) const currCollection = (() => { if (currCollectionIndex === null) return null return showCollectionList[currCollectionIndex] })() const [currTools, setCurrentTools] = useState([]) useEffect(() => { if (!currCollection) return (async () => { setIsDetailLoading(true) try { if (currCollection.type === CollectionType.builtIn) { const list = await fetchBuiltInToolList(currCollection.name) setCurrentTools(list) } else if (currCollection.type === CollectionType.model) { const list = await fetchModelToolList(currCollection.name) setCurrentTools(list) } else { const list = await fetchCustomToolList(currCollection.name) setCurrentTools(list) } } catch (e) { } setIsDetailLoading(false) })() }, [currCollection?.name, currCollection?.type]) const [isShowEditCollectionToolModal, setIsShowEditCollectionToolModal] = useState(false) const handleCreateToolCollection = () => { setIsShowEditCollectionToolModal(true) } const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => { await createCustomCollection(data) Toast.notify({ type: 'success', message: t('common.api.actionSuccess'), }) await fetchCollectionList() setIsShowEditCollectionToolModal(false) } return ( <>
{/* sidebar */}
{isInToolsPage && ( )} {isInDebugPage && (
)} setCollectionType(v as CollectionType)} options={collectionTypeOptions} /> {isInToolsPage && ( )} {(collectionType === CollectionType.custom && hasNoCustomCollection) ? (
) : ( (showCollectionList.length > 0 || !query) ? : (
{ setQuery('') }} />
) )} {loc === LOC.tools && ( )}
{/* tools */}
{!(collectionType === CollectionType.custom && hasNoCustomCollection) && showCollectionList.length > 0 && ( { setCurrCollectionIndex(0) fetchCollectionList() }} isLoading={isDetailLoading} /> )} {collectionType === CollectionType.custom && hasNoCustomCollection && ( )}
{isShowEditCollectionToolModal && ( setIsShowEditCollectionToolModal(false)} onAdd={doCreateCustomToolCollection} /> )} ) } export default React.memo(Tools)