From 238497b7ab45c4a0b8c6bfe311a6c332e6e5d643 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sat, 14 Mar 2026 17:20:52 +0800 Subject: [PATCH] Move trigger workflow nodes into core workflow --- api/core/app/apps/workflow_app_runner.py | 2 +- api/core/trigger/debug/event_selectors.py | 4 +-- api/core/workflow/node_factory.py | 2 +- api/core/workflow/nodes/__init__.py | 1 + api/core/workflow/nodes/node_mapping.py | 30 +++++++++++++++++++ .../nodes/trigger_plugin/__init__.py | 0 .../nodes/trigger_plugin/entities.py | 3 +- .../workflow}/nodes/trigger_plugin/exc.py | 0 .../trigger_plugin/trigger_event_node.py | 0 .../nodes/trigger_schedule/__init__.py | 3 ++ .../nodes/trigger_schedule/entities.py | 0 .../workflow}/nodes/trigger_schedule/exc.py | 0 .../trigger_schedule/trigger_schedule_node.py | 3 +- .../nodes/trigger_webhook/__init__.py | 0 .../nodes/trigger_webhook/entities.py | 0 .../workflow}/nodes/trigger_webhook/exc.py | 0 .../workflow}/nodes/trigger_webhook/node.py | 0 api/core/workflow/workflow_entry.py | 2 +- api/dify_graph/nodes/base/node.py | 10 +++---- .../nodes/trigger_schedule/__init__.py | 3 -- ...nc_workflow_schedule_when_app_published.py | 2 +- api/services/app_dsl_service.py | 2 +- api/services/rag_pipeline/rag_pipeline.py | 2 +- api/services/trigger/schedule_service.py | 8 ++--- api/services/trigger/trigger_service.py | 2 +- api/services/trigger/webhook_service.py | 8 ++--- api/services/workflow_service.py | 2 +- api/tasks/trigger_processing_tasks.py | 2 +- api/tasks/workflow_schedule_tasks.py | 2 +- .../test_trigger_debug_event_selectors.py | 2 +- .../workflow/nodes/base/test_base_node.py | 5 ++-- .../workflow/nodes/webhook/test_entities.py | 2 +- .../workflow/nodes/webhook/test_exceptions.py | 6 ++-- .../webhook/test_webhook_file_conversion.py | 20 ++++++------- .../nodes/webhook/test_webhook_node.py | 10 +++---- .../libs/test_cron_compatibility.py | 2 +- .../services/test_schedule_service.py | 8 ++--- 37 files changed, 90 insertions(+), 58 deletions(-) create mode 100644 api/core/workflow/nodes/__init__.py create mode 100644 api/core/workflow/nodes/node_mapping.py rename api/{dify_graph => core/workflow}/nodes/trigger_plugin/__init__.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_plugin/entities.py (97%) rename api/{dify_graph => core/workflow}/nodes/trigger_plugin/exc.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_plugin/trigger_event_node.py (100%) create mode 100644 api/core/workflow/nodes/trigger_schedule/__init__.py rename api/{dify_graph => core/workflow}/nodes/trigger_schedule/entities.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_schedule/exc.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_schedule/trigger_schedule_node.py (95%) rename api/{dify_graph => core/workflow}/nodes/trigger_webhook/__init__.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_webhook/entities.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_webhook/exc.py (100%) rename api/{dify_graph => core/workflow}/nodes/trigger_webhook/node.py (100%) delete mode 100644 api/dify_graph/nodes/trigger_schedule/__init__.py diff --git a/api/core/app/apps/workflow_app_runner.py b/api/core/app/apps/workflow_app_runner.py index 3812fac28a..252faf7e3e 100644 --- a/api/core/app/apps/workflow_app_runner.py +++ b/api/core/app/apps/workflow_app_runner.py @@ -30,6 +30,7 @@ from core.app.entities.queue_entities import ( QueueWorkflowSucceededEvent, ) from core.workflow.node_factory import DifyNodeFactory +from core.workflow.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING from core.workflow.workflow_entry import WorkflowEntry from dify_graph.entities import GraphInitParams from dify_graph.entities.graph_config import NodeConfigDictAdapter @@ -63,7 +64,6 @@ from dify_graph.graph_events import ( NodeRunSucceededEvent, ) from dify_graph.graph_events.graph import GraphRunAbortedEvent -from dify_graph.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING from dify_graph.runtime import GraphRuntimeState, VariablePool from dify_graph.system_variable import SystemVariable from dify_graph.variable_loader import DUMMY_VARIABLE_LOADER, VariableLoader, load_into_variable_pool diff --git a/api/core/trigger/debug/event_selectors.py b/api/core/trigger/debug/event_selectors.py index 442a2434d5..0aff27652c 100644 --- a/api/core/trigger/debug/event_selectors.py +++ b/api/core/trigger/debug/event_selectors.py @@ -19,10 +19,10 @@ from core.trigger.debug.events import ( build_plugin_pool_key, build_webhook_pool_key, ) +from core.workflow.nodes.trigger_plugin.entities import TriggerEventNodeData +from core.workflow.nodes.trigger_schedule.entities import ScheduleConfig from dify_graph.entities.graph_config import NodeConfigDict from dify_graph.enums import NodeType -from dify_graph.nodes.trigger_plugin.entities import TriggerEventNodeData -from dify_graph.nodes.trigger_schedule.entities import ScheduleConfig from extensions.ext_redis import redis_client from libs.datetime_utils import ensure_naive_utc, naive_utc_now from libs.schedule_utils import calculate_next_run_at diff --git a/api/core/workflow/node_factory.py b/api/core/workflow/node_factory.py index d7f2a67c06..6ab43fbf6f 100644 --- a/api/core/workflow/node_factory.py +++ b/api/core/workflow/node_factory.py @@ -22,6 +22,7 @@ from core.rag.retrieval.dataset_retrieval import DatasetRetrieval from core.rag.summary_index.summary_index import SummaryIndex from core.repositories.human_input_repository import HumanInputFormRepositoryImpl from core.tools.tool_file_manager import ToolFileManager +from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from dify_graph.entities.base_node_data import BaseNodeData from dify_graph.entities.graph_config import NodeConfigDict, NodeConfigDictAdapter from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY @@ -39,7 +40,6 @@ from dify_graph.nodes.document_extractor import UnstructuredApiConfig from dify_graph.nodes.http_request import build_http_request_config from dify_graph.nodes.llm.entities import LLMNodeData from dify_graph.nodes.llm.exc import LLMModeRequiredError, ModelNotExistError -from dify_graph.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from dify_graph.nodes.parameter_extractor.entities import ParameterExtractorNodeData from dify_graph.nodes.question_classifier.entities import QuestionClassifierNodeData from dify_graph.nodes.template_transform.template_renderer import ( diff --git a/api/core/workflow/nodes/__init__.py b/api/core/workflow/nodes/__init__.py new file mode 100644 index 0000000000..46e7610fe2 --- /dev/null +++ b/api/core/workflow/nodes/__init__.py @@ -0,0 +1 @@ +"""Core-owned workflow node packages.""" diff --git a/api/core/workflow/nodes/node_mapping.py b/api/core/workflow/nodes/node_mapping.py new file mode 100644 index 0000000000..618eb710b1 --- /dev/null +++ b/api/core/workflow/nodes/node_mapping.py @@ -0,0 +1,30 @@ +"""Node mapping for workflow execution. + +`core.workflow` owns the trigger node implementations, while the remaining node +implementations still live under `dify_graph`. This module imports the +core-owned node packages first, then asks the shared `Node` registry to load the +rest of the workflow nodes from `dify_graph`. +""" + +import importlib +import pkgutil +from collections.abc import Mapping + +from dify_graph.enums import NodeType +from dify_graph.nodes.base.node import Node + +LATEST_VERSION = "latest" + + +def _register_core_workflow_nodes() -> None: + import core.workflow.nodes as workflow_nodes_pkg + + for _, modname, _ in pkgutil.walk_packages(workflow_nodes_pkg.__path__, workflow_nodes_pkg.__name__ + "."): + if modname == "core.workflow.nodes.node_mapping": + continue + importlib.import_module(modname) + + +_register_core_workflow_nodes() + +NODE_TYPE_CLASSES_MAPPING: Mapping[NodeType, Mapping[str, type[Node]]] = Node.get_node_type_classes_mapping() diff --git a/api/dify_graph/nodes/trigger_plugin/__init__.py b/api/core/workflow/nodes/trigger_plugin/__init__.py similarity index 100% rename from api/dify_graph/nodes/trigger_plugin/__init__.py rename to api/core/workflow/nodes/trigger_plugin/__init__.py diff --git a/api/dify_graph/nodes/trigger_plugin/entities.py b/api/core/workflow/nodes/trigger_plugin/entities.py similarity index 97% rename from api/dify_graph/nodes/trigger_plugin/entities.py rename to api/core/workflow/nodes/trigger_plugin/entities.py index 33a61c9bc8..ccee2d83ab 100644 --- a/api/dify_graph/nodes/trigger_plugin/entities.py +++ b/api/core/workflow/nodes/trigger_plugin/entities.py @@ -6,7 +6,8 @@ from pydantic import BaseModel, Field, ValidationInfo, field_validator from core.trigger.entities.entities import EventParameter from dify_graph.entities.base_node_data import BaseNodeData from dify_graph.enums import NodeType -from dify_graph.nodes.trigger_plugin.exc import TriggerEventParameterError + +from .exc import TriggerEventParameterError class TriggerEventNodeData(BaseNodeData): diff --git a/api/dify_graph/nodes/trigger_plugin/exc.py b/api/core/workflow/nodes/trigger_plugin/exc.py similarity index 100% rename from api/dify_graph/nodes/trigger_plugin/exc.py rename to api/core/workflow/nodes/trigger_plugin/exc.py diff --git a/api/dify_graph/nodes/trigger_plugin/trigger_event_node.py b/api/core/workflow/nodes/trigger_plugin/trigger_event_node.py similarity index 100% rename from api/dify_graph/nodes/trigger_plugin/trigger_event_node.py rename to api/core/workflow/nodes/trigger_plugin/trigger_event_node.py diff --git a/api/core/workflow/nodes/trigger_schedule/__init__.py b/api/core/workflow/nodes/trigger_schedule/__init__.py new file mode 100644 index 0000000000..07b711a0fd --- /dev/null +++ b/api/core/workflow/nodes/trigger_schedule/__init__.py @@ -0,0 +1,3 @@ +from .trigger_schedule_node import TriggerScheduleNode + +__all__ = ["TriggerScheduleNode"] diff --git a/api/dify_graph/nodes/trigger_schedule/entities.py b/api/core/workflow/nodes/trigger_schedule/entities.py similarity index 100% rename from api/dify_graph/nodes/trigger_schedule/entities.py rename to api/core/workflow/nodes/trigger_schedule/entities.py diff --git a/api/dify_graph/nodes/trigger_schedule/exc.py b/api/core/workflow/nodes/trigger_schedule/exc.py similarity index 100% rename from api/dify_graph/nodes/trigger_schedule/exc.py rename to api/core/workflow/nodes/trigger_schedule/exc.py diff --git a/api/dify_graph/nodes/trigger_schedule/trigger_schedule_node.py b/api/core/workflow/nodes/trigger_schedule/trigger_schedule_node.py similarity index 95% rename from api/dify_graph/nodes/trigger_schedule/trigger_schedule_node.py rename to api/core/workflow/nodes/trigger_schedule/trigger_schedule_node.py index 7e92eb3f4f..07fe98f034 100644 --- a/api/dify_graph/nodes/trigger_schedule/trigger_schedule_node.py +++ b/api/core/workflow/nodes/trigger_schedule/trigger_schedule_node.py @@ -5,7 +5,8 @@ from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionSta from dify_graph.enums import NodeExecutionType, NodeType from dify_graph.node_events import NodeRunResult from dify_graph.nodes.base.node import Node -from dify_graph.nodes.trigger_schedule.entities import TriggerScheduleNodeData + +from .entities import TriggerScheduleNodeData class TriggerScheduleNode(Node[TriggerScheduleNodeData]): diff --git a/api/dify_graph/nodes/trigger_webhook/__init__.py b/api/core/workflow/nodes/trigger_webhook/__init__.py similarity index 100% rename from api/dify_graph/nodes/trigger_webhook/__init__.py rename to api/core/workflow/nodes/trigger_webhook/__init__.py diff --git a/api/dify_graph/nodes/trigger_webhook/entities.py b/api/core/workflow/nodes/trigger_webhook/entities.py similarity index 100% rename from api/dify_graph/nodes/trigger_webhook/entities.py rename to api/core/workflow/nodes/trigger_webhook/entities.py diff --git a/api/dify_graph/nodes/trigger_webhook/exc.py b/api/core/workflow/nodes/trigger_webhook/exc.py similarity index 100% rename from api/dify_graph/nodes/trigger_webhook/exc.py rename to api/core/workflow/nodes/trigger_webhook/exc.py diff --git a/api/dify_graph/nodes/trigger_webhook/node.py b/api/core/workflow/nodes/trigger_webhook/node.py similarity index 100% rename from api/dify_graph/nodes/trigger_webhook/node.py rename to api/core/workflow/nodes/trigger_webhook/node.py diff --git a/api/core/workflow/workflow_entry.py b/api/core/workflow/workflow_entry.py index fef01049c5..f40ffeb06d 100644 --- a/api/core/workflow/workflow_entry.py +++ b/api/core/workflow/workflow_entry.py @@ -9,6 +9,7 @@ from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom, build_di from core.app.workflow.layers.llm_quota import LLMQuotaLayer from core.app.workflow.layers.observability import ObservabilityLayer from core.workflow.node_factory import DifyNodeFactory +from core.workflow.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING from dify_graph.constants import ENVIRONMENT_VARIABLE_NODE_ID from dify_graph.entities import GraphInitParams from dify_graph.entities.graph_config import NodeConfigDictAdapter @@ -23,7 +24,6 @@ from dify_graph.graph_engine.protocols.command_channel import CommandChannel from dify_graph.graph_events import GraphEngineEvent, GraphNodeEventBase, GraphRunFailedEvent from dify_graph.nodes import NodeType from dify_graph.nodes.base.node import Node -from dify_graph.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING from dify_graph.runtime import ChildGraphNotFoundError, GraphRuntimeState, VariablePool from dify_graph.system_variable import SystemVariable from dify_graph.variable_loader import DUMMY_VARIABLE_LOADER, VariableLoader, load_into_variable_pool diff --git a/api/dify_graph/nodes/base/node.py b/api/dify_graph/nodes/base/node.py index d7702c8cb4..eb00f48d6c 100644 --- a/api/dify_graph/nodes/base/node.py +++ b/api/dify_graph/nodes/base/node.py @@ -179,7 +179,8 @@ class Node(Generic[NodeDataT]): # Skip base class itself if cls is Node: return - # Only register production node implementations defined under dify_graph.nodes.* + # Only register production node implementations defined under + # dify_graph.nodes.* or core.workflow.nodes.*. # This prevents test helper subclasses from polluting the global registry and # accidentally overriding real node types (e.g., a test Answer node). module_name = getattr(cls, "__module__", "") @@ -187,7 +188,7 @@ class Node(Generic[NodeDataT]): node_type = cls.node_type version = cls.version() bucket = Node._registry.setdefault(node_type, {}) - if module_name.startswith("dify_graph.nodes."): + if module_name.startswith(("dify_graph.nodes.", "core.workflow.nodes.")): # Production node definitions take precedence and may override bucket[version] = cls # type: ignore[index] else: @@ -379,9 +380,7 @@ class Node(Generic[NodeDataT]): start_event.provider_id = f"{plugin_id}/{provider_name}" start_event.provider_type = getattr(self.node_data, "provider_type", "") - from dify_graph.nodes.trigger_plugin.trigger_event_node import TriggerEventNode - - if isinstance(self, TriggerEventNode): + if self.node_type == NodeType.TRIGGER_PLUGIN: start_event.provider_id = getattr(self.node_data, "provider_id", "") start_event.provider_type = getattr(self.node_data, "provider_type", "") @@ -524,6 +523,7 @@ class Node(Generic[NodeDataT]): """Return mapping of NodeType -> {version -> Node subclass} using __init_subclass__ registry. Import all modules under dify_graph.nodes so subclasses register themselves on import. + Higher-level packages may register additional nodes before calling this helper. Then we return a readonly view of the registry to avoid accidental mutation. """ # Import all node modules to ensure they are loaded (thus registered) diff --git a/api/dify_graph/nodes/trigger_schedule/__init__.py b/api/dify_graph/nodes/trigger_schedule/__init__.py deleted file mode 100644 index c9b3ae6a0d..0000000000 --- a/api/dify_graph/nodes/trigger_schedule/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from dify_graph.nodes.trigger_schedule.trigger_schedule_node import TriggerScheduleNode - -__all__ = ["TriggerScheduleNode"] diff --git a/api/events/event_handlers/sync_workflow_schedule_when_app_published.py b/api/events/event_handlers/sync_workflow_schedule_when_app_published.py index 90f562d167..168513fc04 100644 --- a/api/events/event_handlers/sync_workflow_schedule_when_app_published.py +++ b/api/events/event_handlers/sync_workflow_schedule_when_app_published.py @@ -4,7 +4,7 @@ from typing import cast from sqlalchemy import select from sqlalchemy.orm import Session -from dify_graph.nodes.trigger_schedule.entities import SchedulePlanUpdate +from core.workflow.nodes.trigger_schedule.entities import SchedulePlanUpdate from events.app_event import app_published_workflow_was_updated from extensions.ext_database import db from models import AppMode, Workflow, WorkflowSchedulePlan diff --git a/api/services/app_dsl_service.py b/api/services/app_dsl_service.py index 49ca273442..a2e05ddc3a 100644 --- a/api/services/app_dsl_service.py +++ b/api/services/app_dsl_service.py @@ -20,6 +20,7 @@ from sqlalchemy.orm import Session from configs import dify_config from core.helper import ssrf_proxy from core.plugin.entities.plugin import PluginDependency +from core.workflow.nodes.trigger_schedule.trigger_schedule_node import TriggerScheduleNode from dify_graph.enums import NodeType from dify_graph.model_runtime.utils.encoders import jsonable_encoder from dify_graph.nodes.knowledge_retrieval.entities import KnowledgeRetrievalNodeData @@ -27,7 +28,6 @@ from dify_graph.nodes.llm.entities import LLMNodeData from dify_graph.nodes.parameter_extractor.entities import ParameterExtractorNodeData from dify_graph.nodes.question_classifier.entities import QuestionClassifierNodeData from dify_graph.nodes.tool.entities import ToolNodeData -from dify_graph.nodes.trigger_schedule.trigger_schedule_node import TriggerScheduleNode from events.app_event import app_model_config_was_updated, app_was_created from extensions.ext_redis import redis_client from factories import variable_factory diff --git a/api/services/rag_pipeline/rag_pipeline.py b/api/services/rag_pipeline/rag_pipeline.py index ce745a4679..dd5878a01d 100644 --- a/api/services/rag_pipeline/rag_pipeline.py +++ b/api/services/rag_pipeline/rag_pipeline.py @@ -36,6 +36,7 @@ from core.rag.entities.event import ( ) from core.repositories.factory import DifyCoreRepositoryFactory from core.repositories.sqlalchemy_workflow_node_execution_repository import SQLAlchemyWorkflowNodeExecutionRepository +from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from core.workflow.workflow_entry import WorkflowEntry from dify_graph.entities.workflow_node_execution import ( WorkflowNodeExecution, @@ -48,7 +49,6 @@ from dify_graph.graph_events.base import GraphNodeEventBase from dify_graph.node_events.base import NodeRunResult from dify_graph.nodes.base.node import Node from dify_graph.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, build_http_request_config -from dify_graph.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from dify_graph.repositories.workflow_node_execution_repository import OrderConfig from dify_graph.runtime import VariablePool from dify_graph.system_variable import SystemVariable diff --git a/api/services/trigger/schedule_service.py b/api/services/trigger/schedule_service.py index 88b640305d..8f4a3ac18b 100644 --- a/api/services/trigger/schedule_service.py +++ b/api/services/trigger/schedule_service.py @@ -5,15 +5,15 @@ from datetime import datetime from sqlalchemy import select from sqlalchemy.orm import Session -from dify_graph.entities.graph_config import NodeConfigDict -from dify_graph.nodes import NodeType -from dify_graph.nodes.trigger_schedule.entities import ( +from core.workflow.nodes.trigger_schedule.entities import ( ScheduleConfig, SchedulePlanUpdate, TriggerScheduleNodeData, VisualConfig, ) -from dify_graph.nodes.trigger_schedule.exc import ScheduleConfigError, ScheduleNotFoundError +from core.workflow.nodes.trigger_schedule.exc import ScheduleConfigError, ScheduleNotFoundError +from dify_graph.entities.graph_config import NodeConfigDict +from dify_graph.nodes import NodeType from libs.schedule_utils import calculate_next_run_at, convert_12h_to_24h from models.account import Account, TenantAccountJoin from models.trigger import WorkflowSchedulePlan diff --git a/api/services/trigger/trigger_service.py b/api/services/trigger/trigger_service.py index 2343bbbd3d..c19b79b4f7 100644 --- a/api/services/trigger/trigger_service.py +++ b/api/services/trigger/trigger_service.py @@ -16,9 +16,9 @@ from core.trigger.debug.events import PluginTriggerDebugEvent from core.trigger.provider import PluginTriggerProviderController from core.trigger.trigger_manager import TriggerManager from core.trigger.utils.encryption import create_trigger_provider_encrypter_for_subscription +from core.workflow.nodes.trigger_plugin.entities import TriggerEventNodeData from dify_graph.entities.graph_config import NodeConfigDict from dify_graph.enums import NodeType -from dify_graph.nodes.trigger_plugin.entities import TriggerEventNodeData from extensions.ext_database import db from extensions.ext_redis import redis_client from models.model import App diff --git a/api/services/trigger/webhook_service.py b/api/services/trigger/webhook_service.py index 02977b934c..64c563ab1c 100644 --- a/api/services/trigger/webhook_service.py +++ b/api/services/trigger/webhook_service.py @@ -16,15 +16,15 @@ from werkzeug.exceptions import RequestEntityTooLarge from configs import dify_config from core.app.entities.app_invoke_entities import InvokeFrom from core.tools.tool_file_manager import ToolFileManager -from dify_graph.entities.graph_config import NodeConfigDict -from dify_graph.enums import NodeType -from dify_graph.file.models import FileTransferMethod -from dify_graph.nodes.trigger_webhook.entities import ( +from core.workflow.nodes.trigger_webhook.entities import ( ContentType, WebhookBodyParameter, WebhookData, WebhookParameter, ) +from dify_graph.entities.graph_config import NodeConfigDict +from dify_graph.enums import NodeType +from dify_graph.file.models import FileTransferMethod from dify_graph.variables.types import ArrayValidation, SegmentType from enums.quota_type import QuotaType from extensions.ext_database import db diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index 2549cdf180..e987a2000f 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -14,6 +14,7 @@ from core.app.apps.workflow.app_config_manager import WorkflowAppConfigManager from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom, build_dify_run_context from core.repositories import DifyCoreRepositoryFactory from core.repositories.human_input_repository import HumanInputFormRepositoryImpl +from core.workflow.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from core.workflow.workflow_entry import WorkflowEntry from dify_graph.entities import GraphInitParams, WorkflowNodeExecution from dify_graph.entities.graph_config import NodeConfigDict @@ -34,7 +35,6 @@ from dify_graph.nodes.human_input.entities import ( ) from dify_graph.nodes.human_input.enums import HumanInputFormKind from dify_graph.nodes.human_input.human_input_node import HumanInputNode -from dify_graph.nodes.node_mapping import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING from dify_graph.nodes.start.entities import StartNodeData from dify_graph.repositories.human_input_form_repository import FormCreateParams from dify_graph.runtime import GraphRuntimeState, VariablePool diff --git a/api/tasks/trigger_processing_tasks.py b/api/tasks/trigger_processing_tasks.py index e7f4e37c75..925ddf917e 100644 --- a/api/tasks/trigger_processing_tasks.py +++ b/api/tasks/trigger_processing_tasks.py @@ -25,8 +25,8 @@ from core.trigger.debug.events import PluginTriggerDebugEvent, build_plugin_pool from core.trigger.entities.entities import TriggerProviderEntity from core.trigger.provider import PluginTriggerProviderController from core.trigger.trigger_manager import TriggerManager +from core.workflow.nodes.trigger_plugin.entities import TriggerEventNodeData from dify_graph.enums import NodeType, WorkflowExecutionStatus -from dify_graph.nodes.trigger_plugin.entities import TriggerEventNodeData from enums.quota_type import QuotaType, unlimited from models.enums import ( AppTriggerType, diff --git a/api/tasks/workflow_schedule_tasks.py b/api/tasks/workflow_schedule_tasks.py index ced7ef973b..8c64d3ab27 100644 --- a/api/tasks/workflow_schedule_tasks.py +++ b/api/tasks/workflow_schedule_tasks.py @@ -3,7 +3,7 @@ import logging from celery import shared_task from core.db.session_factory import session_factory -from dify_graph.nodes.trigger_schedule.exc import ( +from core.workflow.nodes.trigger_schedule.exc import ( ScheduleExecutionError, ScheduleNotFoundError, TenantOwnerNotFoundError, diff --git a/api/tests/unit_tests/core/test_trigger_debug_event_selectors.py b/api/tests/unit_tests/core/test_trigger_debug_event_selectors.py index 14b42adbbe..2b508ca654 100644 --- a/api/tests/unit_tests/core/test_trigger_debug_event_selectors.py +++ b/api/tests/unit_tests/core/test_trigger_debug_event_selectors.py @@ -6,7 +6,7 @@ import pytest import pytz from core.trigger.debug import event_selectors -from dify_graph.nodes.trigger_schedule.entities import ScheduleConfig +from core.workflow.nodes.trigger_schedule.entities import ScheduleConfig class _DummyRedis: diff --git a/api/tests/unit_tests/core/workflow/nodes/base/test_base_node.py b/api/tests/unit_tests/core/workflow/nodes/base/test_base_node.py index 3fb775f934..89921e0a2e 100644 --- a/api/tests/unit_tests/core/workflow/nodes/base/test_base_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/base/test_base_node.py @@ -1,12 +1,11 @@ import pytest +# Ensures that all node classes are imported. +from core.workflow.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING from dify_graph.entities.base_node_data import BaseNodeData from dify_graph.enums import NodeType from dify_graph.nodes.base.node import Node -# Ensures that all node classes are imported. -from dify_graph.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING - # Ensure `NODE_TYPE_CLASSES_MAPPING` is used and not automatically removed. _ = NODE_TYPE_CLASSES_MAPPING diff --git a/api/tests/unit_tests/core/workflow/nodes/webhook/test_entities.py b/api/tests/unit_tests/core/workflow/nodes/webhook/test_entities.py index 61b18566b0..6be5bb23e8 100644 --- a/api/tests/unit_tests/core/workflow/nodes/webhook/test_entities.py +++ b/api/tests/unit_tests/core/workflow/nodes/webhook/test_entities.py @@ -1,7 +1,7 @@ import pytest from pydantic import ValidationError -from dify_graph.nodes.trigger_webhook.entities import ( +from core.workflow.nodes.trigger_webhook.entities import ( ContentType, Method, WebhookBodyParameter, diff --git a/api/tests/unit_tests/core/workflow/nodes/webhook/test_exceptions.py b/api/tests/unit_tests/core/workflow/nodes/webhook/test_exceptions.py index a821e361c5..ddf1af5a59 100644 --- a/api/tests/unit_tests/core/workflow/nodes/webhook/test_exceptions.py +++ b/api/tests/unit_tests/core/workflow/nodes/webhook/test_exceptions.py @@ -1,12 +1,12 @@ import pytest -from dify_graph.entities.exc import BaseNodeError -from dify_graph.nodes.trigger_webhook.exc import ( +from core.workflow.nodes.trigger_webhook.exc import ( WebhookConfigError, WebhookNodeError, WebhookNotFoundError, WebhookTimeoutError, ) +from dify_graph.entities.exc import BaseNodeError def test_webhook_node_error_inheritance(): @@ -149,7 +149,7 @@ def test_webhook_error_attributes(): assert WebhookConfigError.__name__ == "WebhookConfigError" # Test that all error classes have proper __module__ - expected_module = "dify_graph.nodes.trigger_webhook.exc" + expected_module = "core.workflow.nodes.trigger_webhook.exc" assert WebhookNodeError.__module__ == expected_module assert WebhookTimeoutError.__module__ == expected_module assert WebhookNotFoundError.__module__ == expected_module diff --git a/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_file_conversion.py b/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_file_conversion.py index c750e74182..78dd7ce0f3 100644 --- a/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_file_conversion.py +++ b/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_file_conversion.py @@ -9,15 +9,15 @@ when passing files to downstream LLM nodes. from unittest.mock import Mock, patch from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom -from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY, GraphInitParams -from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionStatus -from dify_graph.nodes.trigger_webhook.entities import ( +from core.workflow.nodes.trigger_webhook.entities import ( ContentType, Method, WebhookBodyParameter, WebhookData, ) -from dify_graph.nodes.trigger_webhook.node import TriggerWebhookNode +from core.workflow.nodes.trigger_webhook.node import TriggerWebhookNode +from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY, GraphInitParams +from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionStatus from dify_graph.runtime.graph_runtime_state import GraphRuntimeState from dify_graph.runtime.variable_pool import VariablePool from dify_graph.system_variable import SystemVariable @@ -130,8 +130,8 @@ def test_webhook_node_file_conversion_to_file_variable(): # Mock the file factory and variable factory with ( patch("factories.file_factory.build_from_mapping") as mock_file_factory, - patch("dify_graph.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, - patch("dify_graph.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, + patch("core.workflow.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, + patch("core.workflow.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, ): # Setup mocks mock_file_obj = Mock() @@ -322,8 +322,8 @@ def test_webhook_node_file_conversion_mixed_parameters(): with ( patch("factories.file_factory.build_from_mapping") as mock_file_factory, - patch("dify_graph.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, - patch("dify_graph.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, + patch("core.workflow.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, + patch("core.workflow.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, ): # Setup mocks for file mock_file_obj = Mock() @@ -390,8 +390,8 @@ def test_webhook_node_different_file_types(): with ( patch("factories.file_factory.build_from_mapping") as mock_file_factory, - patch("dify_graph.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, - patch("dify_graph.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, + patch("core.workflow.nodes.trigger_webhook.node.build_segment_with_type") as mock_segment_factory, + patch("core.workflow.nodes.trigger_webhook.node.FileVariable") as mock_file_variable, ): # Setup mocks for all files mock_file_objs = [Mock() for _ in range(3)] diff --git a/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_node.py b/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_node.py index df13bbb92f..b47b88de1d 100644 --- a/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/webhook/test_webhook_node.py @@ -3,17 +3,17 @@ from unittest.mock import patch import pytest from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom -from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY, GraphInitParams -from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionStatus -from dify_graph.file import File, FileTransferMethod, FileType -from dify_graph.nodes.trigger_webhook.entities import ( +from core.workflow.nodes.trigger_webhook.entities import ( ContentType, Method, WebhookBodyParameter, WebhookData, WebhookParameter, ) -from dify_graph.nodes.trigger_webhook.node import TriggerWebhookNode +from core.workflow.nodes.trigger_webhook.node import TriggerWebhookNode +from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY, GraphInitParams +from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionStatus +from dify_graph.file import File, FileTransferMethod, FileType from dify_graph.runtime.graph_runtime_state import GraphRuntimeState from dify_graph.runtime.variable_pool import VariablePool from dify_graph.system_variable import SystemVariable diff --git a/api/tests/unit_tests/libs/test_cron_compatibility.py b/api/tests/unit_tests/libs/test_cron_compatibility.py index 61103d7935..6f3a94f6dc 100644 --- a/api/tests/unit_tests/libs/test_cron_compatibility.py +++ b/api/tests/unit_tests/libs/test_cron_compatibility.py @@ -294,7 +294,7 @@ class TestFrontendBackendIntegration(unittest.TestCase): def test_schedule_service_integration(self): """Test integration with ScheduleService patterns.""" - from dify_graph.nodes.trigger_schedule.entities import VisualConfig + from core.workflow.nodes.trigger_schedule.entities import VisualConfig from services.trigger.schedule_service import ScheduleService # Test enhanced syntax through visual config conversion diff --git a/api/tests/unit_tests/services/test_schedule_service.py b/api/tests/unit_tests/services/test_schedule_service.py index 5e3dd157e6..e28965ea2c 100644 --- a/api/tests/unit_tests/services/test_schedule_service.py +++ b/api/tests/unit_tests/services/test_schedule_service.py @@ -5,8 +5,8 @@ from unittest.mock import MagicMock, Mock, patch import pytest from sqlalchemy.orm import Session -from dify_graph.nodes.trigger_schedule.entities import ScheduleConfig, SchedulePlanUpdate, VisualConfig -from dify_graph.nodes.trigger_schedule.exc import ScheduleConfigError +from core.workflow.nodes.trigger_schedule.entities import ScheduleConfig, SchedulePlanUpdate, VisualConfig +from core.workflow.nodes.trigger_schedule.exc import ScheduleConfigError from events.event_handlers.sync_workflow_schedule_when_app_published import ( sync_schedule_from_workflow, ) @@ -136,7 +136,7 @@ class TestScheduleService(unittest.TestCase): def test_update_schedule_not_found(self): """Test updating a non-existent schedule raises exception.""" - from dify_graph.nodes.trigger_schedule.exc import ScheduleNotFoundError + from core.workflow.nodes.trigger_schedule.exc import ScheduleNotFoundError mock_session = MagicMock(spec=Session) mock_session.get.return_value = None @@ -172,7 +172,7 @@ class TestScheduleService(unittest.TestCase): def test_delete_schedule_not_found(self): """Test deleting a non-existent schedule raises exception.""" - from dify_graph.nodes.trigger_schedule.exc import ScheduleNotFoundError + from core.workflow.nodes.trigger_schedule.exc import ScheduleNotFoundError mock_session = MagicMock(spec=Session) mock_session.get.return_value = None