merge main

This commit is contained in:
zxhlyh
2025-10-14 10:26:12 +08:00
178 changed files with 7680 additions and 2960 deletions

View File

@ -1,10 +1,9 @@
import {
useCallback,
useEffect,
useMemo,
useRef,
} from 'react'
import Link from 'next/link'
import { useTranslation } from 'react-i18next'
import { RiArrowRightUpLine } from '@remixicon/react'
import { BlockEnum } from '../types'
import type {
OnSelectBlock,
@ -14,10 +13,12 @@ import type { DataSourceDefaultValue, ToolDefaultValue } from './types'
import Tools from './tools'
import { ViewType } from './view-type-select'
import cn from '@/utils/classnames'
import type { ListRef } from '@/app/components/workflow/block-selector/market-place-plugin/list'
import { getMarketplaceUrl } from '@/utils/var'
import PluginList, { type ListRef } from '@/app/components/workflow/block-selector/market-place-plugin/list'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { DEFAULT_FILE_EXTENSIONS_IN_LOCAL_FILE_DATA_SOURCE } from './constants'
import { useMarketplacePlugins } from '../../plugins/marketplace/hooks'
import { PluginType } from '../../plugins/types'
import { useGetLanguage } from '@/context/i18n'
type AllToolsProps = {
className?: string
@ -34,9 +35,26 @@ const DataSources = ({
onSelect,
dataSources,
}: AllToolsProps) => {
const { t } = useTranslation()
const language = useGetLanguage()
const pluginRef = useRef<ListRef>(null)
const wrapElemRef = useRef<HTMLDivElement>(null)
const isMatchingKeywords = (text: string, keywords: string) => {
return text.toLowerCase().includes(keywords.toLowerCase())
}
const filteredDatasources = useMemo(() => {
const hasFilter = searchText
if (!hasFilter)
return dataSources.filter(toolWithProvider => toolWithProvider.tools.length > 0)
return dataSources.filter((toolWithProvider) => {
return isMatchingKeywords(toolWithProvider.name, searchText) || toolWithProvider.tools.some((tool) => {
return tool.label[language].toLowerCase().includes(searchText.toLowerCase()) || tool.name.toLowerCase().includes(searchText.toLowerCase())
})
})
}, [searchText, dataSources, language])
const handleSelect = useCallback((_: any, toolDefaultValue: ToolDefaultValue) => {
let defaultValue: DataSourceDefaultValue = {
plugin_id: toolDefaultValue?.provider_id,
@ -55,8 +73,24 @@ const DataSources = ({
}
onSelect(BlockEnum.DataSource, toolDefaultValue && defaultValue)
}, [onSelect])
const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures)
const {
queryPluginsWithDebounced: fetchPlugins,
plugins: notInstalledPlugins = [],
} = useMarketplacePlugins()
useEffect(() => {
if (!enable_marketplace) return
if (searchText) {
fetchPlugins({
query: searchText,
category: PluginType.datasource,
})
}
}, [searchText, enable_marketplace])
return (
<div className={cn(className)}>
<div
@ -66,24 +100,23 @@ const DataSources = ({
>
<Tools
className={toolContentClassName}
tools={dataSources}
tools={filteredDatasources}
onSelect={handleSelect as OnSelectBlock}
viewType={ViewType.flat}
hasSearchText={!!searchText}
canNotSelectMultiple
/>
{
enable_marketplace && (
<Link
className='system-sm-medium sticky bottom-0 z-10 flex h-8 cursor-pointer items-center rounded-b-lg border-[0.5px] border-t border-components-panel-border bg-components-panel-bg-blur px-4 py-1 text-text-accent-light-mode-only shadow-lg'
href={getMarketplaceUrl('')}
target='_blank'
>
<span>{t('plugin.findMoreInMarketplace')}</span>
<RiArrowRightUpLine className='ml-0.5 h-3 w-3' />
</Link>
)
}
{/* Plugins from marketplace */}
{enable_marketplace && (
<PluginList
ref={pluginRef}
wrapElemRef={wrapElemRef}
list={notInstalledPlugins}
tags={[]}
searchText={searchText}
toolContentClassName={toolContentClassName}
/>
)}
</div>
</div>
)

View File

@ -0,0 +1,94 @@
import type { ComponentType } from 'react'
import { BlockEnum } from '../types'
import StartNode from './start/node'
import StartPanel from './start/panel'
import EndNode from './end/node'
import EndPanel from './end/panel'
import AnswerNode from './answer/node'
import AnswerPanel from './answer/panel'
import LLMNode from './llm/node'
import LLMPanel from './llm/panel'
import KnowledgeRetrievalNode from './knowledge-retrieval/node'
import KnowledgeRetrievalPanel from './knowledge-retrieval/panel'
import QuestionClassifierNode from './question-classifier/node'
import QuestionClassifierPanel from './question-classifier/panel'
import IfElseNode from './if-else/node'
import IfElsePanel from './if-else/panel'
import CodeNode from './code/node'
import CodePanel from './code/panel'
import TemplateTransformNode from './template-transform/node'
import TemplateTransformPanel from './template-transform/panel'
import HttpNode from './http/node'
import HttpPanel from './http/panel'
import ToolNode from './tool/node'
import ToolPanel from './tool/panel'
import VariableAssignerNode from './variable-assigner/node'
import VariableAssignerPanel from './variable-assigner/panel'
import AssignerNode from './assigner/node'
import AssignerPanel from './assigner/panel'
import ParameterExtractorNode from './parameter-extractor/node'
import ParameterExtractorPanel from './parameter-extractor/panel'
import IterationNode from './iteration/node'
import IterationPanel from './iteration/panel'
import LoopNode from './loop/node'
import LoopPanel from './loop/panel'
import DocExtractorNode from './document-extractor/node'
import DocExtractorPanel from './document-extractor/panel'
import ListFilterNode from './list-operator/node'
import ListFilterPanel from './list-operator/panel'
import AgentNode from './agent/node'
import AgentPanel from './agent/panel'
import DataSourceNode from './data-source/node'
import DataSourcePanel from './data-source/panel'
import KnowledgeBaseNode from './knowledge-base/node'
import KnowledgeBasePanel from './knowledge-base/panel'
export const NodeComponentMap: Record<string, ComponentType<any>> = {
[BlockEnum.Start]: StartNode,
[BlockEnum.End]: EndNode,
[BlockEnum.Answer]: AnswerNode,
[BlockEnum.LLM]: LLMNode,
[BlockEnum.KnowledgeRetrieval]: KnowledgeRetrievalNode,
[BlockEnum.QuestionClassifier]: QuestionClassifierNode,
[BlockEnum.IfElse]: IfElseNode,
[BlockEnum.Code]: CodeNode,
[BlockEnum.TemplateTransform]: TemplateTransformNode,
[BlockEnum.HttpRequest]: HttpNode,
[BlockEnum.Tool]: ToolNode,
[BlockEnum.VariableAssigner]: VariableAssignerNode,
[BlockEnum.Assigner]: AssignerNode,
[BlockEnum.VariableAggregator]: VariableAssignerNode,
[BlockEnum.ParameterExtractor]: ParameterExtractorNode,
[BlockEnum.Iteration]: IterationNode,
[BlockEnum.Loop]: LoopNode,
[BlockEnum.DocExtractor]: DocExtractorNode,
[BlockEnum.ListFilter]: ListFilterNode,
[BlockEnum.Agent]: AgentNode,
[BlockEnum.DataSource]: DataSourceNode,
[BlockEnum.KnowledgeBase]: KnowledgeBaseNode,
}
export const PanelComponentMap: Record<string, ComponentType<any>> = {
[BlockEnum.Start]: StartPanel,
[BlockEnum.End]: EndPanel,
[BlockEnum.Answer]: AnswerPanel,
[BlockEnum.LLM]: LLMPanel,
[BlockEnum.KnowledgeRetrieval]: KnowledgeRetrievalPanel,
[BlockEnum.QuestionClassifier]: QuestionClassifierPanel,
[BlockEnum.IfElse]: IfElsePanel,
[BlockEnum.Code]: CodePanel,
[BlockEnum.TemplateTransform]: TemplateTransformPanel,
[BlockEnum.HttpRequest]: HttpPanel,
[BlockEnum.Tool]: ToolPanel,
[BlockEnum.VariableAssigner]: VariableAssignerPanel,
[BlockEnum.VariableAggregator]: VariableAssignerPanel,
[BlockEnum.Assigner]: AssignerPanel,
[BlockEnum.ParameterExtractor]: ParameterExtractorPanel,
[BlockEnum.Iteration]: IterationPanel,
[BlockEnum.Loop]: LoopPanel,
[BlockEnum.DocExtractor]: DocExtractorPanel,
[BlockEnum.ListFilter]: ListFilterPanel,
[BlockEnum.Agent]: AgentPanel,
[BlockEnum.DataSource]: DataSourcePanel,
[BlockEnum.KnowledgeBase]: KnowledgeBasePanel,
}

View File

@ -1,101 +1,5 @@
import type { ComponentType } from 'react'
import { BlockEnum } from '../types'
import StartNode from './start/node'
import StartPanel from './start/panel'
import EndNode from './end/node'
import EndPanel from './end/panel'
import AnswerNode from './answer/node'
import AnswerPanel from './answer/panel'
import LLMNode from './llm/node'
import LLMPanel from './llm/panel'
import KnowledgeRetrievalNode from './knowledge-retrieval/node'
import KnowledgeRetrievalPanel from './knowledge-retrieval/panel'
import QuestionClassifierNode from './question-classifier/node'
import QuestionClassifierPanel from './question-classifier/panel'
import IfElseNode from './if-else/node'
import IfElsePanel from './if-else/panel'
import CodeNode from './code/node'
import CodePanel from './code/panel'
import TemplateTransformNode from './template-transform/node'
import TemplateTransformPanel from './template-transform/panel'
import HttpNode from './http/node'
import HttpPanel from './http/panel'
import ToolNode from './tool/node'
import ToolPanel from './tool/panel'
import VariableAssignerNode from './variable-assigner/node'
import VariableAssignerPanel from './variable-assigner/panel'
import AssignerNode from './assigner/node'
import AssignerPanel from './assigner/panel'
import ParameterExtractorNode from './parameter-extractor/node'
import ParameterExtractorPanel from './parameter-extractor/panel'
import IterationNode from './iteration/node'
import IterationPanel from './iteration/panel'
import LoopNode from './loop/node'
import LoopPanel from './loop/panel'
import DocExtractorNode from './document-extractor/node'
import DocExtractorPanel from './document-extractor/panel'
import ListFilterNode from './list-operator/node'
import ListFilterPanel from './list-operator/panel'
import AgentNode from './agent/node'
import AgentPanel from './agent/panel'
import DataSourceNode from './data-source/node'
import DataSourcePanel from './data-source/panel'
import KnowledgeBaseNode from './knowledge-base/node'
import KnowledgeBasePanel from './knowledge-base/panel'
import { TransferMethod } from '@/types/app'
export const NodeComponentMap: Record<string, ComponentType<any>> = {
[BlockEnum.Start]: StartNode,
[BlockEnum.End]: EndNode,
[BlockEnum.Answer]: AnswerNode,
[BlockEnum.LLM]: LLMNode,
[BlockEnum.KnowledgeRetrieval]: KnowledgeRetrievalNode,
[BlockEnum.QuestionClassifier]: QuestionClassifierNode,
[BlockEnum.IfElse]: IfElseNode,
[BlockEnum.Code]: CodeNode,
[BlockEnum.TemplateTransform]: TemplateTransformNode,
[BlockEnum.HttpRequest]: HttpNode,
[BlockEnum.Tool]: ToolNode,
[BlockEnum.VariableAssigner]: VariableAssignerNode,
[BlockEnum.Assigner]: AssignerNode,
[BlockEnum.VariableAggregator]: VariableAssignerNode,
[BlockEnum.ParameterExtractor]: ParameterExtractorNode,
[BlockEnum.Iteration]: IterationNode,
[BlockEnum.Loop]: LoopNode,
[BlockEnum.DocExtractor]: DocExtractorNode,
[BlockEnum.ListFilter]: ListFilterNode,
[BlockEnum.Agent]: AgentNode,
[BlockEnum.DataSource]: DataSourceNode,
[BlockEnum.KnowledgeBase]: KnowledgeBaseNode,
}
export const PanelComponentMap: Record<string, ComponentType<any>> = {
[BlockEnum.Start]: StartPanel,
[BlockEnum.End]: EndPanel,
[BlockEnum.Answer]: AnswerPanel,
[BlockEnum.LLM]: LLMPanel,
[BlockEnum.KnowledgeRetrieval]: KnowledgeRetrievalPanel,
[BlockEnum.QuestionClassifier]: QuestionClassifierPanel,
[BlockEnum.IfElse]: IfElsePanel,
[BlockEnum.Code]: CodePanel,
[BlockEnum.TemplateTransform]: TemplateTransformPanel,
[BlockEnum.HttpRequest]: HttpPanel,
[BlockEnum.Tool]: ToolPanel,
[BlockEnum.VariableAssigner]: VariableAssignerPanel,
[BlockEnum.VariableAggregator]: VariableAssignerPanel,
[BlockEnum.Assigner]: AssignerPanel,
[BlockEnum.ParameterExtractor]: ParameterExtractorPanel,
[BlockEnum.Iteration]: IterationPanel,
[BlockEnum.Loop]: LoopPanel,
[BlockEnum.DocExtractor]: DocExtractorPanel,
[BlockEnum.ListFilter]: ListFilterPanel,
[BlockEnum.Agent]: AgentPanel,
[BlockEnum.DataSource]: DataSourcePanel,
[BlockEnum.KnowledgeBase]: KnowledgeBasePanel,
}
export const CUSTOM_NODE_TYPE = 'custom'
export const FILE_TYPE_OPTIONS = [
{ value: 'image', i18nKey: 'image' },
{ value: 'document', i18nKey: 'doc' },

View File

@ -8,7 +8,7 @@ import { CUSTOM_NODE } from '../constants'
import {
NodeComponentMap,
PanelComponentMap,
} from './constants'
} from './components'
import BaseNode from './_base/node'
import BasePanel from './_base/components/workflow-panel'

View File

@ -29,7 +29,7 @@ const ChunkStructure = ({
<Field
fieldTitleProps={{
title: t('workflow.nodes.knowledgeBase.chunkStructure'),
tooltip: t('workflow.nodes.knowledgeBase.chunkStructure'),
tooltip: t('workflow.nodes.knowledgeBase.chunkStructureTip.message'),
operation: chunkStructure && (
<Selector
options={options}