Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/core/app/apps/workflow_app_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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
Expand Down Expand Up @@ -63,7 +64,6 @@
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
Expand Down
2 changes: 1 addition & 1 deletion api/core/app/entities/queue_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class QueueNodeStartedEvent(AppQueueEvent):
start_at: datetime
agent_strategy: AgentNodeStrategyInit | None = None

# FIXME(-LAN-): only for ToolNode, need to refactor
# Legacy provider fields kept for existing start-event consumers.
provider_type: str # should be a core.tools.entities.tool_entities.ToolProviderType
provider_id: str

Expand Down
4 changes: 2 additions & 2 deletions api/core/trigger/debug/event_selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
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
Expand Down
2 changes: 1 addition & 1 deletion api/core/workflow/node_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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
Expand All @@ -39,7 +40,6 @@
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 (
Expand Down
1 change: 1 addition & 0 deletions api/core/workflow/nodes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Core-owned workflow node packages."""
30 changes: 30 additions & 0 deletions api/core/workflow/nodes/node_mapping.py
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dify_graph.constants import SYSTEM_VARIABLE_NODE_ID
from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
from dify_graph.enums import NodeExecutionType, NodeType
from dify_graph.graph_events import NodeRunStartedEvent
from dify_graph.node_events import NodeRunResult
from dify_graph.nodes.base.node import Node

Expand Down Expand Up @@ -32,6 +33,11 @@ def get_default_config(cls, filters: Mapping[str, object] | None = None) -> Mapp
def version(cls) -> str:
return "1"

def customize_start_event(self, event: NodeRunStartedEvent) -> None:
provider_id = self.node_data.provider_id
event.provider_id = provider_id
event.extras["provider_id"] = provider_id

def _run(self) -> NodeRunResult:
"""
Run the plugin trigger node.
Expand Down
3 changes: 3 additions & 0 deletions api/core/workflow/nodes/trigger_schedule/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .trigger_schedule_node import TriggerScheduleNode

__all__ = ["TriggerScheduleNode"]
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
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]):
Expand Down
2 changes: 1 addition & 1 deletion api/core/workflow/workflow_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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
Expand All @@ -23,7 +24,6 @@
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
Expand Down
3 changes: 2 additions & 1 deletion api/dify_graph/graph_events/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ class NodeRunStartedEvent(GraphNodeEventBase):
predecessor_node_id: str | None = None
agent_strategy: AgentNodeStrategyInit | None = None
start_at: datetime = Field(..., description="node start time")
extras: dict[str, object] = Field(default_factory=dict)

# FIXME(-LAN-): only for ToolNode
# Legacy provider fields kept for existing start-event consumers.
provider_type: str = ""
provider_id: str = ""

Expand Down
15 changes: 8 additions & 7 deletions api/dify_graph/nodes/base/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class CodeNode(Node[CodeNodeData]): # CodeNodeData is auto-extracted
# 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.*.
# 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__", "")
Expand Down Expand Up @@ -273,6 +273,10 @@ def post_init(self) -> None:
"""Optional hook for subclasses requiring extra initialization."""
return

def customize_start_event(self, event: NodeRunStartedEvent) -> None:
"""Optional hook for subclasses to attach start-event metadata or extras."""
return

@property
def graph_init_params(self) -> GraphInitParams:
return self._graph_init_params
Expand Down Expand Up @@ -379,12 +383,6 @@ def run(self) -> Generator[GraphNodeEventBase, None, None]:
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):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this branch drops provider_id from NodeRunStartedEvent for trigger-plugin nodes. I verified on the current head that next(TriggerEventNode(...).run()).provider_id == "", while downstream start-event consumers still use that field for trigger icon lookup in workflow_response_converter.py and workflow_app_runner.py. Please preserve the start-event provider metadata when moving the node, either by keying off self.node_type == NodeType.TRIGGER_PLUGIN here or by moving this into a node-level helper.

start_event.provider_id = getattr(self.node_data, "provider_id", "")
start_event.provider_type = getattr(self.node_data, "provider_type", "")

from dify_graph.nodes.agent.agent_node import AgentNode
from dify_graph.nodes.agent.entities import AgentNodeData

Expand All @@ -394,6 +392,8 @@ def run(self) -> Generator[GraphNodeEventBase, None, None]:
icon=self.agent_strategy_icon,
)

self.customize_start_event(start_event)

# ===
yield start_event

Expand Down Expand Up @@ -524,6 +524,7 @@ def get_node_type_classes_mapping(cls) -> Mapping[NodeType, Mapping[str, type[No
"""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)
Expand Down
3 changes: 0 additions & 3 deletions api/dify_graph/nodes/trigger_schedule/__init__.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
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
Expand Down
2 changes: 1 addition & 1 deletion api/services/app_dsl_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
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
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
Expand Down
2 changes: 1 addition & 1 deletion api/services/rag_pipeline/rag_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
)
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,
Expand All @@ -48,7 +49,6 @@
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
Expand Down
8 changes: 4 additions & 4 deletions api/services/trigger/schedule_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
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
Expand Down
2 changes: 1 addition & 1 deletion api/services/trigger/trigger_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
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
Expand Down
8 changes: 4 additions & 4 deletions api/services/trigger/webhook_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
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
Expand Down
2 changes: 1 addition & 1 deletion api/services/workflow_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
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
Expand All @@ -34,7 +35,6 @@
)
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
Expand Down
2 changes: 1 addition & 1 deletion api/tasks/trigger_processing_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
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,
Expand Down
2 changes: 1 addition & 1 deletion api/tasks/workflow_schedule_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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,
Expand Down
Loading
Loading