mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
feat: Enhance sub-graph components with context handling and variable management
This commit is contained in:
@ -67,6 +67,9 @@ const ConfigPanel: FC<ConfigPanelProps> = ({
|
||||
description: t('subGraphModal.whenOutputNone.defaultDesc', { ns: 'workflow' }),
|
||||
},
|
||||
]), [t])
|
||||
const selectedWhenOutputNoneOption = useMemo(() => (
|
||||
whenOutputNoneOptions.find(item => item.value === mentionConfig.null_strategy) ?? whenOutputNoneOptions[0]
|
||||
), [mentionConfig.null_strategy, whenOutputNoneOptions])
|
||||
|
||||
const handleNullStrategyChange = useCallback((item: Item) => {
|
||||
if (typeof item.value !== 'string')
|
||||
@ -94,6 +97,8 @@ const ConfigPanel: FC<ConfigPanelProps> = ({
|
||||
default_value: nextValue,
|
||||
})
|
||||
}, [mentionConfig, onMentionConfigChange])
|
||||
const defaultValue = mentionConfig.default_value ?? ''
|
||||
const shouldFormatDefaultValue = typeof defaultValue !== 'string'
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
@ -131,45 +136,54 @@ const ConfigPanel: FC<ConfigPanelProps> = ({
|
||||
</Field>
|
||||
</div>
|
||||
<div className="space-y-4 px-4 py-4">
|
||||
<Field title={t('subGraphModal.whenOutputIsNone', { ns: 'workflow' })}>
|
||||
<SimpleSelect
|
||||
items={whenOutputNoneOptions}
|
||||
defaultValue={mentionConfig.null_strategy}
|
||||
allowSearch={false}
|
||||
notClearable
|
||||
onSelect={handleNullStrategyChange}
|
||||
renderOption={({ item, selected }) => (
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
{selected && (
|
||||
<RiCheckLine className="h-4 w-4 text-[14px] text-text-accent" />
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="system-sm-medium text-text-secondary">{item.name}</div>
|
||||
<div className="system-xs-regular mt-0.5 text-text-tertiary">{item.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</Field>
|
||||
{mentionConfig.null_strategy === 'use_default' && (
|
||||
<div>
|
||||
<div className="system-xs-regular text-text-tertiary">
|
||||
{t('subGraphModal.defaultValueHint', { ns: 'workflow' })}
|
||||
</div>
|
||||
<div className={cn('mt-2 overflow-hidden rounded-lg border border-components-input-border-active bg-components-input-bg-normal p-1')}>
|
||||
<CodeEditor
|
||||
noWrapper
|
||||
language={CodeLanguage.json}
|
||||
value={mentionConfig.default_value ?? ''}
|
||||
onChange={handleDefaultValueChange}
|
||||
isJSONStringifyBeauty
|
||||
className="min-h-[160px]"
|
||||
<Field
|
||||
title={t('subGraphModal.whenOutputIsNone', { ns: 'workflow' })}
|
||||
operations={(
|
||||
<div className="flex items-center">
|
||||
<SimpleSelect
|
||||
items={whenOutputNoneOptions}
|
||||
defaultValue={mentionConfig.null_strategy}
|
||||
allowSearch={false}
|
||||
notClearable
|
||||
wrapperClassName="min-w-[160px]"
|
||||
onSelect={handleNullStrategyChange}
|
||||
renderOption={({ item, selected }) => (
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
{selected && (
|
||||
<RiCheckLine className="h-4 w-4 text-[14px] text-text-accent" />
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="system-sm-medium text-text-secondary">{item.name}</div>
|
||||
<div className="system-xs-regular mt-0.5 text-text-tertiary">{item.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
{selectedWhenOutputNoneOption?.description && (
|
||||
<div className="system-xs-regular text-text-tertiary">
|
||||
{selectedWhenOutputNoneOption.description}
|
||||
</div>
|
||||
)}
|
||||
{mentionConfig.null_strategy === 'use_default' && (
|
||||
<div className={cn('overflow-hidden rounded-lg border border-components-input-border-active bg-components-input-bg-normal p-1')}>
|
||||
<CodeEditor
|
||||
noWrapper
|
||||
language={CodeLanguage.json}
|
||||
value={defaultValue}
|
||||
onChange={handleDefaultValueChange}
|
||||
isJSONStringifyBeauty={shouldFormatDefaultValue}
|
||||
className="min-h-[160px]"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,12 +2,13 @@ import type { FC } from 'react'
|
||||
import type { Viewport } from 'reactflow'
|
||||
import type { SubGraphProps } from './types'
|
||||
import type { InjectWorkflowStoreSliceFn } from '@/app/components/workflow/store'
|
||||
import type { PromptItem } from '@/app/components/workflow/types'
|
||||
import { memo, useMemo } from 'react'
|
||||
import type { PromptItem, PromptTemplateItem } from '@/app/components/workflow/types'
|
||||
import { memo, useEffect, useMemo } from 'react'
|
||||
import WorkflowWithDefaultContext from '@/app/components/workflow'
|
||||
import { NODE_WIDTH_X_OFFSET, START_INITIAL_POSITION } from '@/app/components/workflow/constants'
|
||||
import { WorkflowContextProvider } from '@/app/components/workflow/context'
|
||||
import { BlockEnum, EditionType, PromptRole } from '@/app/components/workflow/types'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { BlockEnum, EditionType, isPromptMessageContext, PromptRole } from '@/app/components/workflow/types'
|
||||
import SubGraphMain from './components/sub-graph-main'
|
||||
import { useSubGraphNodes } from './hooks'
|
||||
import { createSubGraphSlice } from './store'
|
||||
@ -38,9 +39,19 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
onMentionConfigChange,
|
||||
extractorNode,
|
||||
toolParamValue,
|
||||
parentAvailableNodes,
|
||||
parentAvailableVars,
|
||||
onSave,
|
||||
} = props
|
||||
|
||||
const setParentAvailableVars = useStore(state => state.setParentAvailableVars)
|
||||
const setParentAvailableNodes = useStore(state => state.setParentAvailableNodes)
|
||||
|
||||
useEffect(() => {
|
||||
setParentAvailableVars?.(parentAvailableVars || [])
|
||||
setParentAvailableNodes?.(parentAvailableNodes || [])
|
||||
}, [parentAvailableNodes, parentAvailableVars, setParentAvailableNodes, setParentAvailableVars])
|
||||
|
||||
const promptText = useMemo(() => {
|
||||
if (!toolParamValue)
|
||||
return ''
|
||||
@ -95,16 +106,18 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
if (!Array.isArray(template))
|
||||
return applyPromptText(template as PromptItem)
|
||||
|
||||
const userIndex = template.findIndex(item => item.role === PromptRole.user)
|
||||
const promptItems = template.filter((item): item is PromptItem => !isPromptMessageContext(item))
|
||||
|
||||
const userIndex = promptItems.findIndex(item => item.role === PromptRole.user)
|
||||
if (userIndex >= 0) {
|
||||
return template.map((item, index) => {
|
||||
return promptItems.map((item, index) => {
|
||||
if (index !== userIndex)
|
||||
return item
|
||||
return applyPromptText(item)
|
||||
})
|
||||
}) as PromptTemplateItem[]
|
||||
}
|
||||
|
||||
const useJinja = template.some((item: PromptItem) => item.edition_type === EditionType.jinja2)
|
||||
const useJinja = promptItems.some((item: PromptItem) => item.edition_type === EditionType.jinja2)
|
||||
const defaultUserPrompt: PromptItem = useJinja
|
||||
? {
|
||||
role: PromptRole.user,
|
||||
@ -113,13 +126,13 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
edition_type: EditionType.jinja2,
|
||||
}
|
||||
: { role: PromptRole.user, text: promptText }
|
||||
const systemIndex = template.findIndex(item => item.role === PromptRole.system)
|
||||
const nextTemplate = [...template]
|
||||
const systemIndex = promptItems.findIndex(item => item.role === PromptRole.system)
|
||||
const nextTemplate = [...promptItems]
|
||||
if (systemIndex >= 0)
|
||||
nextTemplate.splice(systemIndex + 1, 0, defaultUserPrompt)
|
||||
else
|
||||
nextTemplate.unshift(defaultUserPrompt)
|
||||
return nextTemplate
|
||||
return nextTemplate as PromptTemplateItem[]
|
||||
})()
|
||||
|
||||
return {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { CreateSubGraphSlice, SubGraphSliceShape } from '../types'
|
||||
|
||||
const initialState: Omit<SubGraphSliceShape, 'setSubGraphContext' | 'setSubGraphNodes' | 'setSubGraphEdges' | 'setSelectedOutputVar' | 'setWhenOutputNone' | 'setDefaultValue' | 'setShowDebugPanel' | 'setIsRunning' | 'setParentAvailableVars' | 'resetSubGraph'> = {
|
||||
const initialState: Omit<SubGraphSliceShape, 'setSubGraphContext' | 'setSubGraphNodes' | 'setSubGraphEdges' | 'setSelectedOutputVar' | 'setWhenOutputNone' | 'setDefaultValue' | 'setShowDebugPanel' | 'setIsRunning' | 'setParentAvailableVars' | 'setParentAvailableNodes' | 'resetSubGraph'> = {
|
||||
parentToolNodeId: '',
|
||||
parameterKey: '',
|
||||
sourceAgentNodeId: '',
|
||||
@ -18,6 +18,7 @@ const initialState: Omit<SubGraphSliceShape, 'setSubGraphContext' | 'setSubGraph
|
||||
isRunning: false,
|
||||
|
||||
parentAvailableVars: [],
|
||||
parentAvailableNodes: [],
|
||||
}
|
||||
|
||||
export const createSubGraphSlice: CreateSubGraphSlice = set => ({
|
||||
@ -46,5 +47,7 @@ export const createSubGraphSlice: CreateSubGraphSlice = set => ({
|
||||
|
||||
setParentAvailableVars: vars => set(() => ({ parentAvailableVars: vars })),
|
||||
|
||||
setParentAvailableNodes: nodes => set(() => ({ parentAvailableNodes: nodes })),
|
||||
|
||||
resetSubGraph: () => set(() => ({ ...initialState })),
|
||||
})
|
||||
|
||||
@ -31,6 +31,8 @@ export type SubGraphProps = {
|
||||
onMentionConfigChange: (config: MentionConfig) => void
|
||||
extractorNode?: Node<LLMNodeType>
|
||||
toolParamValue?: string
|
||||
parentAvailableNodes?: Node[]
|
||||
parentAvailableVars?: NodeOutPutVar[]
|
||||
onSave?: (nodes: Node[], edges: Edge[]) => void
|
||||
}
|
||||
|
||||
@ -52,6 +54,7 @@ export type SubGraphSliceShape = {
|
||||
isRunning: boolean
|
||||
|
||||
parentAvailableVars: NodeOutPutVar[]
|
||||
parentAvailableNodes: Node[]
|
||||
|
||||
setSubGraphContext: (context: {
|
||||
parentToolNodeId: string
|
||||
@ -67,6 +70,7 @@ export type SubGraphSliceShape = {
|
||||
setShowDebugPanel: (show: boolean) => void
|
||||
setIsRunning: (running: boolean) => void
|
||||
setParentAvailableVars: (vars: NodeOutPutVar[]) => void
|
||||
setParentAvailableNodes: (nodes: Node[]) => void
|
||||
resetSubGraph: () => void
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user