Feat: sync input variable names to main() function (#21667)

This commit is contained in:
Minamiyama
2025-07-01 10:57:07 +08:00
committed by GitHub
parent 2455135eaa
commit 25de39d9c6
9 changed files with 102 additions and 2 deletions

View File

@@ -0,0 +1,27 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import { RiRefreshLine } from '@remixicon/react'
import cn from '@/utils/classnames'
import TooltipPlus from '@/app/components/base/tooltip'
type Props = {
className?: string,
popupContent?: string,
onClick: () => void
}
const SyncButton: FC<Props> = ({
className,
popupContent = '',
onClick,
}) => {
return (
<TooltipPlus popupContent={popupContent}>
<div className={cn(className, 'cursor-pointer select-none rounded-md p-1 hover:bg-state-base-hover')} onClick={onClick}>
<RiRefreshLine className='h-4 w-4 text-text-tertiary' />
</div>
</TooltipPlus>
)
}
export default React.memo(SyncButton)

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

@@ -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

@@ -84,6 +84,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,
@@ -119,6 +178,7 @@ const useConfig = (id: string, payload: CodeNodeType) => {
handleVarListChange,
handleAddVariable,
handleRemoveVariable,
handleSyncFunctionSignature,
handleCodeChange,
handleCodeLanguageChange,
handleVarsChange,

View File

@@ -136,6 +136,7 @@ export type Variable = {
variable: string
}
value_selector: ValueSelector
value_type?: VarType
variable_type?: VarKindType
value?: string
options?: string[]

View File

@@ -549,6 +549,7 @@ const translation = {
advancedDependencies: 'Advanced Dependencies',
advancedDependenciesTip: 'Add some preloaded dependencies that take more time to consume or are not default built-in here',
searchDependencies: 'Search Dependencies',
syncFunctionSignature: 'Sync function signature to code',
},
templateTransform: {
inputVars: 'Input Variables',

View File

@@ -550,6 +550,7 @@ const translation = {
advancedDependencies: '高度な依存関係',
advancedDependenciesTip: '消費に時間がかかる、またはデフォルトで組み込まれていない事前ロードされた依存関係を追加します',
searchDependencies: '依存関係を検索',
syncFunctionSignature: 'コードの関数署名を同期',
},
templateTransform: {
inputVars: '入力変数',

View File

@@ -550,6 +550,7 @@ const translation = {
advancedDependencies: '高级依赖',
advancedDependenciesTip: '在这里添加一些预加载需要消耗较多时间或非默认内置的依赖包',
searchDependencies: '搜索依赖',
syncFunctionSignature: '同步函数签名至代码',
},
templateTransform: {
inputVars: '输入变量',

View File

@@ -544,6 +544,7 @@ const translation = {
advancedDependencies: '高級依賴',
advancedDependenciesTip: '在這裡添加一些預加載需要消耗較多時間或非默認內置的依賴包',
searchDependencies: '搜索依賴',
syncFunctionSignature: '同步函數簽名至代碼',
},
templateTransform: {
inputVars: '輸入變量',