Merge remote-tracking branch 'origin/main' into feat/trigger

This commit is contained in:
lyzno1
2025-10-28 11:28:06 +08:00
191 changed files with 9019 additions and 2546 deletions

View File

@ -72,7 +72,7 @@ export const isSystemVar = (valueSelector: ValueSelector) => {
export const isGlobalVar = (valueSelector: ValueSelector) => {
if(!isSystemVar(valueSelector)) return false
const second = valueSelector[1]
// eslint-disable-next-line sonarjs/prefer-single-boolean-return
if(['query', 'files'].includes(second))
return false
return true

View File

@ -79,6 +79,7 @@ import LastRun from './last-run'
import useLastRun from './last-run/use-last-run'
import { TriggerSubscription } from './trigger-subscription'
import { ReadmeEntrance } from '@/app/components/plugins/readme-panel/entrance'
import { useAllBuiltInTools } from '@/service/use-tools'
const getCustomRunForm = (params: CustomRunFormProps): React.JSX.Element => {
const nodeType = params.payload.type
@ -284,12 +285,14 @@ const BasePanel: FC<BasePanelProps> = ({
return {}
})()
const buildInTools = useStore(s => s.buildInTools)
const storeBuildInTools = useStore(s => s.buildInTools)
const { data: buildInTools } = useAllBuiltInTools()
const currToolCollection = useMemo(() => {
return buildInTools.find(item => canFindTool(item.id, data.provider_id))
}, [buildInTools, data.provider_id])
const candidates = buildInTools ?? storeBuildInTools
return candidates?.find(item => canFindTool(item.id, data.provider_id))
}, [buildInTools, storeBuildInTools, data.provider_id])
const needsToolAuth = useMemo(() => {
return (data.type === BlockEnum.Tool && currToolCollection?.allow_delete)
return data.type === BlockEnum.Tool && currToolCollection?.allow_delete
}, [data.type, currToolCollection?.allow_delete])
const { data: triggerProviders = [] } = useAllTriggerPlugins()
@ -492,6 +495,7 @@ const BasePanel: FC<BasePanelProps> = ({
className='px-4 pb-2'
pluginPayload={{
provider: currToolCollection?.name || '',
providerType: currToolCollection?.type || '',
category: AuthCategory.tool,
detail: currToolCollection as any,
}}
@ -504,6 +508,7 @@ const BasePanel: FC<BasePanelProps> = ({
<AuthorizedInNode
pluginPayload={{
provider: currToolCollection?.name || '',
providerType: currToolCollection?.type || '',
category: AuthCategory.tool,
detail: currToolCollection as any,
}}

View File

@ -62,6 +62,13 @@ import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars
import type { FlowType } from '@/types/common'
import useMatchSchemaType from '../components/variable/use-match-schema-type'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllMCPTools,
useAllWorkflowTools,
} from '@/service/use-tools'
// eslint-disable-next-line ts/no-unsafe-function-type
const checkValidFns: Record<BlockEnum, Function> = {
[BlockEnum.LLM]: checkLLMValid,
@ -142,21 +149,23 @@ const useOneStepRun = <T>({
const availableNodesIncludeParent = getBeforeNodesInSameBranchIncludeParent(id)
const workflowStore = useWorkflowStore()
const { schemaTypeDefinitions } = useMatchSchemaType()
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const { data: mcpTools } = useAllMCPTools()
const getVar = (valueSelector: ValueSelector): Var | undefined => {
const isSystem = valueSelector[0] === 'sys'
const {
buildInTools,
customTools,
workflowTools,
mcpTools,
dataSourceList,
} = workflowStore.getState()
const allPluginInfoList = {
buildInTools,
customTools,
workflowTools,
mcpTools,
dataSourceList: dataSourceList ?? [],
buildInTools: buildInTools || [],
customTools: customTools || [],
workflowTools: workflowTools || [],
mcpTools: mcpTools || [],
dataSourceList: dataSourceList || [],
}
const allOutputVars = toNodeOutputVars(availableNodes, isChatMode, undefined, undefined, conversationVariables, [], allPluginInfoList, schemaTypeDefinitions)

View File

@ -42,6 +42,12 @@ import BoolValue from '@/app/components/workflow/panel/chat-variable-panel/compo
import { getVarType } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { useIsChatMode } from '@/app/components/workflow/hooks/use-workflow'
import useMatchSchemaType from '../../../_base/components/variable/use-match-schema-type'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllMCPTools,
useAllWorkflowTools,
} from '@/service/use-tools'
const optionNameI18NPrefix = 'workflow.nodes.ifElse.optionName'
type ConditionItemProps = {
@ -91,15 +97,12 @@ const ConditionItem = ({
const [isHovered, setIsHovered] = useState(false)
const [open, setOpen] = useState(false)
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const { data: mcpTools } = useAllMCPTools()
const workflowStore = useWorkflowStore()
const {
setControlPromptEditorRerenderKey,
buildInTools,
customTools,
mcpTools,
workflowTools,
dataSourceList,
} = workflowStore.getState()
const doUpdateCondition = useCallback((newCondition: Condition) => {
if (isSubVariableKey)
@ -213,6 +216,8 @@ const ConditionItem = ({
const handleVarChange = useCallback((valueSelector: ValueSelector, _varItem: Var) => {
const {
conversationVariables,
setControlPromptEditorRerenderKey,
dataSourceList,
} = workflowStore.getState()
const resolvedVarType = getVarType({
valueSelector,
@ -220,11 +225,11 @@ const ConditionItem = ({
availableNodes,
isChatMode,
allPluginInfoList: {
buildInTools,
customTools,
mcpTools,
workflowTools,
dataSourceList: dataSourceList ?? [],
buildInTools: buildInTools || [],
customTools: customTools || [],
mcpTools: mcpTools || [],
workflowTools: workflowTools || [],
dataSourceList: dataSourceList || [],
},
schemaTypeDefinitions,
})
@ -241,12 +246,12 @@ const ConditionItem = ({
})
doUpdateCondition(newCondition)
setOpen(false)
}, [condition, doUpdateCondition, availableNodes, isChatMode, setControlPromptEditorRerenderKey, schemaTypeDefinitions])
}, [condition, doUpdateCondition, availableNodes, isChatMode, schemaTypeDefinitions, buildInTools, customTools, mcpTools, workflowTools])
const showBooleanInput = useMemo(() => {
if(condition.varType === VarType.boolean)
return true
// eslint-disable-next-line sonarjs/prefer-single-boolean-return
if(condition.varType === VarType.arrayBoolean && [ComparisonOperator.contains, ComparisonOperator.notContains].includes(condition.comparison_operator!))
return true
return false

View File

@ -22,6 +22,7 @@ const nodeDefault: NodeDefault<IterationNodeType> = {
is_parallel: false,
parallel_nums: 10,
error_handle_mode: ErrorHandleMode.Terminated,
flatten_output: true,
},
checkValid(payload: IterationNodeType, t: any) {
let errorMessages = ''

View File

@ -46,6 +46,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
changeParallel,
changeErrorResponseMode,
changeParallelNums,
changeFlattenOutput,
} = useConfig(id, data)
return (
@ -117,6 +118,18 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
<Select items={responseMethod} defaultValue={inputs.error_handle_mode} onSelect={changeErrorResponseMode} allowSearch={false} />
</Field>
</div>
<Split />
<div className='px-4 py-2'>
<Field
title={t(`${i18nPrefix}.flattenOutput`)}
tooltip={<div className='w-[230px]'>{t(`${i18nPrefix}.flattenOutputDesc`)}</div>}
inline
>
<Switch defaultValue={inputs.flatten_output} onChange={changeFlattenOutput} />
</Field>
</div>
</div>
)
}

View File

@ -17,5 +17,6 @@ export type IterationNodeType = CommonNodeType & {
is_parallel: boolean // open the parallel mode or not
parallel_nums: number // the numbers of parallel
error_handle_mode: ErrorHandleMode // how to handle error in the iteration
flatten_output: boolean // whether to flatten the output array if all elements are lists
_isShowTips: boolean // when answer node in parallel mode iteration show tips
}

View File

@ -15,6 +15,12 @@ import type { Item } from '@/app/components/base/select'
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
import { isEqual } from 'lodash-es'
import { useStore } from '../../store'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllMCPTools,
useAllWorkflowTools,
} from '@/service/use-tools'
const useConfig = (id: string, payload: IterationNodeType) => {
const {
@ -40,17 +46,17 @@ const useConfig = (id: string, payload: IterationNodeType) => {
// output
const { getIterationNodeChildren } = useWorkflow()
const iterationChildrenNodes = getIterationNodeChildren(id)
const buildInTools = useStore(s => s.buildInTools)
const customTools = useStore(s => s.customTools)
const workflowTools = useStore(s => s.workflowTools)
const mcpTools = useStore(s => s.mcpTools)
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const { data: mcpTools } = useAllMCPTools()
const dataSourceList = useStore(s => s.dataSourceList)
const allPluginInfoList = {
buildInTools,
customTools,
workflowTools,
mcpTools,
dataSourceList: dataSourceList ?? [],
buildInTools: buildInTools || [],
customTools: customTools || [],
workflowTools: workflowTools || [],
mcpTools: mcpTools || [],
dataSourceList: dataSourceList || [],
}
const childrenNodeVars = toNodeOutputVars(iterationChildrenNodes, isChatMode, undefined, [], [], [], allPluginInfoList)
@ -98,6 +104,14 @@ const useConfig = (id: string, payload: IterationNodeType) => {
})
setInputs(newInputs)
}, [inputs, setInputs])
const changeFlattenOutput = useCallback((value: boolean) => {
const newInputs = produce(inputs, (draft) => {
draft.flatten_output = value
})
setInputs(newInputs)
}, [inputs, setInputs])
return {
readOnly,
inputs,
@ -109,6 +123,7 @@ const useConfig = (id: string, payload: IterationNodeType) => {
changeParallel,
changeErrorResponseMode,
changeParallelNums,
changeFlattenOutput,
}
}

View File

@ -15,9 +15,24 @@ import useNodeCrud from '../_base/hooks/use-node-crud'
import { toNodeOutputVars } from '../_base/components/variable/utils'
import { getOperators } from './utils'
import { LogicalOperator } from './types'
import type { HandleAddCondition, HandleAddSubVariableCondition, HandleRemoveCondition, HandleToggleConditionLogicalOperator, HandleToggleSubVariableConditionLogicalOperator, HandleUpdateCondition, HandleUpdateSubVariableCondition, LoopNodeType } from './types'
import type {
HandleAddCondition,
HandleAddSubVariableCondition,
HandleRemoveCondition,
HandleToggleConditionLogicalOperator,
HandleToggleSubVariableConditionLogicalOperator,
HandleUpdateCondition,
HandleUpdateSubVariableCondition,
LoopNodeType,
} from './types'
import useIsVarFileAttribute from './use-is-var-file-attribute'
import { useStore } from '@/app/components/workflow/store'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllMCPTools,
useAllWorkflowTools,
} from '@/service/use-tools'
const useConfig = (id: string, payload: LoopNodeType) => {
const { nodesReadOnly: readOnly } = useNodesReadOnly()
@ -38,17 +53,17 @@ const useConfig = (id: string, payload: LoopNodeType) => {
// output
const { getLoopNodeChildren } = useWorkflow()
const loopChildrenNodes = [{ id, data: payload } as any, ...getLoopNodeChildren(id)]
const buildInTools = useStore(s => s.buildInTools)
const customTools = useStore(s => s.customTools)
const workflowTools = useStore(s => s.workflowTools)
const mcpTools = useStore(s => s.mcpTools)
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const { data: mcpTools } = useAllMCPTools()
const dataSourceList = useStore(s => s.dataSourceList)
const allPluginInfoList = {
buildInTools,
customTools,
workflowTools,
mcpTools,
dataSourceList: dataSourceList ?? [],
buildInTools: buildInTools || [],
customTools: customTools || [],
workflowTools: workflowTools || [],
mcpTools: mcpTools || [],
dataSourceList: dataSourceList || [],
}
const childrenNodeVars = toNodeOutputVars(loopChildrenNodes, isChatMode, undefined, [], conversationVariables, [], allPluginInfoList)

View File

@ -8,7 +8,6 @@ import { useTranslation } from 'react-i18next'
import BlockSelector from '../../../../block-selector'
import type { Param, ParamType } from '../../types'
import cn from '@/utils/classnames'
import { useStore } from '@/app/components/workflow/store'
import type {
PluginDefaultValue,
ToolDefaultValue,
@ -18,6 +17,11 @@ import { CollectionType } from '@/app/components/tools/types'
import type { BlockEnum } from '@/app/components/workflow/types'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { canFindTool } from '@/utils'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllWorkflowTools,
} from '@/service/use-tools'
const i18nPrefix = 'workflow.nodes.parameterExtractor'
@ -42,9 +46,9 @@ const ImportFromTool: FC<Props> = ({
const { t } = useTranslation()
const language = useLanguage()
const buildInTools = useStore(s => s.buildInTools)
const customTools = useStore(s => s.customTools)
const workflowTools = useStore(s => s.workflowTools)
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const handleSelectTool = useCallback((_type: BlockEnum, toolInfo?: PluginDefaultValue) => {
if (!toolInfo || 'datasource_name' in toolInfo || !('tool_name' in toolInfo))
@ -54,11 +58,11 @@ const ImportFromTool: FC<Props> = ({
const currentTools = (() => {
switch (provider_type) {
case CollectionType.builtIn:
return buildInTools
return buildInTools || []
case CollectionType.custom:
return customTools
return customTools || []
case CollectionType.workflow:
return workflowTools
return workflowTools || []
default:
return []
}

View File

@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { produce } from 'immer'
import { useBoolean } from 'ahooks'
import { useStore, useWorkflowStore } from '../../store'
import { useWorkflowStore } from '../../store'
import type { ToolNodeType, ToolVarInputs } from './types'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
@ -15,15 +15,20 @@ import {
import Toast from '@/app/components/base/toast'
import type { InputVar } from '@/app/components/workflow/types'
import {
useFetchToolsData,
useNodesReadOnly,
} from '@/app/components/workflow/hooks'
import { canFindTool } from '@/utils'
import {
useAllBuiltInTools,
useAllCustomTools,
useAllMCPTools,
useAllWorkflowTools,
useInvalidToolsByType,
} from '@/service/use-tools'
const useConfig = (id: string, payload: ToolNodeType) => {
const workflowStore = useWorkflowStore()
const { nodesReadOnly: readOnly } = useNodesReadOnly()
const { handleFetchAllTools } = useFetchToolsData()
const { t } = useTranslation()
const language = useLanguage()
@ -43,21 +48,21 @@ const useConfig = (id: string, payload: ToolNodeType) => {
tool_parameters,
} = inputs
const isBuiltIn = provider_type === CollectionType.builtIn
const buildInTools = useStore(s => s.buildInTools)
const customTools = useStore(s => s.customTools)
const workflowTools = useStore(s => s.workflowTools)
const mcpTools = useStore(s => s.mcpTools)
const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools()
const { data: mcpTools } = useAllMCPTools()
const currentTools = useMemo(() => {
switch (provider_type) {
case CollectionType.builtIn:
return buildInTools
return buildInTools || []
case CollectionType.custom:
return customTools
return customTools || []
case CollectionType.workflow:
return workflowTools
return workflowTools || []
case CollectionType.mcp:
return mcpTools
return mcpTools || []
default:
return []
}
@ -75,6 +80,7 @@ const useConfig = (id: string, payload: ToolNodeType) => {
{ setTrue: showSetAuthModal, setFalse: hideSetAuthModal },
] = useBoolean(false)
const invalidToolsByType = useInvalidToolsByType(provider_type)
const handleSaveAuth = useCallback(
async (value: any) => {
await updateBuiltInToolCredential(currCollection?.name as string, value)
@ -83,14 +89,14 @@ const useConfig = (id: string, payload: ToolNodeType) => {
type: 'success',
message: t('common.api.actionSuccess'),
})
handleFetchAllTools(provider_type)
invalidToolsByType()
hideSetAuthModal()
},
[
currCollection?.name,
hideSetAuthModal,
t,
handleFetchAllTools,
invalidToolsByType,
provider_type,
],
)
@ -241,17 +247,15 @@ const useConfig = (id: string, payload: ToolNodeType) => {
name: outputKey,
type:
output.type === 'array'
? `Array[${
output.items?.type
? output.items.type.slice(0, 1).toLocaleUpperCase()
+ output.items.type.slice(1)
: 'Unknown'
? `Array[${output.items?.type
? output.items.type.slice(0, 1).toLocaleUpperCase()
+ output.items.type.slice(1)
: 'Unknown'
}]`
: `${
output.type
? output.type.slice(0, 1).toLocaleUpperCase()
+ output.type.slice(1)
: 'Unknown'
: `${output.type
? output.type.slice(0, 1).toLocaleUpperCase()
+ output.type.slice(1)
: 'Unknown'
}`,
description: output.description,
})