diff --git a/web/app/components/workflow/variable-inspect/group.tsx b/web/app/components/workflow/variable-inspect/group.tsx new file mode 100644 index 0000000000..67a06e331d --- /dev/null +++ b/web/app/components/workflow/variable-inspect/group.tsx @@ -0,0 +1,128 @@ +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + RiArrowRightSLine, + // RiErrorWarningFill, + // RiLoader2Line, +} from '@remixicon/react' +import { useStore } from '../store' +// import { BlockEnum } from '../types' +// import Button from '@/app/components/base/button' +// import ActionButton from '@/app/components/base/action-button' +// import Tooltip from '@/app/components/base/tooltip' +// import BlockIcon from '@/app/components/workflow/block-icon' +import { + // BubbleX, + Env, +} from '@/app/components/base/icons/src/vender/line/others' +// import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' +// import useCurrentVars from '../hooks/use-inspect-vars-crud' +import type { currentVarType } from './panel' +import cn from '@/utils/classnames' + +type Props = { + isEnv?: boolean + isChatVar?: boolean + isSystem?: boolean + currentVar?: currentVarType + handleSelect: (state: any) => void +} + +const Group = ({ + isEnv, + isChatVar, + isSystem, + currentVar, + handleSelect, +}: Props) => { + const { t } = useTranslation() + + const environmentVariables = useStore(s => s.environmentVariables) + // const { + // conversationVars, + // systemVars, + // nodesWithInspectVars, + // } = useCurrentVars() + + const [isCollapsed, setIsCollapsed] = useState(false) + + const handleSelectVar = (varItem: any, type?: string) => { + if (type === 'env') { + handleSelect({ + nodeId: 'env', + nodeTitle: 'env', + nodeType: 'env', + var: { + ...varItem, + type: 'env', + ...(varItem.value_type === 'secret' ? { value: '******************' } : {}), + }, + }) + return + } + if (type === 'chat') { + handleSelect({ + nodeId: 'conversation', + nodeTitle: 'conversation', + nodeType: 'conversation', + var: { + ...varItem, + type: 'conversation', + }, + }) + return + } + if (type === 'system') { + handleSelect({ + nodeId: 'sys', + nodeTitle: 'sys', + nodeType: 'sys', + var: varItem, + }) + return + } + handleSelect({ + nodeId: varItem.nodeId, + nodeTitle: varItem.nodeTitle, + nodeType: varItem.nodeType, + var: varItem.var, + }) + } + + return ( +
+ {/* node item */} +
+ +
setIsCollapsed(!isCollapsed)}> +
+ {isEnv && t('workflow.debug.variableInspect.envNode')} + {isChatVar && t('workflow.debug.variableInspect.chatNode')} + {isSystem && t('workflow.debug.variableInspect.systemNode')} +
+
+
+ {/* var item list */} + {!isCollapsed && ( +
+ {environmentVariables.length > 0 && environmentVariables.map(env => ( +
handleSelectVar(env, 'env')} + > + +
{env.name}
+
{env.value_type}
+
+ ))} +
+ )} +
+ ) +} + +export default Group diff --git a/web/app/components/workflow/variable-inspect/left.tsx b/web/app/components/workflow/variable-inspect/left.tsx index e9538e8e0b..045a1e859b 100644 --- a/web/app/components/workflow/variable-inspect/left.tsx +++ b/web/app/components/workflow/variable-inspect/left.tsx @@ -5,27 +5,35 @@ import { RiErrorWarningFill, RiLoader2Line, } from '@remixicon/react' -// import { useStore } from '../store' +import { useStore } from '../store' import { BlockEnum } from '../types' import Button from '@/app/components/base/button' -// import ActionButton from '@/app/components/base/action-button' -// import Tooltip from '@/app/components/base/tooltip' +// import ActionButton from '@/app/components/base/action-button' +// import Tooltip from '@/app/components/base/tooltip' import BlockIcon from '@/app/components/workflow/block-icon' -import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' +import { BubbleX } from '@/app/components/base/icons/src/vender/line/others' import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' +import Group from './group' import useCurrentVars from '../hooks/use-inspect-vars-crud' +import type { currentVarType } from './panel' import cn from '@/utils/classnames' type Props = { - handleMenuClick: (state: any) => void + currentNodeVar?: currentVarType + handleVarSelect: (state: any) => void } -const Left = ({ handleMenuClick }: Props) => { +const Left = ({ + currentNodeVar, + handleVarSelect, +}: Props) => { const { t } = useTranslation() - // const bottomPanelWidth = useStore(s => s.bottomPanelWidth) - // const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel) + const environmentVariables = useStore(s => s.environmentVariables) const { + conversationVars, + systemVars, + nodesWithInspectVars, deleteAllInspectorVars, } = useCurrentVars() @@ -42,29 +50,13 @@ const Left = ({ handleMenuClick }: Props) => { {/* content */}
{/* group ENV */} -
- {/* node item */} -
- -
-
{t('workflow.env.envPanelTitle')}
-
-
- {/* var item list */} -
-
- -
SECRET_KEY
-
string
-
-
- {selectedNode && } - -
PORT
-
number
-
-
-
+ {environmentVariables.length > 0 && ( + + )} {/* group CHAT VAR */}
{/* node item */} diff --git a/web/app/components/workflow/variable-inspect/panel.tsx b/web/app/components/workflow/variable-inspect/panel.tsx index 46d8ca8607..4c6a86d990 100644 --- a/web/app/components/workflow/variable-inspect/panel.tsx +++ b/web/app/components/workflow/variable-inspect/panel.tsx @@ -10,14 +10,23 @@ import Empty from './empty' import Left from './left' import Right from './right' import ActionButton from '@/app/components/base/action-button' +import type { VarInInspect } from '@/types/workflow' import cn from '@/utils/classnames' +export type currentVarType = { + nodeId: string + nodeTitle: string + nodeType: string + var: VarInInspect +} + const Panel: FC = () => { const { t } = useTranslation() const bottomPanelWidth = useStore(s => s.bottomPanelWidth) const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel) const [showLeftPanel, setShowLeftPanel] = useState(true) + const [currentNodeVar, setCurrentNodeVar] = useState() const environmentVariables = useStore(s => s.environmentVariables) const { @@ -60,11 +69,17 @@ const Panel: FC = () => { : 'block', )} > - +
{/* right */}
- setShowLeftPanel(true)} /> + setShowLeftPanel(true)} + />
) diff --git a/web/app/components/workflow/variable-inspect/right.tsx b/web/app/components/workflow/variable-inspect/right.tsx index 2ce95044b8..58e59bbee5 100644 --- a/web/app/components/workflow/variable-inspect/right.tsx +++ b/web/app/components/workflow/variable-inspect/right.tsx @@ -6,7 +6,7 @@ import { RiMenuLine, } from '@remixicon/react' import { useStore } from '../store' -import { BlockEnum } from '../types' +import type { BlockEnum } from '../types' import useCurrentVars from '../hooks/use-inspect-vars-crud' import Empty from './empty' import ValueContent from './value-content' @@ -16,43 +16,29 @@ import CopyFeedback from '@/app/components/base/copy-feedback' import Tooltip from '@/app/components/base/tooltip' import BlockIcon from '@/app/components/workflow/block-icon' import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others' +import type { currentVarType } from './panel' import cn from '@/utils/classnames' -export const currentVar = { - id: 'var-jfkldjjfkldaf-dfhekdfj', - type: 'node', - // type: 'conversation', - // type: 'environment', - name: 'out_put', - var_type: 'string', - // var_type: 'number', - // var_type: 'object', - // var_type: 'array[string]', - // var_type: 'array[number]', - // var_type: 'array[object]', - // var_type: 'file', - // var_type: 'array[file]', - value: 'tuituitui', - edited: true, -} - type Props = { + currentNodeVar?: currentVarType handleOpenMenu: () => void } -const Right = ({ handleOpenMenu }: Props) => { +const Right = ({ + currentNodeVar, + handleOpenMenu, +}: Props) => { const { t } = useTranslation() const bottomPanelWidth = useStore(s => s.bottomPanelWidth) const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel) - const current = currentVar - const { resetToLastRunVar, } = useCurrentVars() const resetValue = () => { - resetToLastRunVar('node_id', current.name) + if (!currentNodeVar) return + resetToLastRunVar(currentNodeVar.nodeId, currentNodeVar.var.name) } return ( @@ -65,48 +51,48 @@ const Right = ({ handleOpenMenu }: Props) => { )}
- {current && ( + {currentNodeVar && ( <> - {current.type === 'environment' && ( + {currentNodeVar.nodeType === 'env' && ( )} - {current.type === 'conversation' && ( + {currentNodeVar.nodeType === 'conversation' && ( )} - {current.type === 'node' && ( + {currentNodeVar.nodeType !== 'env' && currentNodeVar.nodeType !== 'conversation' && currentNodeVar.nodeType !== 'sys' && ( <> -
LLM
+
{currentNodeVar.nodeTitle}
/
)} -
{current.name}
-
{current.var_type}
+
{currentNodeVar.var.name}
+
{currentNodeVar.var.value_type}
)}
- {current && ( + {currentNodeVar && ( <> - {current.edited && ( + {currentNodeVar.var.edited && ( {t('workflow.debug.variableInspect.edited')} )} - {current.edited && ( + {currentNodeVar.var.edited && ( )} - {(current.type !== 'environment' || current.var_type !== 'secret') && ( - + {currentNodeVar.var.value_type !== 'secret' && ( + )} )} @@ -117,8 +103,8 @@ const Right = ({ handleOpenMenu }: Props) => {
{/* content */}
- {!current && } - {current && } + {!currentNodeVar && } + {currentNodeVar && }
) diff --git a/web/app/components/workflow/variable-inspect/value-content.tsx b/web/app/components/workflow/variable-inspect/value-content.tsx index ee75912702..132d299c82 100644 --- a/web/app/components/workflow/variable-inspect/value-content.tsx +++ b/web/app/components/workflow/variable-inspect/value-content.tsx @@ -19,22 +19,24 @@ import { JSON_SCHEMA_MAX_DEPTH } from '@/config' import { TransferMethod } from '@/types/app' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import { SupportUploadFileTypes } from '@/app/components/workflow/types' +import type { VarInInspect } from '@/types/workflow' +import { VarInInspectType } from '@/types/workflow' import cn from '@/utils/classnames' -export const currentVar = { +export const MOCK_DATA = { id: 'var-jfkldjjfkldaf-dfhekdfj', type: 'node', // type: 'conversation', // type: 'environment', name: 'out_put', - // var_type: 'string', - // var_type: 'number', - // var_type: 'object', - // var_type: 'array[string]', - // var_type: 'array[number]', - // var_type: 'array[object]', - // var_type: 'file', - var_type: 'array[file]', + // value_type: 'string', + // value_type: 'number', + // value_type: 'object', + // value_type: 'array[string]', + // value_type: 'array[number]', + // value_type: 'array[object]', + // value_type: 'file', + value_type: 'array[file]', // value: 'tuituitui', // value: ['aaa', 'bbb', 'ccc'], // value: { @@ -46,34 +48,62 @@ export const currentVar = { edited: true, } -const ValueContent = () => { - const current = currentVar +type Props = { + currentVar: VarInInspect +} + +const ValueContent = ({ + // currentVar = MOCK_DATA as any, // TODO remove this line + currentVar, +}: Props) => { const contentContainerRef = useRef(null) const errorMessageRef = useRef(null) const [editorHeight, setEditorHeight] = useState(0) - const showTextEditor = current.var_type === 'secret' || current.var_type === 'string' || current.var_type === 'number' - const showJSONEditor = current.var_type === 'object' || current.var_type === 'array[string]' || current.var_type === 'array[number]' || current.var_type === 'array[object]' - const showFileEditor = current.var_type === 'file' || current.var_type === 'array[file]' + const showTextEditor = currentVar.value_type === 'secret' || currentVar.value_type === 'string' || currentVar.value_type === 'number' + const showJSONEditor = currentVar.value_type === 'object' || currentVar.value_type === 'array[string]' || currentVar.value_type === 'array[number]' || currentVar.value_type === 'array[object]' + const showFileEditor = currentVar.value_type === 'file' || currentVar.value_type === 'array[file]' - const [value, setValue] = useState(current.value ? JSON.stringify(current.value) : '') - const [jsonSchema, setJsonSchema] = useState(current.value || null) - const [json, setJson] = useState(JSON.stringify(jsonSchema, null, 2)) + const [value, setValue] = useState() + const [jsonSchema, setJsonSchema] = useState() + const [json, setJson] = useState('') const [parseError, setParseError] = useState(null) const [validationError, setValidationError] = useState('') const fileFeature = useFeatures(s => s.features.file) const [fileValue, setFileValue] = useState( - current.var_type === 'array[file]' - ? current.value || [] - : current.value - ? [current.value] + currentVar.value_type === 'array[file]' + ? currentVar.value || [] + : currentVar.value + ? [currentVar.value] : [], ) + // update default value when id changed + useEffect(() => { + if (showTextEditor) { + if (!currentVar.value) + return setValue('') + if (currentVar.value_type === 'number') + return setValue(JSON.stringify(currentVar.value)) + setValue(currentVar.value) + } + if (showJSONEditor) { + setJsonSchema(currentVar.value || null) + setJson(currentVar.value ? JSON.stringify(currentVar.value, null, 2) : '') + } + if (showFileEditor) { + setFileValue(currentVar.value_type === 'array[file]' + ? currentVar.value || [] + : currentVar.value + ? [currentVar.value] + : []) + } + }, [currentVar, showTextEditor, showJSONEditor, showFileEditor]) + const handleTextChange = (value: string) => { - if (current.var_type === 'string') + if (currentVar.value_type === 'string') setValue(value) - if (current.var_type === 'number') { + if (currentVar.value_type === 'number') { if (/^-?\d+(\.)?(\d+)?$/.test(value)) setValue(value) } @@ -119,7 +149,7 @@ const ValueContent = () => { const handleEditorChange = (value: string) => { setJson(value) - if (jsonValueValidate(value, current.var_type)) { + if (jsonValueValidate(value, currentVar.value_type)) { const parsed = JSON.parse(value) setJsonSchema(parsed) // TODO call api of value update @@ -131,10 +161,10 @@ const ValueContent = () => { setFileValue(value) // TODO check every file upload progress // invoke update api after every file uploaded - if (current.var_type === 'file') { + if (currentVar.value_type === 'file') { // TODO call api of value update } - if (current.var_type === 'array[file]') { + if (currentVar.value_type === 'array[file]') { // TODO call api of value update } } @@ -164,8 +194,8 @@ const ValueContent = () => {
{showTextEditor && (