| import type { | |||||
| Dispatch, | |||||
| SetStateAction, | |||||
| } from 'react' | |||||
| import { | import { | ||||
| useEffect, | useEffect, | ||||
| useMemo, | useMemo, | ||||
| import { PluginType } from '../../plugins/types' | import { PluginType } from '../../plugins/types' | ||||
| import { useMarketplacePlugins } from '../../plugins/marketplace/hooks' | import { useMarketplacePlugins } from '../../plugins/marketplace/hooks' | ||||
| import { useGlobalPublicStore } from '@/context/global-public-context' | import { useGlobalPublicStore } from '@/context/global-public-context' | ||||
| import RAGToolSuggestions from './rag-tool-suggestions' | |||||
| type AllToolsProps = { | type AllToolsProps = { | ||||
| className?: string | className?: string | ||||
| onSelectMultiple?: (type: BlockEnum, tools: ToolDefaultValue[]) => void | onSelectMultiple?: (type: BlockEnum, tools: ToolDefaultValue[]) => void | ||||
| selectedTools?: ToolValue[] | selectedTools?: ToolValue[] | ||||
| canChooseMCPTool?: boolean | canChooseMCPTool?: boolean | ||||
| onTagsChange: Dispatch<SetStateAction<string[]>> | |||||
| isInRAGPipeline?: boolean | |||||
| } | } | ||||
| const DEFAULT_TAGS: AllToolsProps['tags'] = [] | const DEFAULT_TAGS: AllToolsProps['tags'] = [] | ||||
| mcpTools = [], | mcpTools = [], | ||||
| selectedTools, | selectedTools, | ||||
| canChooseMCPTool, | canChooseMCPTool, | ||||
| onTagsChange, | |||||
| isInRAGPipeline = false, | |||||
| }: AllToolsProps) => { | }: AllToolsProps) => { | ||||
| const language = useGetLanguage() | const language = useGetLanguage() | ||||
| const tabs = useToolTabs() | const tabs = useToolTabs() | ||||
| category: PluginType.tool, | category: PluginType.tool, | ||||
| }) | }) | ||||
| } | } | ||||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||||
| }, [searchText, tags, enable_marketplace]) | }, [searchText, tags, enable_marketplace]) | ||||
| const pluginRef = useRef<ListRef>(null) | const pluginRef = useRef<ListRef>(null) | ||||
| const wrapElemRef = useRef<HTMLDivElement>(null) | const wrapElemRef = useRef<HTMLDivElement>(null) | ||||
| const isSupportGroupView = [ToolTypeEnum.All, ToolTypeEnum.BuiltIn].includes(activeTab) | const isSupportGroupView = [ToolTypeEnum.All, ToolTypeEnum.BuiltIn].includes(activeTab) | ||||
| const isShowRAGRecommendations = isInRAGPipeline && activeTab === ToolTypeEnum.All && !searchText | |||||
| return ( | return ( | ||||
| <div className={cn('min-w-[400px] max-w-[500px]', className)}> | <div className={cn('min-w-[400px] max-w-[500px]', className)}> | ||||
| <div className='flex items-center justify-between border-b border-divider-subtle px-3'> | <div className='flex items-center justify-between border-b border-divider-subtle px-3'> | ||||
| className='max-h-[464px] overflow-y-auto' | className='max-h-[464px] overflow-y-auto' | ||||
| onScroll={pluginRef.current?.handleScroll} | onScroll={pluginRef.current?.handleScroll} | ||||
| > | > | ||||
| {isShowRAGRecommendations && ( | |||||
| <RAGToolSuggestions | |||||
| tools={[]} | |||||
| viewType={isSupportGroupView ? activeView : ViewType.flat} | |||||
| onSelect={onSelect} | |||||
| onTagsChange={onTagsChange} | |||||
| /> | |||||
| )} | |||||
| <Tools | <Tools | ||||
| className={toolContentClassName} | className={toolContentClassName} | ||||
| tools={tools} | tools={tools} | ||||
| hasSearchText={!!searchText} | hasSearchText={!!searchText} | ||||
| selectedTools={selectedTools} | selectedTools={selectedTools} | ||||
| canChooseMCPTool={canChooseMCPTool} | canChooseMCPTool={canChooseMCPTool} | ||||
| isShowRAGRecommendations={isShowRAGRecommendations} | |||||
| /> | /> | ||||
| {/* Plugins from marketplace */} | {/* Plugins from marketplace */} | ||||
| {enable_marketplace && <PluginList | |||||
| ref={pluginRef} | |||||
| wrapElemRef={wrapElemRef} | |||||
| list={notInstalledPlugins} | |||||
| searchText={searchText} | |||||
| toolContentClassName={toolContentClassName} | |||||
| tags={tags} | |||||
| />} | |||||
| {enable_marketplace && ( | |||||
| <PluginList | |||||
| ref={pluginRef} | |||||
| wrapElemRef={wrapElemRef} | |||||
| list={notInstalledPlugins} | |||||
| searchText={searchText} | |||||
| toolContentClassName={toolContentClassName} | |||||
| tags={tags} | |||||
| /> | |||||
| )} | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ) | ) |
| noBlocks={noBlocks} | noBlocks={noBlocks} | ||||
| dataSources={dataSources} | dataSources={dataSources} | ||||
| noTools={noTools} | noTools={noTools} | ||||
| onTagsChange={setTags} | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| </PortalToFollowElemContent> | </PortalToFollowElemContent> |
| import type { Dispatch, SetStateAction } from 'react' | |||||
| import React, { useCallback } from 'react' | |||||
| import { useTranslation } from 'react-i18next' | |||||
| import type { OnSelectBlock, ToolWithProvider } from '../types' | |||||
| // import Tools from './tools' | |||||
| // import { ToolTypeEnum } from './types' | |||||
| import type { ViewType } from './view-type-select' | |||||
| import { RiMoreLine } from '@remixicon/react' | |||||
| type RAGToolSuggestionsProps = { | |||||
| tools: ToolWithProvider[] | |||||
| viewType: ViewType | |||||
| onSelect: OnSelectBlock | |||||
| onTagsChange: Dispatch<SetStateAction<string[]>> | |||||
| } | |||||
| const RAGToolSuggestions: React.FC<RAGToolSuggestionsProps> = ({ | |||||
| // tools, | |||||
| // viewType, | |||||
| // onSelect, | |||||
| onTagsChange, | |||||
| }) => { | |||||
| const { t } = useTranslation() | |||||
| const loadMore = useCallback(() => { | |||||
| onTagsChange(prev => [...prev, 'rag']) | |||||
| }, [onTagsChange]) | |||||
| return ( | |||||
| <div className='flex flex-col p-1'> | |||||
| <div className='system-xs-medium px-3 pb-0.5 pt-1 text-text-tertiary'> | |||||
| {t('pipeline.ragToolSuggestions.title')} | |||||
| </div> | |||||
| {/* <Tools | |||||
| className='p-0' | |||||
| tools={tools} | |||||
| onSelect={onSelect} | |||||
| canNotSelectMultiple | |||||
| toolType={ToolTypeEnum.All} | |||||
| viewType={viewType} | |||||
| hasSearchText={false} | |||||
| /> */} | |||||
| <div | |||||
| className='flex cursor-pointer items-center gap-x-2 py-1 pl-3 pr-2' | |||||
| onClick={loadMore} | |||||
| > | |||||
| <div className='px-1'> | |||||
| <RiMoreLine className='size-4 text-text-tertiary' /> | |||||
| </div> | |||||
| <div className='system-xs-regular text-text-tertiary'> | |||||
| {t('common.operation.more')} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| ) | |||||
| } | |||||
| export default React.memo(RAGToolSuggestions) |
| import type { FC } from 'react' | |||||
| import type { Dispatch, FC, SetStateAction } from 'react' | |||||
| import { memo } from 'react' | import { memo } from 'react' | ||||
| import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools' | import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools' | ||||
| import type { | import type { | ||||
| onActiveTabChange: (activeTab: TabsEnum) => void | onActiveTabChange: (activeTab: TabsEnum) => void | ||||
| searchText: string | searchText: string | ||||
| tags: string[] | tags: string[] | ||||
| onTagsChange: Dispatch<SetStateAction<string[]>> | |||||
| onSelect: OnSelectBlock | onSelect: OnSelectBlock | ||||
| availableBlocksTypes?: BlockEnum[] | availableBlocksTypes?: BlockEnum[] | ||||
| blocks: NodeDefault[] | blocks: NodeDefault[] | ||||
| activeTab, | activeTab, | ||||
| onActiveTabChange, | onActiveTabChange, | ||||
| tags, | tags, | ||||
| onTagsChange, | |||||
| searchText, | searchText, | ||||
| onSelect, | onSelect, | ||||
| availableBlocksTypes, | availableBlocksTypes, | ||||
| workflowTools={workflowTools || []} | workflowTools={workflowTools || []} | ||||
| mcpTools={mcpTools || []} | mcpTools={mcpTools || []} | ||||
| canChooseMCPTool | canChooseMCPTool | ||||
| onTagsChange={onTagsChange} | |||||
| isInRAGPipeline={dataSources.length > 0} | |||||
| /> | /> | ||||
| ) | ) | ||||
| } | } |
| indexBarClassName?: string | indexBarClassName?: string | ||||
| selectedTools?: ToolValue[] | selectedTools?: ToolValue[] | ||||
| canChooseMCPTool?: boolean | canChooseMCPTool?: boolean | ||||
| isShowRAGRecommendations?: boolean | |||||
| } | } | ||||
| const Blocks = ({ | const Blocks = ({ | ||||
| onSelect, | onSelect, | ||||
| indexBarClassName, | indexBarClassName, | ||||
| selectedTools, | selectedTools, | ||||
| canChooseMCPTool, | canChooseMCPTool, | ||||
| isShowRAGRecommendations = false, | |||||
| }: ToolsProps) => { | }: ToolsProps) => { | ||||
| // const tools: any = [] | // const tools: any = [] | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| } | } | ||||
| {!tools.length && !hasSearchText && ( | {!tools.length && !hasSearchText && ( | ||||
| <div className='py-10'> | <div className='py-10'> | ||||
| <Empty type={toolType!} isAgent={isAgent}/> | |||||
| <Empty type={toolType!} isAgent={isAgent} /> | |||||
| </div> | |||||
| )} | |||||
| {!!tools.length && isShowRAGRecommendations && ( | |||||
| <div className='system-xs-medium px-3 pb-0.5 pt-1 text-text-tertiary'> | |||||
| {t('tools.allTools')} | |||||
| </div> | </div> | ||||
| )} | )} | ||||
| {!!tools.length && ( | {!!tools.length && ( |
| footerTip: 'In test run mode, preview up to {{count}} chunks', | footerTip: 'In test run mode, preview up to {{count}} chunks', | ||||
| }, | }, | ||||
| }, | }, | ||||
| ragToolSuggestions: { | |||||
| title: 'Suggestions for RAG', | |||||
| }, | |||||
| } | } | ||||
| export default translation | export default translation |
| publishTip: 'App not published. Please publish the app first.', | publishTip: 'App not published. Please publish the app first.', | ||||
| }, | }, | ||||
| }, | }, | ||||
| allTools: 'All tools', | |||||
| } | } | ||||
| export default translation | export default translation |
| footerTip: '在测试运行模式下,最多预览 {{count}} 个分段', | footerTip: '在测试运行模式下,最多预览 {{count}} 个分段', | ||||
| }, | }, | ||||
| }, | }, | ||||
| ragToolSuggestions: { | |||||
| title: 'RAG 工具推荐', | |||||
| }, | |||||
| } | } | ||||
| export default translation | export default translation |
| publishTip: '应用未发布。请先发布应用。', | publishTip: '应用未发布。请先发布应用。', | ||||
| }, | }, | ||||
| }, | }, | ||||
| allTools: '全部工具', | |||||
| } | } | ||||
| export default translation | export default translation |