From 7222a896d848d03b531eeba0bd7d242afe32123b Mon Sep 17 00:00:00 2001 From: zhsama Date: Fri, 16 Jan 2026 15:01:11 +0800 Subject: [PATCH 1/2] Align warning styles for agent mentions --- .../agent-header-bar.tsx | 18 ++++++- .../mixed-variable-text-input/index.tsx | 50 ++++++++++++++++++- .../components/workflow/nodes/tool/node.tsx | 5 +- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx index f956188474..f5edd80f89 100644 --- a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx +++ b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx @@ -2,25 +2,36 @@ import type { FC } from 'react' import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react' import { memo } from 'react' import { useTranslation } from 'react-i18next' +import AlertTriangle from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback/AlertTriangle' import { Agent } from '@/app/components/base/icons/src/vender/workflow' +import { cn } from '@/utils/classnames' type AgentHeaderBarProps = { agentName: string onRemove: () => void onViewInternals?: () => void + hasWarning?: boolean } const AgentHeaderBar: FC = ({ agentName, onRemove, onViewInternals, + hasWarning, }) => { const { t } = useTranslation() return (
-
+
@@ -39,11 +50,14 @@ const AgentHeaderBar: FC = ({
) diff --git a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx index eec880bd77..1e3848bf48 100644 --- a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx +++ b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/index.tsx @@ -1,5 +1,6 @@ import type { AgentNode } from '@/app/components/base/prompt-editor/types' import type { MentionConfig, VarKindType } from '@/app/components/workflow/nodes/_base/types' +import type { AgentNodeType } from '@/app/components/workflow/nodes/agent/types' import type { LLMNodeType } from '@/app/components/workflow/nodes/llm/types' import type { Node, @@ -15,7 +16,7 @@ import { useState, } from 'react' import { useTranslation } from 'react-i18next' -import { useStoreApi } from 'reactflow' +import { useStore as useReactflowStore, useStoreApi } from 'reactflow' import PromptEditor from '@/app/components/base/prompt-editor' import { useNodesMetaData, useNodesSyncDraft } from '@/app/components/workflow/hooks' import { VarKindType as VarKindTypeEnum } from '@/app/components/workflow/nodes/_base/types' @@ -23,6 +24,8 @@ import { Type } from '@/app/components/workflow/nodes/llm/types' import { useStore } from '@/app/components/workflow/store' import { BlockEnum, EditionType, isPromptMessageContext, PromptRole } from '@/app/components/workflow/types' import { generateNewNode, getNodeCustomTypeByNodeDataType } from '@/app/components/workflow/utils' +import { useGetLanguage } from '@/context/i18n' +import { useStrategyProviders } from '@/service/use-strategy' import { cn } from '@/utils/classnames' import SubGraphModal from '../sub-graph-modal' import AgentHeaderBar from './agent-header-bar' @@ -137,7 +140,10 @@ const MixedVariableTextInput = ({ paramKey = '', }: MixedVariableTextInputProps) => { const { t } = useTranslation() + const language = useGetLanguage() + const { data: strategyProviders } = useStrategyProviders() const reactFlowStore = useStoreApi() + const nodes = useReactflowStore(state => state.nodes) const controlPromptEditorRerenderKey = useStore(s => s.controlPromptEditorRerenderKey) const setControlPromptEditorRerenderKey = useStore(s => s.setControlPromptEditorRerenderKey) const { nodesMap: nodesMetaDataMap } = useNodesMetaData() @@ -151,6 +157,13 @@ const MixedVariableTextInput = ({ }, {} as Record) }, [availableNodes]) + const nodesById = useMemo(() => { + return nodes.reduce((acc, node) => { + acc[node.id] = node + return acc + }, {} as Record) + }, [nodes]) + type DetectedAgent = { nodeId: string name: string @@ -188,6 +201,40 @@ const MixedVariableTextInput = ({ })) }, [availableNodes]) + const getNodeWarning = useCallback((node?: Node) => { + if (!node) + return true + const validator = nodesMetaDataMap?.[node.data.type as BlockEnum]?.checkValid + if (!validator) + return false + let moreDataForCheckValid: any + if (node.data.type === BlockEnum.Agent) { + const agentData = node.data as AgentNodeType + const isReadyForCheckValid = !!strategyProviders + const provider = strategyProviders?.find(provider => provider.declaration.identity.name === agentData.agent_strategy_provider_name) + const strategy = provider?.declaration.strategies?.find(s => s.identity.name === agentData.agent_strategy_name) + moreDataForCheckValid = { + provider, + strategy, + language, + isReadyForCheckValid, + } + } + const { errorMessage } = validator(node.data as any, t, moreDataForCheckValid) + return Boolean(errorMessage) + }, [language, nodesMetaDataMap, strategyProviders, t]) + + const hasAgentWarning = useMemo(() => { + if (!detectedAgentFromValue) + return false + const agentWarning = getNodeWarning(nodesById[detectedAgentFromValue.nodeId]) + if (!toolNodeId || !paramKey) + return agentWarning + const extractorNodeId = `${toolNodeId}_ext_${paramKey}` + const extractorWarning = getNodeWarning(nodesById[extractorNodeId]) + return agentWarning || extractorWarning + }, [detectedAgentFromValue, getNodeWarning, nodesById, paramKey, toolNodeId]) + const syncExtractorPromptFromText = useCallback((text: string) => { if (!toolNodeId || !paramKey) return @@ -341,6 +388,7 @@ const MixedVariableTextInput = ({ agentName={detectedAgentFromValue.name} onRemove={handleAgentRemove} onViewInternals={handleOpenSubGraphModal} + hasWarning={hasAgentWarning} /> )} > = ({ {referenceItems.map(item => (
Date: Fri, 16 Jan 2026 15:09:42 +0800 Subject: [PATCH 2/2] Use warning token borders for mentions --- .../mixed-variable-text-input/agent-header-bar.tsx | 2 +- web/app/components/workflow/nodes/tool/node.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx index f5edd80f89..dcb46f78d2 100644 --- a/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx +++ b/web/app/components/workflow/nodes/tool/components/mixed-variable-text-input/agent-header-bar.tsx @@ -28,7 +28,7 @@ const AgentHeaderBar: FC = ({ className={cn( 'flex items-center gap-1 rounded-md border-[0.5px] px-1.5 py-0.5 shadow-xs', hasWarning - ? 'border-components-badge-status-light-warning-border-inner bg-components-badge-status-light-warning-halo' + ? 'border-text-warning-secondary bg-components-badge-status-light-warning-halo' : 'border-components-panel-border-subtle bg-components-badge-white-to-dark', )} > diff --git a/web/app/components/workflow/nodes/tool/node.tsx b/web/app/components/workflow/nodes/tool/node.tsx index 938aa51b4b..9535b3fbb6 100644 --- a/web/app/components/workflow/nodes/tool/node.tsx +++ b/web/app/components/workflow/nodes/tool/node.tsx @@ -191,8 +191,10 @@ const Node: FC> = ({