merge main

This commit is contained in:
zxhlyh
2025-07-02 18:07:09 +08:00
173 changed files with 3532 additions and 1135 deletions

View File

@ -15,6 +15,7 @@ import {
import useToggleExpend from '@/app/components/workflow/nodes/_base/hooks/use-toggle-expend'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import FileListInLog from '@/app/components/base/file-uploader/file-list-in-log'
import ActionButton from '@/app/components/base/action-button'
type Props = {
className?: string
@ -88,15 +89,16 @@ const Base: FC<Props> = ({
<CodeGeneratorButton onGenerated={onGenerated} codeLanguages={codeLanguages} />
</div>
)}
{!isCopied
? (
<Clipboard className='mx-1 h-3.5 w-3.5 cursor-pointer text-text-tertiary' onClick={handleCopy} />
)
: (
<ClipboardCheck className='mx-1 h-3.5 w-3.5 text-text-tertiary' />
)
}
<ActionButton className='ml-1' onClick={handleCopy}>
{!isCopied
? (
<Clipboard className='h-4 w-4 cursor-pointer' />
)
: (
<ClipboardCheck className='h-4 w-4' />
)
}
</ActionButton>
<div className='ml-1'>
<ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
</div>

View File

@ -1,10 +1,10 @@
import { memo, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { isEqual } from 'lodash-es'
import {
getConnectedEdges,
getOutgoers,
useEdges,
useStoreApi,
useStore,
} from 'reactflow'
import { useToolIcon } from '../../../../hooks'
import BlockIcon from '../../../../block-icon'
@ -26,12 +26,21 @@ const NextStep = ({
const { t } = useTranslation()
const data = selectedNode.data
const toolIcon = useToolIcon(data)
const store = useStoreApi()
const branches = useMemo(() => {
return data._targetBranches || []
}, [data])
const edges = useEdges()
const outgoers = getOutgoers(selectedNode as Node, store.getState().getNodes(), edges)
const edges = useStore(s => s.edges.map(edge => ({
id: edge.id,
source: edge.source,
sourceHandle: edge.sourceHandle,
target: edge.target,
targetHandle: edge.targetHandle,
})), isEqual)
const nodes = useStore(s => s.getNodes().map(node => ({
id: node.id,
data: node.data,
})), isEqual)
const outgoers = getOutgoers(selectedNode as Node, nodes as Node[], edges)
const connectedEdges = getConnectedEdges([selectedNode] as Node[], edges).filter(edge => edge.source === selectedNode!.id)
const list = useMemo(() => {

View File

@ -1,30 +1,39 @@
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import { useShallow } from 'zustand/react/shallow'
import { RiCrosshairLine } from '@remixicon/react'
import type { XYPosition } from 'reactflow'
import { useReactFlow, useStoreApi } from 'reactflow'
import { useReactFlow, useStore } from 'reactflow'
import TooltipPlus from '@/app/components/base/tooltip'
import { useNodesSyncDraft } from '@/app/components/workflow-app/hooks'
type NodePositionProps = {
nodePosition: XYPosition,
nodeWidth?: number | null,
nodeHeight?: number | null,
nodeId: string
}
const NodePosition = ({
nodePosition,
nodeWidth,
nodeHeight,
nodeId,
}: NodePositionProps) => {
const { t } = useTranslation()
const reactflow = useReactFlow()
const store = useStoreApi()
const { doSyncWorkflowDraft } = useNodesSyncDraft()
const {
nodePosition,
nodeWidth,
nodeHeight,
} = useStore(useShallow((s) => {
const nodes = s.getNodes()
const currentNode = nodes.find(node => node.id === nodeId)!
return {
nodePosition: currentNode.position,
nodeWidth: currentNode.width,
nodeHeight: currentNode.height,
}
}))
const transform = useStore(s => s.transform)
if (!nodePosition || !nodeWidth || !nodeHeight) return null
const workflowContainer = document.getElementById('workflow-container')
const { transform } = store.getState()
const zoom = transform[2]
const { clientWidth, clientHeight } = workflowContainer!

View File

@ -15,7 +15,7 @@ import { pluginManifestToCardPluginProps } from '@/app/components/plugins/instal
import { Badge as Badge2, BadgeState } from '@/app/components/base/badge/index'
import Link from 'next/link'
import { useTranslation } from 'react-i18next'
import { MARKETPLACE_URL_PREFIX } from '@/config'
import { getMarketplaceUrl } from '@/utils/var'
export type SwitchPluginVersionProps = {
uniqueIdentifier: string
@ -82,7 +82,7 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
modalBottomLeft={
<Link
className='flex items-center justify-center gap-1'
href={`${MARKETPLACE_URL_PREFIX}/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`}
href={getMarketplaceUrl(`/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`)}
target='_blank'
>
<span className='system-xs-regular text-xs text-text-accent'>

View File

@ -13,6 +13,8 @@ type Props = {
readonly: boolean
value: string
onChange: (value: string | number, varKindType: VarKindType, varInfo?: Var) => void
onOpenChange?: (open: boolean) => void
isLoading?: boolean
}
const DEFAULT_SCHEMA = {} as CredentialFormSchema
@ -22,6 +24,8 @@ const ConstantField: FC<Props> = ({
readonly,
value,
onChange,
onOpenChange,
isLoading,
}) => {
const language = useLanguage()
const placeholder = (schema as CredentialFormSchemaSelect).placeholder
@ -36,7 +40,7 @@ const ConstantField: FC<Props> = ({
return (
<>
{schema.type === FormTypeEnum.select && (
{(schema.type === FormTypeEnum.select || schema.type === FormTypeEnum.dynamicSelect) && (
<SimpleSelect
wrapperClassName='w-full !h-8'
className='flex items-center'
@ -45,6 +49,8 @@ const ConstantField: FC<Props> = ({
items={(schema as CredentialFormSchemaSelect).options.map(option => ({ value: option.value, name: option.label[language] || option.label.en_US }))}
onSelect={item => handleSelectChange(item.value)}
placeholder={placeholder?.[language] || placeholder?.en_US}
onOpenChange={onOpenChange}
isLoading={isLoading}
/>
)}
{schema.type === FormTypeEnum.textNumber && (

View File

@ -1171,13 +1171,13 @@ export const getNodeUsedVarPassToServerKey = (node: Node, valueSelector: ValueSe
break
}
case BlockEnum.Code: {
const targetVar = (data as CodeNodeType).variables?.find(v => v.value_selector.join('.') === valueSelector.join('.'))
const targetVar = (data as CodeNodeType).variables?.find(v => Array.isArray(v.value_selector) && v.value_selector && v.value_selector.join('.') === valueSelector.join('.'))
if (targetVar)
res = targetVar.variable
break
}
case BlockEnum.TemplateTransform: {
const targetVar = (data as TemplateTransformNodeType).variables?.find(v => v.value_selector.join('.') === valueSelector.join('.'))
const targetVar = (data as TemplateTransformNodeType).variables?.find(v => Array.isArray(v.value_selector) && v.value_selector && v.value_selector.join('.') === valueSelector.join('.'))
if (targetVar)
res = targetVar.variable
break

View File

@ -65,10 +65,11 @@ const VarList: FC<Props> = ({
}, [list, onVarNameChange, onChange])
const handleVarReferenceChange = useCallback((index: number) => {
return (value: ValueSelector | string, varKindType: VarKindType) => {
return (value: ValueSelector | string, varKindType: VarKindType, varInfo?: Var) => {
const newList = produce(list, (draft) => {
if (!isSupportConstantValue || varKindType === VarKindType.variable) {
draft[index].value_selector = value as ValueSelector
draft[index].value_type = varInfo?.type
if (isSupportConstantValue)
draft[index].variable_type = VarKindType.variable

View File

@ -6,6 +6,7 @@ import {
RiArrowDownSLine,
RiCloseLine,
RiErrorWarningFill,
RiLoader4Line,
RiMoreLine,
} from '@remixicon/react'
import produce from 'immer'
@ -20,8 +21,9 @@ import VarReferencePopup from './var-reference-popup'
import { getNodeInfoById, isConversationVar, isENV, isRagVariableVar, isSystemVar, varTypeToStructType } from './utils'
import ConstantField from './constant-field'
import cn from '@/utils/classnames'
import type { CommonNodeType, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { CommonNodeType, Node, NodeOutPutVar, ToolWithProvider, ValueSelector, Var } from '@/app/components/workflow/types'
import type { CredentialFormSchemaSelect } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { type CredentialFormSchema, type FormOption, FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { BlockEnum } from '@/app/components/workflow/types'
import { VarBlockIcon } from '@/app/components/workflow/block-icon'
import { Line3 } from '@/app/components/base/icons/src/public/common'
@ -46,6 +48,9 @@ import VarFullPathPanel from './var-full-path-panel'
import { noop } from 'lodash-es'
import { InputField } from '@/app/components/base/icons/src/vender/pipeline'
import { useStore as useWorkflowStore } from '@/app/components/workflow/store'
import { useFetchDynamicOptions } from '@/service/use-plugins'
import type { Tool } from '@/app/components/tools/types'
const TRIGGER_DEFAULT_WIDTH = 227
type Props = {
@ -73,6 +78,8 @@ type Props = {
minWidth?: number
popupFor?: 'assigned' | 'toAssigned'
zIndex?: number
currentTool?: Tool
currentProvider?: ToolWithProvider
}
const DEFAULT_VALUE_SELECTOR: Props['value'] = []
@ -102,6 +109,8 @@ const VarReferencePicker: FC<Props> = ({
minWidth,
popupFor,
zIndex,
currentTool,
currentProvider,
}) => {
const { t } = useTranslation()
const store = useStoreApi()
@ -182,9 +191,11 @@ const VarReferencePicker: FC<Props> = ({
return startNode?.data
const node = getNodeInfoById(availableNodes, outputVarNodeId)?.data
return {
...node,
id: outputVarNodeId,
if (node) {
return {
...node,
id: outputVarNodeId,
}
}
}, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode, isLoopVar, loopNode])
@ -325,6 +336,41 @@ const VarReferencePicker: FC<Props> = ({
return null
}, [isValidVar, isShowAPart, hasValue, t, outputVarNode?.title, outputVarNode?.type, value, type])
const [dynamicOptions, setDynamicOptions] = useState<FormOption[] | null>(null)
const [isLoading, setIsLoading] = useState(false)
const { mutateAsync: fetchDynamicOptions } = useFetchDynamicOptions(
currentProvider?.plugin_id || '', currentProvider?.name || '', currentTool?.name || '', (schema as CredentialFormSchemaSelect)?.variable || '',
'tool',
)
const handleFetchDynamicOptions = async () => {
if (schema?.type !== FormTypeEnum.dynamicSelect || !currentTool || !currentProvider)
return
setIsLoading(true)
try {
const data = await fetchDynamicOptions()
setDynamicOptions(data?.options || [])
}
finally {
setIsLoading(false)
}
}
useEffect(() => {
handleFetchDynamicOptions()
}, [currentTool, currentProvider, schema])
const schemaWithDynamicSelect = useMemo(() => {
if (schema?.type !== FormTypeEnum.dynamicSelect)
return schema
// rewrite schema.options with dynamicOptions
if (dynamicOptions) {
return {
...schema,
options: dynamicOptions,
}
}
return schema
}, [dynamicOptions])
return (
<div className={cn(className, !readonly && 'cursor-pointer')}>
<PortalToFollowElem
@ -375,8 +421,9 @@ const VarReferencePicker: FC<Props> = ({
<ConstantField
value={value as string}
onChange={onChange as ((value: string | number, varKindType: VarKindType, varInfo?: Var) => void)}
schema={schema as CredentialFormSchema}
schema={schemaWithDynamicSelect as CredentialFormSchema}
readonly={readonly}
isLoading={isLoading}
/>
)
: (
@ -421,6 +468,7 @@ const VarReferencePicker: FC<Props> = ({
)}
<div className='flex items-center text-text-accent'>
{!hasValue && <Variable02 className='h-3.5 w-3.5' />}
{isLoading && <RiLoader4Line className='h-3.5 w-3.5 animate-spin text-text-secondary' />}
{isEnv && <Env className='h-3.5 w-3.5 text-util-colors-violet-violet-600' />}
{isChatVar && <BubbleX className='h-3.5 w-3.5 text-util-colors-teal-teal-700' />}
{isRagVar && <InputField className='h-3.5 w-3.5 text-text-accent' />}
@ -434,7 +482,16 @@ const VarReferencePicker: FC<Props> = ({
{!isValidVar && <RiErrorWarningFill className='ml-0.5 h-3 w-3 text-text-destructive' />}
</>
)
: <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`}>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</div>}
: <div className={`overflow-hidden ${readonly ? 'text-components-input-text-disabled' : 'text-components-input-text-placeholder'} system-sm-regular text-ellipsis`}>
{isLoading ? (
<div className='flex items-center'>
<RiLoader4Line className='mr-1 h-3.5 w-3.5 animate-spin text-text-secondary' />
<span>{placeholder ?? t('workflow.common.setVarValuePlaceholder')}</span>
</div>
) : (
placeholder ?? t('workflow.common.setVarValuePlaceholder')
)}
</div>}
</div>
</Tooltip>
</div>

View File

@ -62,15 +62,14 @@ import { Stop } from '@/app/components/base/icons/src/vender/line/mediaAndDevice
type BasePanelProps = {
children: ReactNode
} & Node
id: Node['id']
data: Node['data']
}
const BasePanel: FC<BasePanelProps> = ({
id,
data,
children,
position,
width,
height,
}) => {
const { t } = useTranslation()
const { showMessageLogModal } = useAppStore(useShallow(state => ({
@ -331,7 +330,7 @@ const BasePanel: FC<BasePanelProps> = ({
</Tooltip>
)
}
<NodePosition nodePosition={position} nodeWidth={width} nodeHeight={height}></NodePosition>
<NodePosition nodeId={id}></NodePosition>
<HelpLink nodeType={data.type} />
<PanelOperator id={id} data={data} showHelpLink={false} />
<div className='mx-3 h-3.5 w-[1px] bg-divider-regular' />

View File

@ -48,7 +48,9 @@ import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
type BaseNodeProps = {
children: ReactElement
} & NodeProps
id: NodeProps['id']
data: NodeProps['data']
}
const BaseNode: FC<BaseNodeProps> = ({
id,

View File

@ -14,6 +14,7 @@ import Split from '@/app/components/workflow/nodes/_base/components/split'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
import type { NodePanelProps } from '@/app/components/workflow/types'
import SyncButton from '@/app/components/base/button/sync-button'
const i18nPrefix = 'workflow.nodes.code'
const codeLanguages = [
@ -40,6 +41,7 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
handleVarListChange,
handleAddVariable,
handleRemoveVariable,
handleSyncFunctionSignature,
handleCodeChange,
handleCodeLanguageChange,
handleVarsChange,
@ -68,7 +70,12 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
<Field
title={t(`${i18nPrefix}.inputVars`)}
operations={
!readOnly ? <AddButton onClick={handleAddVariable} /> : undefined
!readOnly ? (
<div className="flex gap-2">
<SyncButton popupContent={t(`${i18nPrefix}.syncFunctionSignature`)} onClick={handleSyncFunctionSignature} />
<AddButton onClick={handleAddVariable} />
</div>
) : undefined
}
>
<VarList

View File

@ -100,6 +100,65 @@ const useConfig = (id: string, payload: CodeNodeType) => {
setInputs(newInputs)
}, [allLanguageDefault, inputs, setInputs])
const handleSyncFunctionSignature = useCallback(() => {
const generateSyncSignatureCode = (code: string) => {
let mainDefRe
let newMainDef
if (inputs.code_language === CodeLanguage.javascript) {
mainDefRe = /function\s+main\b\s*\([\s\S]*?\)/g
newMainDef = 'function main({{var_list}})'
let param_list = inputs.variables?.map(item => item.variable).join(', ') || ''
param_list = param_list ? `{${param_list}}` : ''
newMainDef = newMainDef.replace('{{var_list}}', param_list)
}
else if (inputs.code_language === CodeLanguage.python3) {
mainDefRe = /def\s+main\b\s*\([\s\S]*?\)/g
const param_list = []
for (const item of inputs.variables) {
let param = item.variable
let param_type = ''
switch (item.value_type) {
case VarType.string:
param_type = ': str'
break
case VarType.number:
param_type = ': float'
break
case VarType.object:
param_type = ': dict'
break
case VarType.array:
param_type = ': list'
break
case VarType.arrayNumber:
param_type = ': list[float]'
break
case VarType.arrayString:
param_type = ': list[str]'
break
case VarType.arrayObject:
param_type = ': list[dict]'
break
}
param += param_type
param_list.push(`${param}`)
}
newMainDef = `def main(${param_list.join(', ')})`
}
else { return code }
const newCode = code.replace(mainDefRe, newMainDef)
return newCode
}
const newInputs = produce(inputs, (draft) => {
draft.code = generateSyncSignatureCode(draft.code)
})
setInputs(newInputs)
}, [inputs, setInputs])
const {
handleVarsChange,
handleAddVariable: handleAddOutputVariable,
@ -135,6 +194,7 @@ const useConfig = (id: string, payload: CodeNodeType) => {
handleVarListChange,
handleAddVariable,
handleRemoveVariable,
handleSyncFunctionSignature,
handleCodeChange,
handleCodeLanguageChange,
handleVarsChange,

View File

@ -14,11 +14,14 @@ import BasePanel from './_base/components/workflow-panel'
const CustomNode = (props: NodeProps) => {
const nodeData = props.data
const NodeComponent = NodeComponentMap[nodeData.type]
const NodeComponent = useMemo(() => NodeComponentMap[nodeData.type], [nodeData.type])
return (
<>
<BaseNode {...props}>
<BaseNode
id={props.id}
data={props.data}
>
<NodeComponent />
</BaseNode>
</>
@ -26,7 +29,12 @@ const CustomNode = (props: NodeProps) => {
}
CustomNode.displayName = 'CustomNode'
export const Panel = memo((props: Node) => {
export type PanelProps = {
type: Node['type']
id: Node['id']
data: Node['data']
}
export const Panel = memo((props: PanelProps) => {
const nodeClass = props.type
const nodeData = props.data
const PanelComponent = useMemo(() => {
@ -38,7 +46,11 @@ export const Panel = memo((props: Node) => {
if (nodeClass === CUSTOM_NODE) {
return (
<BasePanel key={props.id} {...props}>
<BasePanel
key={props.id}
id={props.id}
data={props.data}
>
<PanelComponent />
</BasePanel>
)

View File

@ -19,6 +19,8 @@ import Editor from '@/app/components/workflow/nodes/_base/components/prompt/edit
import StructureOutput from './components/structure-output'
import Switch from '@/app/components/base/switch'
import { RiAlertFill, RiQuestionLine } from '@remixicon/react'
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
import Toast from '@/app/components/base/toast'
const i18nPrefix = 'workflow.nodes.llm'
@ -68,10 +70,27 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
modelId: string
mode?: string
}) => {
handleCompletionParamsChange({})
handleModelChanged(model)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
(async () => {
try {
const { params: filtered, removedDetails } = await fetchAndMergeValidCompletionParams(
model.provider,
model.modelId,
inputs.model.completion_params,
)
const keys = Object.keys(removedDetails)
if (keys.length)
Toast.notify({ type: 'warning', message: `${t('common.modelProvider.parametersInvalidRemoved')}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}` })
handleCompletionParamsChange(filtered)
}
catch (e) {
Toast.notify({ type: 'error', message: t('common.error') })
handleCompletionParamsChange({})
}
finally {
handleModelChanged(model)
}
})()
}, [inputs.model.completion_params])
return (
<div className='mt-2'>

View File

@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
import type { ToolVarInputs } from '../types'
import { VarType as VarKindType } from '../types'
import cn from '@/utils/classnames'
import type { ValueSelector, Var } from '@/app/components/workflow/types'
import type { ToolWithProvider, ValueSelector, Var } from '@/app/components/workflow/types'
import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
@ -17,6 +17,7 @@ import { VarType } from '@/app/components/workflow/types'
import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector'
import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector'
import { noop } from 'lodash-es'
import type { Tool } from '@/app/components/tools/types'
type Props = {
readOnly: boolean
@ -27,6 +28,8 @@ type Props = {
onOpen?: (index: number) => void
isSupportConstantValue?: boolean
filterVar?: (payload: Var, valueSelector: ValueSelector) => boolean
currentTool?: Tool
currentProvider?: ToolWithProvider
}
const InputVarList: FC<Props> = ({
@ -38,6 +41,8 @@ const InputVarList: FC<Props> = ({
onOpen = noop,
isSupportConstantValue,
filterVar,
currentTool,
currentProvider,
}) => {
const language = useLanguage()
const { t } = useTranslation()
@ -58,6 +63,8 @@ const InputVarList: FC<Props> = ({
return 'ModelSelector'
else if (type === FormTypeEnum.toolSelector)
return 'ToolSelector'
else if (type === FormTypeEnum.dynamicSelect || type === FormTypeEnum.select)
return 'Select'
else
return 'String'
}
@ -149,6 +156,7 @@ const InputVarList: FC<Props> = ({
const handleOpen = useCallback((index: number) => {
return () => onOpen(index)
}, [onOpen])
return (
<div className='space-y-3'>
{
@ -163,7 +171,8 @@ const InputVarList: FC<Props> = ({
} = schema
const varInput = value[variable]
const isNumber = type === FormTypeEnum.textNumber
const isSelect = type === FormTypeEnum.select
const isDynamicSelect = type === FormTypeEnum.dynamicSelect
const isSelect = type === FormTypeEnum.select || type === FormTypeEnum.dynamicSelect
const isFile = type === FormTypeEnum.file || type === FormTypeEnum.files
const isAppSelector = type === FormTypeEnum.appSelector
const isModelSelector = type === FormTypeEnum.modelSelector
@ -198,11 +207,13 @@ const InputVarList: FC<Props> = ({
value={varInput?.type === VarKindType.constant ? (varInput?.value ?? '') : (varInput?.value ?? [])}
onChange={handleNotMixedTypeChange(variable)}
onOpen={handleOpen(index)}
defaultVarKindType={varInput?.type || (isNumber ? VarKindType.constant : VarKindType.variable)}
defaultVarKindType={varInput?.type || ((isNumber || isDynamicSelect) ? VarKindType.constant : VarKindType.variable)}
isSupportConstantValue={isSupportConstantValue}
filterVar={isNumber ? filterVar : undefined}
availableVars={isSelect ? availableVars : undefined}
schema={schema}
currentTool={currentTool}
currentProvider={currentProvider}
/>
)}
{isFile && (

View File

@ -42,6 +42,7 @@ const Panel: FC<NodePanelProps<ToolNodeType>> = ({
isLoading,
outputSchema,
hasObjectOutput,
currTool,
} = useConfig(id, data)
if (isLoading) {
@ -80,6 +81,8 @@ const Panel: FC<NodePanelProps<ToolNodeType>> = ({
filterVar={filterVar}
isSupportConstantValue
onOpen={handleOnVarOpen}
currentProvider={currCollection}
currentTool={currTool}
/>
</Field>
)}