mirror of
https://github.com/langgenius/dify.git
synced 2026-04-26 02:06:35 +08:00
support create memory var in memory popup
This commit is contained in:
parent
05c05bb6d0
commit
efcaa2bbbd
@ -25,7 +25,7 @@ import {
|
|||||||
} from 'lexical'
|
} from 'lexical'
|
||||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||||
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/add-memory-button'
|
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER, MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/type'
|
||||||
import Divider from '@/app/components/base/divider'
|
import Divider from '@/app/components/base/divider'
|
||||||
import VariableIcon from '@/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-icon'
|
import VariableIcon from '@/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-icon'
|
||||||
import type {
|
import type {
|
||||||
@ -135,15 +135,25 @@ export default function MemoryPopupPlugin({
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
}, [setOpen])
|
}, [setOpen])
|
||||||
|
|
||||||
|
const handleSelectVariable = useCallback((variable: string[]) => {
|
||||||
|
editor.dispatchCommand(INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND, variable)
|
||||||
|
closePortal()
|
||||||
|
}, [editor, closePortal])
|
||||||
|
|
||||||
|
const handleCreate = useCallback(() => {
|
||||||
|
eventEmitter?.emit({ type: MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER, instanceId } as any)
|
||||||
|
closePortal()
|
||||||
|
}, [eventEmitter, instanceId, closePortal])
|
||||||
|
|
||||||
eventEmitter?.useSubscription((v: any) => {
|
eventEmitter?.useSubscription((v: any) => {
|
||||||
if (v.type === MEMORY_POPUP_SHOW_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
if (v.type === MEMORY_POPUP_SHOW_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||||
openPortal()
|
openPortal()
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleSelectVariable = useCallback((variable: string[]) => {
|
eventEmitter?.useSubscription((v: any) => {
|
||||||
editor.dispatchCommand(INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND, variable)
|
if (v.type === MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||||
closePortal()
|
handleSelectVariable(v.variable)
|
||||||
}, [editor, closePortal])
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return editor.registerUpdateListener(({ editorState }) => {
|
return editor.registerUpdateListener(({ editorState }) => {
|
||||||
@ -245,7 +255,7 @@ export default function MemoryPopupPlugin({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='system-xs-medium flex items-center gap-1 border-t border-divider-subtle px-4 py-2 text-text-accent-light-mode-only'>
|
<div className='system-xs-medium flex cursor-pointer items-center gap-1 border-t border-divider-subtle px-4 py-2 text-text-accent-light-mode-only' onClick={handleCreate}>
|
||||||
<RiAddLine className='h-4 w-4' />
|
<RiAddLine className='h-4 w-4' />
|
||||||
<div>{t('workflow.nodes.llm.memory.createButton')}</div>
|
<div>{t('workflow.nodes.llm.memory.createButton')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,9 +2,6 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import { Memory } from '@/app/components/base/icons/src/vender/line/others'
|
import { Memory } from '@/app/components/base/icons/src/vender/line/others'
|
||||||
|
|
||||||
export const MEMORY_POPUP_SHOW_BY_EVENT_EMITTER = 'MEMORY_POPUP_SHOW_BY_EVENT_EMITTER'
|
|
||||||
export const PROMPT_EDITOR_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onAddMemory: () => void
|
onAddMemory: () => void
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,10 +36,12 @@ import Switch from '@/app/components/base/switch'
|
|||||||
import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
|
import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
|
||||||
import { useStore } from '@/app/components/workflow/store'
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
import { useWorkflowVariableType } from '@/app/components/workflow/hooks'
|
import { useWorkflowVariableType } from '@/app/components/workflow/hooks'
|
||||||
import AddMemoryButton, { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from './add-memory-button'
|
import AddMemoryButton from './add-memory-button'
|
||||||
|
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from './type'
|
||||||
import type {
|
import type {
|
||||||
ConversationVariable,
|
ConversationVariable,
|
||||||
} from '@/app/components/workflow/types'
|
} from '@/app/components/workflow/types'
|
||||||
|
import MemoryCreateButton from '@/app/components/workflow/nodes/llm/components/memory-system/memory-create-button'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string
|
className?: string
|
||||||
@ -169,175 +171,178 @@ const Editor: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}>
|
<>
|
||||||
<div ref={ref} className={cn(isFocus ? (gradientBorder && 'bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2') : 'bg-transparent', isExpand && 'h-full', '!rounded-[9px] p-0.5', containerClassName)}>
|
<Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}>
|
||||||
<div className={cn(isFocus ? 'bg-background-default' : 'bg-components-input-bg-normal', isExpand && 'flex h-full flex-col', 'rounded-lg', containerClassName)}>
|
<div ref={ref} className={cn(isFocus ? (gradientBorder && 'bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2') : 'bg-transparent', isExpand && 'h-full', '!rounded-[9px] p-0.5', containerClassName)}>
|
||||||
<div className={cn('flex items-center justify-between pl-3 pr-2 pt-1', headerClassName)}>
|
<div className={cn(isFocus ? 'bg-background-default' : 'bg-components-input-bg-normal', isExpand && 'flex h-full flex-col', 'rounded-lg', containerClassName)}>
|
||||||
<div className='flex gap-2'>
|
<div className={cn('flex items-center justify-between pl-3 pr-2 pt-1', headerClassName)}>
|
||||||
<div className={cn('text-xs font-semibold uppercase leading-4 text-text-secondary', titleClassName)}>{title} {required && <span className='text-text-destructive'>*</span>}</div>
|
<div className='flex gap-2'>
|
||||||
{titleTooltip && <Tooltip popupContent={titleTooltip} />}
|
<div className={cn('text-xs font-semibold uppercase leading-4 text-text-secondary', titleClassName)}>{title} {required && <span className='text-text-destructive'>*</span>}</div>
|
||||||
</div>
|
{titleTooltip && <Tooltip popupContent={titleTooltip} />}
|
||||||
<div className='flex items-center'>
|
|
||||||
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
|
|
||||||
{isSupportPromptGenerator && (
|
|
||||||
<PromptGeneratorBtn
|
|
||||||
nodeId={nodeId!}
|
|
||||||
editorId={editorId}
|
|
||||||
className='ml-[5px]'
|
|
||||||
onGenerated={onGenerated}
|
|
||||||
modelConfig={modelConfig}
|
|
||||||
currentPrompt={value}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div>
|
|
||||||
{/* Operations */}
|
|
||||||
<div className='flex items-center space-x-[2px]'>
|
|
||||||
{isSupportJinja && (
|
|
||||||
<Tooltip
|
|
||||||
popupContent={
|
|
||||||
<div>
|
|
||||||
<div>{t('workflow.common.enableJinja')}</div>
|
|
||||||
<a className='text-text-accent' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className={cn(editionType === EditionType.jinja2 && 'border-components-button-ghost-bg-hover bg-components-button-ghost-bg-hover', 'flex h-[22px] items-center space-x-0.5 rounded-[5px] border border-transparent px-1.5 hover:border-components-button-ghost-bg-hover')}>
|
|
||||||
<Jinja className='h-3 w-6 text-text-quaternary' />
|
|
||||||
<Switch
|
|
||||||
size='sm'
|
|
||||||
defaultValue={editionType === EditionType.jinja2}
|
|
||||||
onChange={(checked) => {
|
|
||||||
onEditionTypeChange?.(checked ? EditionType.jinja2 : EditionType.basic)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
)}
|
|
||||||
{!readOnly && (
|
|
||||||
<Tooltip
|
|
||||||
popupContent={`${t('workflow.common.insertVarTip')}`}
|
|
||||||
>
|
|
||||||
<ActionButton onClick={handleInsertVariable}>
|
|
||||||
<Variable02 className='h-4 w-4' />
|
|
||||||
</ActionButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
{showRemove && (
|
|
||||||
<ActionButton onClick={onRemove}>
|
|
||||||
<RiDeleteBinLine className='h-4 w-4' />
|
|
||||||
</ActionButton>
|
|
||||||
)}
|
|
||||||
{!isCopied
|
|
||||||
? (
|
|
||||||
<ActionButton onClick={handleCopy}>
|
|
||||||
<Copy className='h-4 w-4' />
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
<ActionButton>
|
|
||||||
<CopyCheck className='h-4 w-4' />
|
|
||||||
</ActionButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className='flex items-center'>
|
||||||
</div>
|
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
|
||||||
</div>
|
{isSupportPromptGenerator && (
|
||||||
|
<PromptGeneratorBtn
|
||||||
{/* Min: 80 Max: 560. Header: 24 */}
|
nodeId={nodeId!}
|
||||||
<div className={cn('pb-2', isExpand && 'flex grow flex-col', isMemorySupported && isFocus && 'pb-1.5')}>
|
editorId={editorId}
|
||||||
{!(isSupportJinja && editionType === EditionType.jinja2)
|
className='ml-[5px]'
|
||||||
? (
|
onGenerated={onGenerated}
|
||||||
<>
|
modelConfig={modelConfig}
|
||||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
currentPrompt={value}
|
||||||
<PromptEditor
|
|
||||||
key={controlPromptEditorRerenderKey}
|
|
||||||
placeholder={placeholder}
|
|
||||||
placeholderClassName={placeholderClassName}
|
|
||||||
instanceId={instanceId}
|
|
||||||
compact
|
|
||||||
className={cn('min-h-[56px]', inputClassName)}
|
|
||||||
style={isExpand ? { height: editorExpandHeight - 5 } : {}}
|
|
||||||
value={value}
|
|
||||||
contextBlock={{
|
|
||||||
show: justVar ? false : isShowContext,
|
|
||||||
selectable: !hasSetBlockStatus?.context,
|
|
||||||
canNotAddContext: true,
|
|
||||||
}}
|
|
||||||
historyBlock={{
|
|
||||||
show: justVar ? false : isShowHistory,
|
|
||||||
selectable: !hasSetBlockStatus?.history,
|
|
||||||
history: {
|
|
||||||
user: 'Human',
|
|
||||||
assistant: 'Assistant',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
queryBlock={{
|
|
||||||
show: false, // use [sys.query] instead of query block
|
|
||||||
selectable: false,
|
|
||||||
}}
|
|
||||||
workflowVariableBlock={{
|
|
||||||
show: true,
|
|
||||||
variables: nodesOutputVars || [],
|
|
||||||
getVarType,
|
|
||||||
workflowNodesMap: availableNodes.reduce((acc, node) => {
|
|
||||||
acc[node.id] = {
|
|
||||||
title: node.data.title,
|
|
||||||
type: node.data.type,
|
|
||||||
width: node.width,
|
|
||||||
height: node.height,
|
|
||||||
position: node.position,
|
|
||||||
}
|
|
||||||
if (node.data.type === BlockEnum.Start) {
|
|
||||||
acc.sys = {
|
|
||||||
title: t('workflow.blocks.start'),
|
|
||||||
type: BlockEnum.Start,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, {} as any),
|
|
||||||
showManageInputField: !!pipelineId,
|
|
||||||
onManageInputField: () => setShowInputFieldPanel?.(true),
|
|
||||||
}}
|
|
||||||
onChange={onChange}
|
|
||||||
onBlur={setBlur}
|
|
||||||
onFocus={setFocus}
|
|
||||||
editable={!readOnly}
|
|
||||||
isSupportFileVar={isSupportFileVar}
|
|
||||||
isMemorySupported
|
|
||||||
memoryVarInNode={memoryVarInNode}
|
|
||||||
memoryVarInApp={memoryVarInApp}
|
|
||||||
/>
|
|
||||||
{/* to patch Editor not support dynamic change editable status */}
|
|
||||||
{readOnly && <div className='absolute inset-0 z-10'></div>}
|
|
||||||
</div>
|
|
||||||
{isMemorySupported && <AddMemoryButton onAddMemory={handleAddMemory} />}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
|
||||||
<CodeEditor
|
|
||||||
availableVars={nodesOutputVars || []}
|
|
||||||
varList={varList}
|
|
||||||
onAddVar={handleAddVariable}
|
|
||||||
isInNode
|
|
||||||
readOnly={readOnly}
|
|
||||||
language={CodeLanguage.python3}
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
noWrapper
|
|
||||||
isExpand={isExpand}
|
|
||||||
className={inputClassName}
|
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div>
|
||||||
|
{/* Operations */}
|
||||||
|
<div className='flex items-center space-x-[2px]'>
|
||||||
|
{isSupportJinja && (
|
||||||
|
<Tooltip
|
||||||
|
popupContent={
|
||||||
|
<div>
|
||||||
|
<div>{t('workflow.common.enableJinja')}</div>
|
||||||
|
<a className='text-text-accent' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={cn(editionType === EditionType.jinja2 && 'border-components-button-ghost-bg-hover bg-components-button-ghost-bg-hover', 'flex h-[22px] items-center space-x-0.5 rounded-[5px] border border-transparent px-1.5 hover:border-components-button-ghost-bg-hover')}>
|
||||||
|
<Jinja className='h-3 w-6 text-text-quaternary' />
|
||||||
|
<Switch
|
||||||
|
size='sm'
|
||||||
|
defaultValue={editionType === EditionType.jinja2}
|
||||||
|
onChange={(checked) => {
|
||||||
|
onEditionTypeChange?.(checked ? EditionType.jinja2 : EditionType.basic)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
)}
|
||||||
|
{!readOnly && (
|
||||||
|
<Tooltip
|
||||||
|
popupContent={`${t('workflow.common.insertVarTip')}`}
|
||||||
|
>
|
||||||
|
<ActionButton onClick={handleInsertVariable}>
|
||||||
|
<Variable02 className='h-4 w-4' />
|
||||||
|
</ActionButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{showRemove && (
|
||||||
|
<ActionButton onClick={onRemove}>
|
||||||
|
<RiDeleteBinLine className='h-4 w-4' />
|
||||||
|
</ActionButton>
|
||||||
|
)}
|
||||||
|
{!isCopied
|
||||||
|
? (
|
||||||
|
<ActionButton onClick={handleCopy}>
|
||||||
|
<Copy className='h-4 w-4' />
|
||||||
|
</ActionButton>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<ActionButton>
|
||||||
|
<CopyCheck className='h-4 w-4' />
|
||||||
|
</ActionButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Min: 80 Max: 560. Header: 24 */}
|
||||||
|
<div className={cn('pb-2', isExpand && 'flex grow flex-col', isMemorySupported && isFocus && 'pb-1.5')}>
|
||||||
|
{!(isSupportJinja && editionType === EditionType.jinja2)
|
||||||
|
? (
|
||||||
|
<>
|
||||||
|
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||||
|
<PromptEditor
|
||||||
|
key={controlPromptEditorRerenderKey}
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderClassName={placeholderClassName}
|
||||||
|
instanceId={instanceId}
|
||||||
|
compact
|
||||||
|
className={cn('min-h-[56px]', inputClassName)}
|
||||||
|
style={isExpand ? { height: editorExpandHeight - 5 } : {}}
|
||||||
|
value={value}
|
||||||
|
contextBlock={{
|
||||||
|
show: justVar ? false : isShowContext,
|
||||||
|
selectable: !hasSetBlockStatus?.context,
|
||||||
|
canNotAddContext: true,
|
||||||
|
}}
|
||||||
|
historyBlock={{
|
||||||
|
show: justVar ? false : isShowHistory,
|
||||||
|
selectable: !hasSetBlockStatus?.history,
|
||||||
|
history: {
|
||||||
|
user: 'Human',
|
||||||
|
assistant: 'Assistant',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
queryBlock={{
|
||||||
|
show: false, // use [sys.query] instead of query block
|
||||||
|
selectable: false,
|
||||||
|
}}
|
||||||
|
workflowVariableBlock={{
|
||||||
|
show: true,
|
||||||
|
variables: nodesOutputVars || [],
|
||||||
|
getVarType,
|
||||||
|
workflowNodesMap: availableNodes.reduce((acc, node) => {
|
||||||
|
acc[node.id] = {
|
||||||
|
title: node.data.title,
|
||||||
|
type: node.data.type,
|
||||||
|
width: node.width,
|
||||||
|
height: node.height,
|
||||||
|
position: node.position,
|
||||||
|
}
|
||||||
|
if (node.data.type === BlockEnum.Start) {
|
||||||
|
acc.sys = {
|
||||||
|
title: t('workflow.blocks.start'),
|
||||||
|
type: BlockEnum.Start,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, {} as any),
|
||||||
|
showManageInputField: !!pipelineId,
|
||||||
|
onManageInputField: () => setShowInputFieldPanel?.(true),
|
||||||
|
}}
|
||||||
|
onChange={onChange}
|
||||||
|
onBlur={setBlur}
|
||||||
|
onFocus={setFocus}
|
||||||
|
editable={!readOnly}
|
||||||
|
isSupportFileVar={isSupportFileVar}
|
||||||
|
isMemorySupported
|
||||||
|
memoryVarInNode={memoryVarInNode}
|
||||||
|
memoryVarInApp={memoryVarInApp}
|
||||||
|
/>
|
||||||
|
{/* to patch Editor not support dynamic change editable status */}
|
||||||
|
{readOnly && <div className='absolute inset-0 z-10'></div>}
|
||||||
|
</div>
|
||||||
|
{isMemorySupported && <AddMemoryButton onAddMemory={handleAddMemory} />}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||||
|
<CodeEditor
|
||||||
|
availableVars={nodesOutputVars || []}
|
||||||
|
varList={varList}
|
||||||
|
onAddVar={handleAddVariable}
|
||||||
|
isInNode
|
||||||
|
readOnly={readOnly}
|
||||||
|
language={CodeLanguage.python3}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
noWrapper
|
||||||
|
isExpand={isExpand}
|
||||||
|
className={inputClassName}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Wrap>
|
||||||
</Wrap>
|
{isMemorySupported && <MemoryCreateButton instanceId={instanceId} hideTrigger />}
|
||||||
|
</>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
export const MEMORY_POPUP_SHOW_BY_EVENT_EMITTER = 'MEMORY_POPUP_SHOW_BY_EVENT_EMITTER'
|
||||||
|
export const MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER = 'MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER'
|
||||||
|
export const MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER = 'MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER'
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { useCallback, useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import { RiAddLine } from '@remixicon/react'
|
import { RiAddLine } from '@remixicon/react'
|
||||||
import VariableModal from '@/app/components/workflow/panel/chat-variable-panel/components/variable-modal'
|
import VariableModal from '@/app/components/workflow/panel/chat-variable-panel/components/variable-modal'
|
||||||
|
import type { OffsetOptions, Placement } from '@floating-ui/react'
|
||||||
import {
|
import {
|
||||||
PortalToFollowElem,
|
PortalToFollowElem,
|
||||||
PortalToFollowElemContent,
|
PortalToFollowElemContent,
|
||||||
@ -11,8 +12,23 @@ import type { ConversationVariable } from '@/app/components/workflow/types'
|
|||||||
import { useStore } from '@/app/components/workflow/store'
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
|
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
|
||||||
import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars-crud'
|
import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars-crud'
|
||||||
|
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||||
|
import { MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/type'
|
||||||
|
|
||||||
const MemoryCreateButton = () => {
|
type Props = {
|
||||||
|
placement?: Placement
|
||||||
|
offset?: number | OffsetOptions
|
||||||
|
hideTrigger?: boolean
|
||||||
|
instanceId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const MemoryCreateButton = ({
|
||||||
|
placement,
|
||||||
|
offset,
|
||||||
|
hideTrigger,
|
||||||
|
instanceId,
|
||||||
|
}: Props) => {
|
||||||
|
const { eventEmitter } = useEventEmitterContextContext()
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
||||||
const updateChatVarList = useStore(s => s.setConversationVariables)
|
const updateChatVarList = useStore(s => s.setConversationVariables)
|
||||||
@ -34,19 +50,30 @@ const MemoryCreateButton = () => {
|
|||||||
updateChatVarList(newList)
|
updateChatVarList(newList)
|
||||||
handleVarChanged()
|
handleVarChanged()
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
}, [varList, updateChatVarList, handleVarChanged, setOpen])
|
if (instanceId)
|
||||||
|
eventEmitter?.emit({ type: MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, instanceId, variable: ['conversation', newChatVar.name] } as any)
|
||||||
|
}, [varList, updateChatVarList, handleVarChanged, setOpen, eventEmitter, instanceId])
|
||||||
|
|
||||||
|
eventEmitter?.useSubscription((v: any) => {
|
||||||
|
if (v.type === MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||||
|
setOpen(true)
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PortalToFollowElem
|
<PortalToFollowElem
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
placement='left'
|
placement={placement || 'left'}
|
||||||
|
offset={offset}
|
||||||
>
|
>
|
||||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
||||||
<ActionButton className='shrink-0'>
|
{hideTrigger && <div></div>}
|
||||||
<RiAddLine className='h-4 w-4' />
|
{!hideTrigger && (
|
||||||
</ActionButton>
|
<ActionButton className='shrink-0'>
|
||||||
|
<RiAddLine className='h-4 w-4' />
|
||||||
|
</ActionButton>
|
||||||
|
)}
|
||||||
</PortalToFollowElemTrigger>
|
</PortalToFollowElemTrigger>
|
||||||
<PortalToFollowElemContent className='z-[11]'>
|
<PortalToFollowElemContent className='z-[11]'>
|
||||||
<VariableModal
|
<VariableModal
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user