mirror of https://github.com/langgenius/dify.git
refactor(workflow): update output schema handling in tool and data source nodes for improved integration with plugin info
This commit is contained in:
parent
1f5fd13359
commit
bdcd9ad9cb
|
|
@ -44,7 +44,6 @@ const DataSources = ({
|
|||
datasource_name: toolDefaultValue?.tool_name,
|
||||
datasource_label: toolDefaultValue?.tool_label,
|
||||
title: toolDefaultValue?.title,
|
||||
output_schema: toolDefaultValue?.output_schema,
|
||||
})
|
||||
}, [onSelect])
|
||||
const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ const ToolItem: FC<Props> = ({
|
|||
tool_description: payload.description[language],
|
||||
title: payload.label[language],
|
||||
is_team_authorization: provider.is_team_authorization,
|
||||
output_schema: payload.output_schema,
|
||||
paramSchemas: payload.parameters,
|
||||
params,
|
||||
meta: provider.meta,
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ const Tool: FC<Props> = ({
|
|||
tool_description: tool.description[language],
|
||||
title: tool.label[language],
|
||||
is_team_authorization: payload.is_team_authorization,
|
||||
output_schema: tool.output_schema,
|
||||
paramSchemas: tool.parameters,
|
||||
params,
|
||||
}
|
||||
|
|
@ -122,7 +121,6 @@ const Tool: FC<Props> = ({
|
|||
}
|
||||
if (!hasSearchText && !isFold)
|
||||
setFold(true)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hasSearchText])
|
||||
|
||||
const FoldIcon = isFold ? RiArrowRightSLine : RiArrowDownSLine
|
||||
|
|
@ -171,7 +169,6 @@ const Tool: FC<Props> = ({
|
|||
tool_description: tool.description[language],
|
||||
title: tool.label[language],
|
||||
is_team_authorization: payload.is_team_authorization,
|
||||
output_schema: tool.output_schema,
|
||||
paramSchemas: tool.parameters,
|
||||
params,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ export type ToolDefaultValue = {
|
|||
is_team_authorization: boolean
|
||||
params: Record<string, any>
|
||||
paramSchemas: Record<string, any>[]
|
||||
output_schema: Record<string, any>
|
||||
credential_id?: string
|
||||
meta?: PluginMeta
|
||||
}
|
||||
|
|
@ -46,7 +45,6 @@ export type DataSourceDefaultValue = {
|
|||
provider_name: string
|
||||
datasource_name: string
|
||||
datasource_label: string
|
||||
output_schema?: Record<string, any>
|
||||
}
|
||||
|
||||
export type ToolValue = {
|
||||
|
|
|
|||
|
|
@ -25,9 +25,12 @@ export const transformDataSourceToTool = (dataSourceItem: DataSourceItem) => {
|
|||
description: datasource.description,
|
||||
parameters: datasource.parameters,
|
||||
labels: [],
|
||||
output_schema: datasource.output_schema || {},
|
||||
output_schema: datasource.output_schema,
|
||||
} as Tool
|
||||
}),
|
||||
credentialsSchema: dataSourceItem.declaration.credentials_schema || [],
|
||||
meta: {
|
||||
version: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ export const useWorkflowVariables = () => {
|
|||
conversationVariables,
|
||||
environmentVariables,
|
||||
ragPipelineVariables,
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList,
|
||||
} = workflowStore.getState()
|
||||
return toNodeAvailableVars({
|
||||
parentNode,
|
||||
|
|
@ -45,6 +50,13 @@ export const useWorkflowVariables = () => {
|
|||
conversationVariables: (isChatMode && !hideChatVar) ? conversationVariables : [],
|
||||
ragVariables: ragPipelineVariables,
|
||||
filterVar,
|
||||
allPluginInfoList: {
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
},
|
||||
})
|
||||
}, [t, workflowStore])
|
||||
|
||||
|
|
@ -69,6 +81,11 @@ export const useWorkflowVariables = () => {
|
|||
conversationVariables,
|
||||
environmentVariables,
|
||||
ragPipelineVariables,
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList,
|
||||
} = workflowStore.getState()
|
||||
return getVarType({
|
||||
parentNode,
|
||||
|
|
@ -81,6 +98,13 @@ export const useWorkflowVariables = () => {
|
|||
environmentVariables,
|
||||
conversationVariables,
|
||||
ragVariables: ragPipelineVariables,
|
||||
allPluginInfoList: {
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
},
|
||||
})
|
||||
}, [workflowStore])
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { OUTPUT_FILE_SUB_VARIABLES } from '../../../constants'
|
|||
import type { DocExtractorNodeType } from '../../../document-extractor/types'
|
||||
import { BlockEnum, InputVarType, VarType } from '@/app/components/workflow/types'
|
||||
import type { StartNodeType } from '@/app/components/workflow/nodes/start/types'
|
||||
import type { ConversationVariable, EnvironmentVariable, Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
|
||||
import type { ConversationVariable, EnvironmentVariable, Node, NodeOutPutVar, ToolWithProvider, ValueSelector, Var } from '@/app/components/workflow/types'
|
||||
import type { VariableAssignerNodeType } from '@/app/components/workflow/nodes/variable-assigner/types'
|
||||
import type { Field as StructField } from '@/app/components/workflow/nodes/llm/types'
|
||||
import type { RAGPipelineVariable } from '@/models/pipeline'
|
||||
|
|
@ -35,12 +35,12 @@ import {
|
|||
TEMPLATE_TRANSFORM_OUTPUT_STRUCT,
|
||||
TOOL_OUTPUT_STRUCT,
|
||||
} from '@/app/components/workflow/constants'
|
||||
import ToolNodeDefault from '@/app/components/workflow/nodes/tool/default'
|
||||
import DataSourceNodeDefault from '@/app/components/workflow/nodes/data-source/default'
|
||||
import type { DataSourceNodeType } from '@/app/components/workflow/nodes/data-source/types'
|
||||
import type { PromptItem } from '@/models/debug'
|
||||
import { VAR_REGEX } from '@/config'
|
||||
import type { AgentNodeType } from '../../../agent/types'
|
||||
import { getOutputVariableAlias } from '@/app/components/workflow/utils/tool'
|
||||
|
||||
export const isSystemVar = (valueSelector: ValueSelector) => {
|
||||
return valueSelector[0] === 'sys' || valueSelector[1] === 'sys'
|
||||
|
|
@ -229,6 +229,7 @@ const formatItem = (
|
|||
item: any,
|
||||
isChatMode: boolean,
|
||||
filterVar: (payload: Var, selector: ValueSelector) => boolean,
|
||||
allPluginInfoList: Record<string, ToolWithProvider[]>,
|
||||
ragVars?: Var[],
|
||||
): NodeOutPutVar => {
|
||||
const { id, data } = item
|
||||
|
|
@ -398,43 +399,8 @@ const formatItem = (
|
|||
}
|
||||
|
||||
case BlockEnum.Tool: {
|
||||
const {
|
||||
output_schema,
|
||||
} = data as ToolNodeType
|
||||
if (!output_schema) {
|
||||
res.vars = TOOL_OUTPUT_STRUCT
|
||||
}
|
||||
else {
|
||||
const outputSchema: any[] = []
|
||||
Object.keys(output_schema.properties).forEach((outputKey) => {
|
||||
const output = output_schema.properties[outputKey]
|
||||
const dataType = output.type
|
||||
const alias = getOutputVariableAlias(output.properties)
|
||||
let type = dataType === 'array'
|
||||
? `array[${output.items?.type.slice(0, 1).toLocaleLowerCase()}${output.items?.type.slice(1)}]`
|
||||
: `${output.type.slice(0, 1).toLocaleLowerCase()}${output.type.slice(1)}`
|
||||
|
||||
if (type === VarType.object && alias === 'file')
|
||||
type = VarType.file
|
||||
|
||||
outputSchema.push({
|
||||
variable: outputKey,
|
||||
type,
|
||||
description: output.description,
|
||||
alias,
|
||||
children: output.type === 'object' ? {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: output.properties,
|
||||
},
|
||||
} : undefined,
|
||||
})
|
||||
})
|
||||
res.vars = [
|
||||
...TOOL_OUTPUT_STRUCT,
|
||||
...outputSchema,
|
||||
]
|
||||
}
|
||||
const toolOutputVars = ToolNodeDefault.getOutputVars?.(data as ToolNodeType, allPluginInfoList) || []
|
||||
res.vars = toolOutputVars
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +495,7 @@ const formatItem = (
|
|||
|
||||
case BlockEnum.DataSource: {
|
||||
const payload = data as DataSourceNodeType
|
||||
const dataSourceVars = DataSourceNodeDefault.getOutputVars?.(payload, ragVars) || []
|
||||
const dataSourceVars = DataSourceNodeDefault.getOutputVars?.(payload, allPluginInfoList, ragVars) || []
|
||||
res.vars = dataSourceVars
|
||||
break
|
||||
}
|
||||
|
|
@ -658,6 +624,7 @@ export const toNodeOutputVars = (
|
|||
environmentVariables: EnvironmentVariable[] = [],
|
||||
conversationVariables: ConversationVariable[] = [],
|
||||
ragVariables: RAGPipelineVariable[] = [],
|
||||
allPluginInfoList: Record<string, ToolWithProvider[]>,
|
||||
): NodeOutPutVar[] => {
|
||||
// ENV_NODE data format
|
||||
const ENV_NODE = {
|
||||
|
|
@ -708,7 +675,7 @@ export const toNodeOutputVars = (
|
|||
if (node.data.type === BlockEnum.DataSource)
|
||||
ragVariablesInDataSource = ragVariables.filter(ragVariable => ragVariable.belong_to_node_id === node.id)
|
||||
return {
|
||||
...formatItem(node, isChatMode, filterVar, ragVariablesInDataSource.map(
|
||||
...formatItem(node, isChatMode, filterVar, allPluginInfoList, ragVariablesInDataSource.map(
|
||||
(ragVariable: RAGPipelineVariable) => ({
|
||||
variable: `rag.${node.id}.${ragVariable.variable}`,
|
||||
type: inputVarTypeToVarType(ragVariable.type as any),
|
||||
|
|
@ -835,6 +802,7 @@ export const getVarType = ({
|
|||
environmentVariables = [],
|
||||
conversationVariables = [],
|
||||
ragVariables = [],
|
||||
allPluginInfoList,
|
||||
}: {
|
||||
valueSelector: ValueSelector
|
||||
parentNode?: Node | null
|
||||
|
|
@ -846,6 +814,7 @@ export const getVarType = ({
|
|||
environmentVariables?: EnvironmentVariable[]
|
||||
conversationVariables?: ConversationVariable[]
|
||||
ragVariables?: RAGPipelineVariable[]
|
||||
allPluginInfoList: Record<string, ToolWithProvider[]>
|
||||
}): VarType => {
|
||||
if (isConstant)
|
||||
return VarType.string
|
||||
|
|
@ -857,6 +826,7 @@ export const getVarType = ({
|
|||
environmentVariables,
|
||||
conversationVariables,
|
||||
ragVariables,
|
||||
allPluginInfoList,
|
||||
)
|
||||
|
||||
const isIterationInnerVar = parentNode?.data.type === BlockEnum.Iteration
|
||||
|
|
@ -982,6 +952,7 @@ export const toNodeAvailableVars = ({
|
|||
conversationVariables,
|
||||
ragVariables,
|
||||
filterVar,
|
||||
allPluginInfoList,
|
||||
}: {
|
||||
parentNode?: Node | null
|
||||
t?: any
|
||||
|
|
@ -995,6 +966,7 @@ export const toNodeAvailableVars = ({
|
|||
// rag variables
|
||||
ragVariables?: RAGPipelineVariable[]
|
||||
filterVar: (payload: Var, selector: ValueSelector) => boolean
|
||||
allPluginInfoList: Record<string, ToolWithProvider[]>
|
||||
}): NodeOutPutVar[] => {
|
||||
const beforeNodesOutputVars = toNodeOutputVars(
|
||||
beforeNodes,
|
||||
|
|
@ -1003,6 +975,7 @@ export const toNodeAvailableVars = ({
|
|||
environmentVariables,
|
||||
conversationVariables,
|
||||
ragVariables,
|
||||
allPluginInfoList,
|
||||
)
|
||||
const isInIteration = parentNode?.data.type === BlockEnum.Iteration
|
||||
if (isInIteration) {
|
||||
|
|
@ -1015,6 +988,7 @@ export const toNodeAvailableVars = ({
|
|||
isChatMode,
|
||||
environmentVariables,
|
||||
conversationVariables,
|
||||
allPluginInfoList,
|
||||
})
|
||||
const itemChildren = itemType === VarType.file
|
||||
? {
|
||||
|
|
|
|||
|
|
@ -128,7 +128,19 @@ const useOneStepRun = <T>({
|
|||
|
||||
const availableNodes = getBeforeNodesInSameBranch(id)
|
||||
const availableNodesIncludeParent = getBeforeNodesInSameBranchIncludeParent(id)
|
||||
const allOutputVars = toNodeOutputVars(availableNodes, isChatMode, undefined, undefined, conversationVariables)
|
||||
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 dataSourceList = useStore(s => s.dataSourceList)
|
||||
const allPluginInfoList = {
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
}
|
||||
const allOutputVars = toNodeOutputVars(availableNodes, isChatMode, undefined, undefined, conversationVariables, [], allPluginInfoList)
|
||||
const getVar = (valueSelector: ValueSelector): Var | undefined => {
|
||||
const isSystem = valueSelector[0] === 'sys'
|
||||
const targetVar = allOutputVars.find(item => isSystem ? !!item.isStartNode : item.nodeId === valueSelector[0])
|
||||
|
|
@ -188,11 +200,11 @@ const useOneStepRun = <T>({
|
|||
const isPaused = isPausedRef.current
|
||||
|
||||
// The backend don't support pause the single run, so the frontend handle the pause state.
|
||||
if(isPaused)
|
||||
if (isPaused)
|
||||
return
|
||||
|
||||
const canRunLastRun = !isRunAfterSingleRun || runningStatus === NodeRunningStatus.Succeeded
|
||||
if(!canRunLastRun) {
|
||||
if (!canRunLastRun) {
|
||||
doSetRunResult(data)
|
||||
return
|
||||
}
|
||||
|
|
@ -202,9 +214,9 @@ const useOneStepRun = <T>({
|
|||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
appendNodeInspectVars(id, vars, nodes)
|
||||
if(data?.status === NodeRunningStatus.Succeeded) {
|
||||
if (data?.status === NodeRunningStatus.Succeeded) {
|
||||
invalidLastRun()
|
||||
if(isStartNode)
|
||||
if (isStartNode)
|
||||
invalidateSysVarValues()
|
||||
invalidateConversationVarValues() // loop, iteration, variable assigner node can update the conversation variables, but to simple the logic(some nodes may also can update in the future), all nodes refresh.
|
||||
}
|
||||
|
|
@ -221,21 +233,21 @@ const useOneStepRun = <T>({
|
|||
})
|
||||
}
|
||||
const checkValidWrap = () => {
|
||||
if(!checkValid)
|
||||
if (!checkValid)
|
||||
return { isValid: true, errorMessage: '' }
|
||||
const res = checkValid(data, t, moreDataForCheckValid)
|
||||
if(!res.isValid) {
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
data: {
|
||||
...data,
|
||||
_isSingleRun: false,
|
||||
},
|
||||
})
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: res.errorMessage,
|
||||
})
|
||||
if (!res.isValid) {
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
data: {
|
||||
...data,
|
||||
_isSingleRun: false,
|
||||
},
|
||||
})
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: res.errorMessage,
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -254,7 +266,6 @@ const useOneStepRun = <T>({
|
|||
const { isValid } = checkValidWrap()
|
||||
setCanShowSingleRun(isValid)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data._isSingleRun])
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -296,9 +307,9 @@ const useOneStepRun = <T>({
|
|||
if (!isIteration && !isLoop) {
|
||||
const isStartNode = data.type === BlockEnum.Start
|
||||
const postData: Record<string, any> = {}
|
||||
if(isStartNode) {
|
||||
if (isStartNode) {
|
||||
const { '#sys.query#': query, '#sys.files#': files, ...inputs } = submitData
|
||||
if(isChatMode)
|
||||
if (isChatMode)
|
||||
postData.conversation_id = ''
|
||||
|
||||
postData.inputs = inputs
|
||||
|
|
@ -320,7 +331,7 @@ const useOneStepRun = <T>({
|
|||
{
|
||||
onWorkflowStarted: noop,
|
||||
onWorkflowFinished: (params) => {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
@ -399,7 +410,7 @@ const useOneStepRun = <T>({
|
|||
setIterationRunResult(newIterationRunResult)
|
||||
},
|
||||
onError: () => {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
@ -423,7 +434,7 @@ const useOneStepRun = <T>({
|
|||
{
|
||||
onWorkflowStarted: noop,
|
||||
onWorkflowFinished: (params) => {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
@ -503,7 +514,7 @@ const useOneStepRun = <T>({
|
|||
setLoopRunResult(newLoopRunResult)
|
||||
},
|
||||
onError: () => {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
@ -525,7 +536,7 @@ const useOneStepRun = <T>({
|
|||
hasError = true
|
||||
invalidLastRun()
|
||||
if (!isIteration && !isLoop) {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
@ -547,11 +558,11 @@ const useOneStepRun = <T>({
|
|||
})
|
||||
}
|
||||
}
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
|
||||
if (!isIteration && !isLoop && !hasError) {
|
||||
if(isPausedRef.current)
|
||||
if (isPausedRef.current)
|
||||
return
|
||||
handleNodeDataUpdate({
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -54,15 +54,21 @@ const nodeDefault: NodeDefault<DataSourceNodeType> = {
|
|||
errorMessage,
|
||||
}
|
||||
},
|
||||
getOutputVars(payload, ragVars = []) {
|
||||
getOutputVars(payload, allPluginInfoList, ragVars = []) {
|
||||
const {
|
||||
plugin_id,
|
||||
datasource_name,
|
||||
provider_type,
|
||||
} = payload
|
||||
const isLocalFile = provider_type === DataSourceClassification.localFile
|
||||
const currentDataSource = allPluginInfoList.dataSourceList?.find((ds: any) => ds.plugin_id === plugin_id)
|
||||
const currentDataSourceItem = currentDataSource?.tools?.find((tool: any) => tool.name === datasource_name)
|
||||
const output_schema = currentDataSourceItem?.output_schema
|
||||
const dynamicOutputSchema: any[] = []
|
||||
if (payload.output_schema?.properties) {
|
||||
Object.keys(payload.output_schema.properties).forEach((outputKey) => {
|
||||
const output = payload.output_schema!.properties[outputKey]
|
||||
|
||||
if (output_schema?.properties) {
|
||||
Object.keys(output_schema.properties).forEach((outputKey) => {
|
||||
const output = output_schema.properties[outputKey]
|
||||
const dataType = output.type
|
||||
const alias = getOutputVariableAlias(output.properties)
|
||||
let type = dataType === 'array'
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export const useConfig = (id: string, dataSourceList?: any[]) => {
|
|||
|
||||
const res: any[] = []
|
||||
if (!output_schema || !output_schema.properties)
|
||||
return []
|
||||
return res
|
||||
|
||||
Object.keys(output_schema.properties).forEach((outputKey) => {
|
||||
const output = output_schema.properties[outputKey]
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@ export type DataSourceNodeType = CommonNodeType & {
|
|||
datasource_label: string
|
||||
datasource_parameters: ToolVarInputs
|
||||
datasource_configurations: Record<string, any>
|
||||
output_schema?: {
|
||||
type: string
|
||||
properties: Record<string, any>
|
||||
}
|
||||
}
|
||||
|
||||
export type CustomRunFormProps = {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@ const ConditionItem = ({
|
|||
const workflowStore = useWorkflowStore()
|
||||
const {
|
||||
setControlPromptEditorRerenderKey,
|
||||
buildInTools,
|
||||
customTools,
|
||||
mcpTools,
|
||||
workflowTools,
|
||||
dataSourceList,
|
||||
} = workflowStore.getState()
|
||||
|
||||
const doUpdateCondition = useCallback((newCondition: Condition) => {
|
||||
|
|
@ -207,6 +212,13 @@ const ConditionItem = ({
|
|||
valueSelector,
|
||||
availableNodes,
|
||||
isChatMode,
|
||||
allPluginInfoList: {
|
||||
buildInTools,
|
||||
customTools,
|
||||
mcpTools,
|
||||
workflowTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
},
|
||||
})
|
||||
|
||||
const newCondition = produce(condition, (draft) => {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import type { VarType as VarKindType } from '@/app/components/workflow/nodes/too
|
|||
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'
|
||||
|
||||
const useConfig = (id: string, payload: IterationNodeType) => {
|
||||
const {
|
||||
|
|
@ -39,7 +40,19 @@ const useConfig = (id: string, payload: IterationNodeType) => {
|
|||
// output
|
||||
const { getIterationNodeChildren } = useWorkflow()
|
||||
const iterationChildrenNodes = getIterationNodeChildren(id)
|
||||
const childrenNodeVars = toNodeOutputVars(iterationChildrenNodes, isChatMode)
|
||||
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 dataSourceList = useStore(s => s.dataSourceList)
|
||||
const allPluginInfoList = {
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
}
|
||||
const childrenNodeVars = toNodeOutputVars(iterationChildrenNodes, isChatMode, undefined, [], [], [], allPluginInfoList)
|
||||
|
||||
const handleOutputVarChange = useCallback((output: ValueSelector | string, _varKindType: VarKindType, varInfo?: Var) => {
|
||||
if (isEqual(inputs.output_selector, output as ValueSelector))
|
||||
|
|
|
|||
|
|
@ -38,7 +38,19 @@ const useConfig = (id: string, payload: LoopNodeType) => {
|
|||
// output
|
||||
const { getLoopNodeChildren } = useWorkflow()
|
||||
const loopChildrenNodes = [{ id, data: payload } as any, ...getLoopNodeChildren(id)]
|
||||
const childrenNodeVars = toNodeOutputVars(loopChildrenNodes, isChatMode, undefined, [], conversationVariables)
|
||||
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 dataSourceList = useStore(s => s.dataSourceList)
|
||||
const allPluginInfoList = {
|
||||
buildInTools,
|
||||
customTools,
|
||||
workflowTools,
|
||||
mcpTools,
|
||||
dataSourceList: dataSourceList ?? [],
|
||||
}
|
||||
const childrenNodeVars = toNodeOutputVars(loopChildrenNodes, isChatMode, undefined, [], conversationVariables, [], allPluginInfoList)
|
||||
|
||||
const {
|
||||
getIsVarFileAttribute,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { NodeDefault } from '../../types'
|
||||
import { genNodeMetaData, getOutputVariableAlias } from '@/app/components/workflow/utils'
|
||||
import { BlockEnum, VarType } from '@/app/components/workflow/types'
|
||||
import type { NodeDefault, ToolWithProvider } from '../../types'
|
||||
import type { ToolNodeType } from './types'
|
||||
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
||||
import { TOOL_OUTPUT_STRUCT } from '../../constants'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { canFindTool } from '@/utils'
|
||||
|
||||
const i18nPrefix = 'workflow.errorMsg'
|
||||
|
||||
|
|
@ -62,6 +65,65 @@ const nodeDefault: NodeDefault<ToolNodeType> = {
|
|||
errorMessage: errorMessages,
|
||||
}
|
||||
},
|
||||
getOutputVars(payload: ToolNodeType, allPluginInfoList: Record<string, ToolWithProvider[]>) {
|
||||
const { provider_id, provider_type } = payload
|
||||
let currentTools: ToolWithProvider[] = []
|
||||
switch (provider_type) {
|
||||
case CollectionType.builtIn:
|
||||
currentTools = allPluginInfoList.buildInTools ?? []
|
||||
break
|
||||
case CollectionType.custom:
|
||||
currentTools = allPluginInfoList.customTools ?? []
|
||||
break
|
||||
case CollectionType.workflow:
|
||||
currentTools = allPluginInfoList.workflowTools ?? []
|
||||
break
|
||||
case CollectionType.mcp:
|
||||
currentTools = allPluginInfoList.mcpTools ?? []
|
||||
break
|
||||
default:
|
||||
currentTools = []
|
||||
}
|
||||
const currCollection = currentTools.find(item => canFindTool(item.id, provider_id))
|
||||
const currTool = currCollection?.tools.find(tool => tool.name === payload.tool_name)
|
||||
const output_schema = currTool?.output_schema
|
||||
let res: any[] = []
|
||||
if (!output_schema) {
|
||||
res = TOOL_OUTPUT_STRUCT
|
||||
}
|
||||
else {
|
||||
const outputSchema: any[] = []
|
||||
Object.keys(output_schema.properties).forEach((outputKey) => {
|
||||
const output = output_schema.properties[outputKey]
|
||||
const dataType = output.type
|
||||
const alias = getOutputVariableAlias(output.properties)
|
||||
let type = dataType === 'array'
|
||||
? `array[${output.items?.type.slice(0, 1).toLocaleLowerCase()}${output.items?.type.slice(1)}]`
|
||||
: `${output.type.slice(0, 1).toLocaleLowerCase()}${output.type.slice(1)}`
|
||||
|
||||
if (type === VarType.object && alias === 'file')
|
||||
type = VarType.file
|
||||
|
||||
outputSchema.push({
|
||||
variable: outputKey,
|
||||
type,
|
||||
description: output.description,
|
||||
alias,
|
||||
children: output.type === 'object' ? {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: output.properties,
|
||||
},
|
||||
} : undefined,
|
||||
})
|
||||
})
|
||||
res = [
|
||||
...TOOL_OUTPUT_STRUCT,
|
||||
...outputSchema,
|
||||
]
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export default nodeDefault
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ export type ToolNodeType = CommonNodeType & {
|
|||
tool_label: string
|
||||
tool_parameters: ToolVarInputs
|
||||
tool_configurations: Record<string, any>
|
||||
output_schema: Record<string, any>
|
||||
paramSchemas?: Record<string, any>[]
|
||||
version?: string
|
||||
tool_node_version?: string
|
||||
|
|
|
|||
|
|
@ -30,9 +30,8 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
|||
/*
|
||||
* tool_configurations: tool setting, not dynamic setting (form type = form)
|
||||
* tool_parameters: tool dynamic setting(form type = llm)
|
||||
* output_schema: tool dynamic output
|
||||
*/
|
||||
const { provider_id, provider_type, tool_name, tool_configurations, output_schema, tool_parameters } = inputs
|
||||
const { provider_id, provider_type, tool_name, tool_configurations, tool_parameters } = inputs
|
||||
const isBuiltIn = provider_type === CollectionType.builtIn
|
||||
const buildInTools = useStore(s => s.buildInTools)
|
||||
const customTools = useStore(s => s.customTools)
|
||||
|
|
@ -53,7 +52,9 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
|||
return []
|
||||
}
|
||||
}, [buildInTools, customTools, mcpTools, provider_type, workflowTools])
|
||||
const currCollection = currentTools.find(item => canFindTool(item.id, provider_id))
|
||||
const currCollection = useMemo(() => {
|
||||
return currentTools.find(item => canFindTool(item.id, provider_id))
|
||||
}, [currentTools, provider_id])
|
||||
|
||||
// Auth
|
||||
const needAuth = !!currCollection?.allow_delete
|
||||
|
|
@ -75,13 +76,19 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
|||
hideSetAuthModal()
|
||||
}, [currCollection?.name, hideSetAuthModal, t, handleFetchAllTools, provider_type])
|
||||
|
||||
const currTool = currCollection?.tools.find(tool => tool.name === tool_name)
|
||||
const currTool = useMemo(() => {
|
||||
return currCollection?.tools.find(tool => tool.name === tool_name)
|
||||
}, [currCollection, tool_name])
|
||||
const formSchemas = useMemo(() => {
|
||||
return currTool ? toolParametersToFormSchemas(currTool.parameters) : []
|
||||
}, [currTool])
|
||||
const toolInputVarSchema = formSchemas.filter((item: any) => item.form === 'llm')
|
||||
const toolInputVarSchema = useMemo(() => {
|
||||
return formSchemas.filter((item: any) => item.form === 'llm')
|
||||
}, [formSchemas])
|
||||
// use setting
|
||||
const toolSettingSchema = formSchemas.filter((item: any) => item.form !== 'llm')
|
||||
const toolSettingSchema = useMemo(() => {
|
||||
return formSchemas.filter((item: any) => item.form !== 'llm')
|
||||
}, [formSchemas])
|
||||
const hasShouldTransferTypeSettingInput = toolSettingSchema.some(item => item.type === 'boolean' || item.type === 'number-input')
|
||||
|
||||
const setInputs = useCallback((value: ToolNodeType) => {
|
||||
|
|
@ -174,8 +181,10 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
|||
|
||||
const outputSchema = useMemo(() => {
|
||||
const res: any[] = []
|
||||
if (!output_schema)
|
||||
return []
|
||||
const output_schema = currTool?.output_schema
|
||||
if (!output_schema || !output_schema.properties)
|
||||
return res
|
||||
|
||||
Object.keys(output_schema.properties).forEach((outputKey) => {
|
||||
const output = output_schema.properties[outputKey]
|
||||
const type = output.type
|
||||
|
|
@ -196,14 +205,15 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
|||
}
|
||||
})
|
||||
return res
|
||||
}, [output_schema])
|
||||
}, [currTool])
|
||||
|
||||
const hasObjectOutput = useMemo(() => {
|
||||
if (!output_schema)
|
||||
const output_schema = currTool?.output_schema
|
||||
if (!output_schema || !output_schema.properties)
|
||||
return false
|
||||
const properties = output_schema.properties
|
||||
return Object.keys(properties).some(key => properties[key].type === 'object')
|
||||
}, [output_schema])
|
||||
}, [currTool])
|
||||
|
||||
return {
|
||||
readOnly,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ export const useInitial = (id: string) => {
|
|||
tool_description: currTool.description[language],
|
||||
title: currTool.label[language],
|
||||
is_team_authorization: currCollection.is_team_authorization,
|
||||
output_schema: currTool.output_schema,
|
||||
paramSchemas: currTool.parameters,
|
||||
params,
|
||||
_notInitialized: false,
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ export type NodeDefault<T = {}> = {
|
|||
defaultValue: Partial<T>
|
||||
defaultRunInputData?: Record<string, any>
|
||||
checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
|
||||
getOutputVars?: (payload: T, ragVariables?: Var[]) => Var[]
|
||||
getOutputVars?: (payload: T, allPluginInfoList: Record<string, ToolWithProvider[]>, ragVariables?: Var[]) => Var[]
|
||||
}
|
||||
|
||||
export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue | DataSourceDefaultValue) => void
|
||||
|
|
|
|||
Loading…
Reference in New Issue