mirror of
https://github.com/langgenius/dify.git
synced 2026-03-28 23:00:25 -04:00
- refactor config-modal, create-from-dsl-modal, and sub-graph for lower complexity - add missing tests for config-modal-body, sandbox-provider-page, and install-bundle flows - raise targeted worktree source coverage to 90%+ for lines and statements
170 lines
5.4 KiB
TypeScript
170 lines
5.4 KiB
TypeScript
import type { AgentSubGraphProps, AssembleSubGraphProps, SubGraphProps } from './types'
|
|
import type { CodeNodeType } from '@/app/components/workflow/nodes/code/types'
|
|
import type { LLMNodeType } from '@/app/components/workflow/nodes/llm/types'
|
|
import type { Node, PromptItem, PromptTemplateItem } from '@/app/components/workflow/types'
|
|
import { NODE_WIDTH_X_OFFSET, START_INITIAL_POSITION } from '@/app/components/workflow/constants'
|
|
import { CUSTOM_SUB_GRAPH_START_NODE } from '@/app/components/workflow/nodes/sub-graph-start/constants'
|
|
import { BlockEnum, EditionType, isPromptMessageContext, PromptRole } from '@/app/components/workflow/types'
|
|
|
|
const SUB_GRAPH_EDGE_GAP = 160
|
|
|
|
export const defaultViewport = {
|
|
x: SUB_GRAPH_EDGE_GAP,
|
|
y: 50,
|
|
zoom: 1,
|
|
} as const
|
|
|
|
export const SUB_GRAPH_ENTRY_POSITION = {
|
|
x: START_INITIAL_POSITION.x,
|
|
y: 150,
|
|
} as const
|
|
|
|
export const SUB_GRAPH_EXTRACTOR_POSITION = {
|
|
x: SUB_GRAPH_ENTRY_POSITION.x + NODE_WIDTH_X_OFFSET - SUB_GRAPH_EDGE_GAP,
|
|
y: SUB_GRAPH_ENTRY_POSITION.y,
|
|
} as const
|
|
|
|
export const getSubGraphSourceTitle = (props: SubGraphProps) => (
|
|
props.variant === 'agent' ? (props.agentName || '') : (props.title || '')
|
|
)
|
|
|
|
export const getSubGraphExtractorNodeId = (props: SubGraphProps) => (
|
|
`${props.toolNodeId}_ext_${props.paramKey}`
|
|
)
|
|
|
|
const escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
|
|
export const getSubGraphPromptText = (props: SubGraphProps) => {
|
|
if (props.variant !== 'agent' || !props.toolParamValue)
|
|
return ''
|
|
|
|
const leadingPattern = new RegExp(`^\\{\\{[@#]${escapeRegExp(props.agentNodeId)}\\.context[@#]\\}\\}`)
|
|
return props.toolParamValue.replace(leadingPattern, '')
|
|
}
|
|
|
|
export const buildSubGraphStartNode = (props: SubGraphProps, sourceTitle: string) => ({
|
|
id: 'subgraph-source',
|
|
type: CUSTOM_SUB_GRAPH_START_NODE,
|
|
position: SUB_GRAPH_ENTRY_POSITION,
|
|
data: {
|
|
type: BlockEnum.Start,
|
|
title: sourceTitle,
|
|
desc: '',
|
|
selected: false,
|
|
iconType: props.variant === 'agent' ? 'agent' : 'assemble',
|
|
variables: [],
|
|
},
|
|
selected: false,
|
|
selectable: false,
|
|
draggable: false,
|
|
connectable: false,
|
|
focusable: false,
|
|
deletable: false,
|
|
})
|
|
|
|
const applyPromptText = (item: PromptItem, promptText: string): PromptItem => {
|
|
if (item.edition_type === EditionType.jinja2) {
|
|
return {
|
|
...item,
|
|
text: promptText,
|
|
jinja2_text: promptText,
|
|
}
|
|
}
|
|
|
|
return { ...item, text: promptText }
|
|
}
|
|
|
|
const buildExtractorPromptTemplate = (template: PromptTemplateItem | PromptTemplateItem[], promptText: string) => {
|
|
if (!Array.isArray(template))
|
|
return applyPromptText(template as PromptItem, promptText)
|
|
|
|
const userIndex = template.findIndex(
|
|
item => !isPromptMessageContext(item) && (item as PromptItem).role === PromptRole.user,
|
|
)
|
|
|
|
if (userIndex >= 0) {
|
|
return template.map((item, index) => {
|
|
if (index !== userIndex)
|
|
return item
|
|
return applyPromptText(item as PromptItem, promptText)
|
|
}) as PromptTemplateItem[]
|
|
}
|
|
|
|
const useJinja = template.some(
|
|
item => !isPromptMessageContext(item) && (item as PromptItem).edition_type === EditionType.jinja2,
|
|
)
|
|
const defaultUserPrompt: PromptItem = useJinja
|
|
? {
|
|
role: PromptRole.user,
|
|
text: promptText,
|
|
jinja2_text: promptText,
|
|
edition_type: EditionType.jinja2,
|
|
}
|
|
: { role: PromptRole.user, text: promptText }
|
|
|
|
return [...template, defaultUserPrompt] as PromptTemplateItem[]
|
|
}
|
|
|
|
export function buildSubGraphExtractorDisplayNode(props: AgentSubGraphProps, promptText: string): Node<LLMNodeType> | null
|
|
export function buildSubGraphExtractorDisplayNode(props: AssembleSubGraphProps, promptText: string): Node<CodeNodeType> | null
|
|
export function buildSubGraphExtractorDisplayNode(props: SubGraphProps, promptText: string): Node<LLMNodeType> | Node<CodeNodeType> | null
|
|
export function buildSubGraphExtractorDisplayNode(props: SubGraphProps, promptText: string): Node<LLMNodeType> | Node<CodeNodeType> | null {
|
|
const extractorNode = props.extractorNode
|
|
if (!extractorNode)
|
|
return null
|
|
|
|
if (props.variant !== 'agent') {
|
|
const assembleExtractorNode = extractorNode as Node<CodeNodeType>
|
|
return {
|
|
...assembleExtractorNode,
|
|
hidden: false,
|
|
selected: false,
|
|
position: SUB_GRAPH_EXTRACTOR_POSITION,
|
|
data: {
|
|
...assembleExtractorNode.data,
|
|
selected: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
const agentExtractorNode = extractorNode as Node<LLMNodeType>
|
|
return {
|
|
...agentExtractorNode,
|
|
hidden: false,
|
|
selected: false,
|
|
position: SUB_GRAPH_EXTRACTOR_POSITION,
|
|
data: {
|
|
...agentExtractorNode.data,
|
|
selected: false,
|
|
prompt_template: buildExtractorPromptTemplate(agentExtractorNode.data.prompt_template, promptText),
|
|
},
|
|
}
|
|
}
|
|
|
|
export const buildSubGraphEdges = (
|
|
props: SubGraphProps,
|
|
startNode: ReturnType<typeof buildSubGraphStartNode>,
|
|
extractorDisplayNode: Node<LLMNodeType> | Node<CodeNodeType> | null,
|
|
) => {
|
|
if (!extractorDisplayNode)
|
|
return []
|
|
|
|
return [
|
|
{
|
|
id: `${startNode.id}-${extractorDisplayNode.id}`,
|
|
source: startNode.id,
|
|
sourceHandle: 'source',
|
|
target: extractorDisplayNode.id,
|
|
targetHandle: 'target',
|
|
type: 'custom',
|
|
selectable: false,
|
|
data: {
|
|
sourceType: BlockEnum.Start,
|
|
targetType: props.variant === 'agent' ? BlockEnum.LLM : BlockEnum.Code,
|
|
_isTemp: true,
|
|
_isSubGraphTemp: true,
|
|
},
|
|
},
|
|
]
|
|
}
|