From 9d310fed9212a43e763c8a5c079c51dcfed5a22e Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Tue, 4 Nov 2025 17:53:51 +0800 Subject: [PATCH] fix: memory variable item --- .../hooks/use-nodes-sync-draft.ts | 4 +- .../workflow/hooks/use-memory-variable.ts | 4 +- .../components/memory-system/block-memory.tsx | 23 ++++++-- .../components/variable-item-with-node.tsx | 54 +++++++++++++++++++ .../components/variable-item.tsx | 17 ++++-- .../panel/chat-variable-panel/index.tsx | 41 ++++++++++++-- web/i18n/en-US/workflow.ts | 1 + web/i18n/zh-Hans/workflow.ts | 1 + 8 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 web/app/components/workflow/panel/chat-variable-panel/components/variable-item-with-node.tsx diff --git a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts index 174debb982..406532b3cb 100644 --- a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts +++ b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts @@ -85,9 +85,11 @@ export const useNodesSyncDraft = () => { }, environment_variables: environmentVariables, conversation_variables: conversationVariables, - memory_blocks: memoryVariables.map(({ value_type, more, model, ...rest }) => { + memory_blocks: memoryVariables.map(({ value_type, scope, more, node_id, model, ...rest }) => { return { ...rest, + node_id: scope === 'node' ? node_id : undefined, + scope, model: model ? { completion_params: model.completion_params, mode: model.mode, diff --git a/web/app/components/workflow/hooks/use-memory-variable.ts b/web/app/components/workflow/hooks/use-memory-variable.ts index edd913dda3..e5d131f06c 100644 --- a/web/app/components/workflow/hooks/use-memory-variable.ts +++ b/web/app/components/workflow/hooks/use-memory-variable.ts @@ -1,4 +1,6 @@ -import { useCallback } from 'react' +import { + useCallback, +} from 'react' import { useStore, useWorkflowStore, diff --git a/web/app/components/workflow/nodes/llm/components/memory-system/block-memory.tsx b/web/app/components/workflow/nodes/llm/components/memory-system/block-memory.tsx index fe48f3ccee..1a2b85401e 100644 --- a/web/app/components/workflow/nodes/llm/components/memory-system/block-memory.tsx +++ b/web/app/components/workflow/nodes/llm/components/memory-system/block-memory.tsx @@ -14,6 +14,7 @@ import { useMemoryVariables } from './hooks/use-memory-variables' import Confirm from '@/app/components/base/confirm' import { Memory as MemoryIcon } from '@/app/components/base/icons/src/vender/line/others' import VariableModal from '@/app/components/workflow/panel/chat-variable-panel/components/variable-modal' +import cn from '@/utils/classnames' type BlockMemoryProps = { id: string @@ -21,6 +22,7 @@ type BlockMemoryProps = { } const BlockMemory = ({ id }: BlockMemoryProps) => { const { t } = useTranslation() + const [destructiveItemId, setDestructiveItemId] = useState(undefined) const { memoryVariablesInUsed, editMemoryVariable, @@ -55,7 +57,10 @@ const BlockMemory = ({ id }: BlockMemoryProps) => { memoryVariablesInUsed.map(memoryVariable => (
+ className={cn( + 'group flex h-8 items-center space-x-1 rounded-lg border-[0.5px] border-components-panel-border-subtle bg-components-panel-on-panel-item-bg pl-2 pr-1 shadow-xs', + destructiveItemId === memoryVariable.id && 'border border-state-destructive-solid bg-state-destructive-hover', + )}>
{ > {memoryVariable.name}
- + {memoryVariable.term} handleSetEditMemoryVariable(memoryVariable.id)} > handleDelete(memoryVariable.id)} + onMouseOver={() => setDestructiveItemId(memoryVariable.id)} + onMouseOut={() => setDestructiveItemId(undefined)} > - +
)) diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-item-with-node.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-item-with-node.tsx new file mode 100644 index 0000000000..ea23481b6e --- /dev/null +++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-item-with-node.tsx @@ -0,0 +1,54 @@ +import { memo } from 'react' +import { useStore } from 'reactflow' +import VariableItem from './variable-item' +import BlockIcon from '@/app/components/workflow/block-icon' +import { BlockEnum } from '@/app/components/workflow/types' +import type { MemoryVariable } from '@/app/components/workflow/types' + +type VariableItemWithNodeProps = { + nodeId: string + memoryVariables: MemoryVariable[] + onEdit: (memoryVariable: MemoryVariable) => void + onDelete: (memoryVariable: MemoryVariable) => void + currentVarId?: string +} +const VariableItemWithNode = ({ + nodeId, + memoryVariables, + onEdit, + onDelete, + currentVarId, +}: VariableItemWithNodeProps) => { + const currentNode = useStore(s => s.nodeInternals.get(nodeId)) + + if (!currentNode) return null + + return ( +
+
+ +
+ {currentNode?.data.title} +
+
+ { + memoryVariables.map(memoryVariable => ( + + )) + } +
+ ) +} + +export default memo(VariableItemWithNode) diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-item.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-item.tsx index 0186b137cd..073ec1be98 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-item.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-item.tsx @@ -8,17 +8,24 @@ import { import type { ConversationVariable, MemoryVariable } from '@/app/components/workflow/types' import cn from '@/utils/classnames' import { ChatVarType } from '../type' +import Badge from '@/app/components/base/badge' type VariableItemProps = { item: ConversationVariable | MemoryVariable onEdit: (item: ConversationVariable | MemoryVariable) => void onDelete: (item: ConversationVariable | MemoryVariable) => void + scope?: string + term?: string + currentVarId?: string } const VariableItem = ({ item, onEdit, onDelete, + scope, + term, + currentVarId, }: VariableItemProps) => { const [destructive, setDestructive] = useState(false) return ( @@ -26,7 +33,7 @@ const VariableItem = ({ 'radius-md mb-1 border border-components-panel-border-subtle bg-components-panel-on-panel-item-bg px-2.5 py-2 shadow-xs hover:bg-components-panel-on-panel-item-bg-hover', destructive && 'border-state-destructive-border hover:bg-state-destructive-hover', )}> -
+
{ item.value_type === ChatVarType.Memory && ( @@ -42,16 +49,20 @@ const VariableItem = ({
{capitalize(item.value_type)}
-
+ +
+ {scope && } + {term && } +
{ diff --git a/web/app/components/workflow/panel/chat-variable-panel/index.tsx b/web/app/components/workflow/panel/chat-variable-panel/index.tsx index 20ec4670e5..de46538b7a 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/index.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/index.tsx @@ -3,6 +3,7 @@ import { useCallback, useState, } from 'react' +import { groupBy } from 'lodash-es' import { useStoreApi, } from 'reactflow' @@ -30,16 +31,24 @@ import cn from '@/utils/classnames' import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud' import { ChatVarType } from './type' import { useMemoryVariable } from '@/app/components/workflow/hooks' +import VariableItemWithNode from './components/variable-item-with-node' const ChatVariablePanel = () => { const { t } = useTranslation() const docLink = useDocLink() const store = useStoreApi() const workflowStore = useWorkflowStore() - const { handleAddMemoryVariable, handleUpdateMemoryVariable, handleDeleteMemoryVariable } = useMemoryVariable() + const appScopeMemoryVariables = useStore(s => s.memoryVariables.filter(v => v.scope === 'app')) + const nodeScopeMemoryVariables = useStore((s) => { + return groupBy(s.memoryVariables.filter(v => v.scope === 'node'), 'node_id') + }) + const { + handleAddMemoryVariable, + handleUpdateMemoryVariable, + handleDeleteMemoryVariable, + } = useMemoryVariable() const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel) const varList = useStore(s => s.conversationVariables) as ConversationVariable[] - const memoryVariables = useStore(s => s.memoryVariables) as MemoryVariable[] const updateChatVarList = useStore(s => s.setConversationVariables) const setMemoryVariables = useStore(s => s.setMemoryVariables) const { doSyncWorkflowDraft } = useNodesSyncDraft() @@ -220,12 +229,15 @@ const ChatVariablePanel = () => {
{ - memoryVariables.map(memoryVariable => ( + appScopeMemoryVariables.map(memoryVariable => ( )) } @@ -235,8 +247,31 @@ const ChatVariablePanel = () => { item={chatVar} onEdit={handleEdit} onDelete={deleteCheck} + currentVarId={currentVar?.id} /> ))} + { + !!Object.keys(nodeScopeMemoryVariables).length && ( +
+
+ {t('workflow.chatVariable.nodeScopeMemory')} +
+
+ { + Object.keys(nodeScopeMemoryVariables).map(nodeId => ( + + )) + } +
+ ) + }