fix(workflow): replace hardcoded trigger node logic with metadata-driven approach

- Add isStart: true to all trigger nodes (TriggerWebhook, TriggerSchedule, TriggerPlugin)
- Replace hardcoded BlockEnum checks in use-checklist.ts with metadata-driven logic
- Update trigger node tests to validate metadata instead of obsolete methods
- Add webhook URL validation to TriggerWebhook node
- Ensure backward compatibility with existing workflow configurations

This change migrates from hardcoded trigger node identification to a
centralized metadata-driven approach, improving maintainability and
consistency across the workflow system.
This commit is contained in:
lyzno1 2025-09-26 22:35:21 +08:00
parent 8feef2c1a9
commit 60c86dd8d1
6 changed files with 23 additions and 23 deletions

View File

@ -27,10 +27,10 @@ import {
} from '../constants'
import {
useGetToolIcon,
useNodesMetaData,
} from '../hooks'
import type { ToolNodeType } from '../nodes/tool/types'
import type { DataSourceNodeType } from '../nodes/data-source/types'
import { useNodesMetaData } from './use-nodes-meta-data'
import { useToastContext } from '@/app/components/base/toast'
import { useGetLanguage } from '@/context/i18n'
import type { AgentNodeType } from '../nodes/agent/types'
@ -132,10 +132,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
// Start nodes and Trigger nodes should not show unConnected error if they have validation errors
// or if they are valid start nodes (even without incoming connections)
const isStartNode = node.data.type === BlockEnum.Start
|| node.data.type === BlockEnum.TriggerSchedule
|| node.data.type === BlockEnum.TriggerWebhook
|| node.data.type === BlockEnum.TriggerPlugin
const isStartNode = nodesExtraData?.[node.data.type as BlockEnum]?.metaData.isStart || false
const isUnconnected = !validNodes.find(n => n.id === node.id)
const shouldShowError = errorMessage || (isUnconnected && !isStartNode)

View File

@ -6,6 +6,7 @@ import type { PluginTriggerNodeType } from './types'
const metaData = genNodeMetaData({
sort: 1,
type: BlockEnum.TriggerPlugin,
isStart: true,
})
const nodeDefault: NodeDefault<PluginTriggerNodeType> = {

View File

@ -34,15 +34,11 @@ describe('Schedule Trigger Node Default', () => {
expect(nodeDefault.defaultValue.frequency).toBe('daily')
})
it('should have empty prev nodes', () => {
const prevNodes = nodeDefault.getAvailablePrevNodes(false)
expect(prevNodes).toEqual([])
})
it('should have available next nodes excluding Start', () => {
const nextNodes = nodeDefault.getAvailableNextNodes(false)
expect(nextNodes).toBeDefined()
expect(nextNodes.length).toBeGreaterThan(0)
it('should have correct metadata for trigger node', () => {
expect(nodeDefault.metaData).toBeDefined()
expect(nodeDefault.metaData.type).toBe('trigger-schedule')
expect(nodeDefault.metaData.sort).toBe(2)
expect(nodeDefault.metaData.isStart).toBe(true)
})
})

View File

@ -107,6 +107,7 @@ const validateVisualConfig = (payload: ScheduleTriggerNodeType, t: any): string
const metaData = genNodeMetaData({
sort: 2,
type: BlockEnum.TriggerSchedule,
isStart: true,
})
const nodeDefault: NodeDefault<ScheduleTriggerNodeType> = {

View File

@ -45,15 +45,11 @@ describe('Webhook Trigger Node Default', () => {
expect(defaultValue.body).toHaveLength(0)
})
it('should have empty prev nodes', () => {
const prevNodes = nodeDefault.getAvailablePrevNodes(false)
expect(prevNodes).toEqual([])
})
it('should have available next nodes excluding Start', () => {
const nextNodes = nodeDefault.getAvailableNextNodes(false)
expect(nextNodes).toBeDefined()
expect(nextNodes.length).toBeGreaterThan(0)
it('should have correct metadata for trigger node', () => {
expect(nodeDefault.metaData).toBeDefined()
expect(nodeDefault.metaData.type).toBe('trigger-webhook')
expect(nodeDefault.metaData.sort).toBe(3)
expect(nodeDefault.metaData.isStart).toBe(true)
})
})

View File

@ -7,6 +7,7 @@ import { isValidParameterType } from './utils/parameter-type-utils'
const metaData = genNodeMetaData({
sort: 3,
type: BlockEnum.TriggerWebhook,
isStart: true,
})
const nodeDefault: NodeDefault<WebhookTriggerNodeType> = {
@ -23,6 +24,14 @@ const nodeDefault: NodeDefault<WebhookTriggerNodeType> = {
response_body: '',
},
checkValid(payload: WebhookTriggerNodeType, t: any) {
// Require webhook_url to be configured
if (!payload.webhook_url || payload.webhook_url.trim() === '') {
return {
isValid: false,
errorMessage: t('workflow.nodes.triggerWebhook.validation.webhookUrlRequired'),
}
}
// Validate parameter types for params and body
const parametersWithTypes = [
...(payload.params || []),