Merge branch 'feat/model-provider-refactor' into deploy/dev

This commit is contained in:
yyh
2026-03-05 15:08:23 +08:00
90 changed files with 1627 additions and 797 deletions

View File

@ -4,10 +4,9 @@ import uuid
import pytest
from configs import dify_config
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.node_events import NodeRunResult
from dify_graph.nodes.code.code_node import CodeNode
@ -15,6 +14,7 @@ from dify_graph.nodes.code.limits import CodeNodeLimits
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.integration_tests.workflow.nodes.__mock.code_executor import setup_code_executor_mock
from tests.workflow_test_utils import build_test_graph_init_params
CODE_MAX_STRING_LENGTH = dify_config.CODE_MAX_STRING_LENGTH
@ -31,11 +31,11 @@ def init_code_node(code_config: dict):
"nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}, code_config],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -5,18 +5,18 @@ from urllib.parse import urlencode
import pytest
from configs import dify_config
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.helper.ssrf_proxy import ssrf_proxy
from core.tools.tool_file_manager import ToolFileManager
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.file.file_manager import file_manager
from dify_graph.graph import Graph
from dify_graph.nodes.http_request import HttpRequestNode, HttpRequestNodeConfig
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.integration_tests.workflow.nodes.__mock.http import setup_http_mock
from tests.workflow_test_utils import build_test_graph_init_params
HTTP_REQUEST_CONFIG = HttpRequestNodeConfig(
max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT,
@ -41,11 +41,11 @@ def init_http_node(config: dict):
"nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}, config],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
@ -685,11 +685,11 @@ def test_nested_object_variable_selector(setup_http_mock):
],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -4,17 +4,17 @@ import uuid
from collections.abc import Generator
from unittest.mock import MagicMock, patch
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.llm_generator.output_parser.structured_output import _parse_structured_output
from core.model_manager import ModelInstance
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.node_events import StreamCompletedEvent
from dify_graph.nodes.llm.node import LLMNode
from dify_graph.nodes.llm.protocols import CredentialsProvider, ModelFactory
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from extensions.ext_database import db
from tests.workflow_test_utils import build_test_graph_init_params
"""FOR MOCK FIXTURES, DO NOT REMOVE"""
@ -37,11 +37,11 @@ def init_llm_node(config: dict) -> LLMNode:
workflow_id = "9d2074fc-6f86-45a9-b09d-6ecc63b9056d"
user_id = "9d2074fc-6f86-45a9-b09d-6ecc63b9056e"
init_params = GraphInitParams(
tenant_id=tenant_id,
app_id=app_id,
init_params = build_test_graph_init_params(
workflow_id=workflow_id,
graph_config=graph_config,
tenant_id=tenant_id,
app_id=app_id,
user_id=user_id,
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -3,10 +3,9 @@ import time
import uuid
from unittest.mock import MagicMock
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.model_manager import ModelInstance
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.model_runtime.entities import AssistantPromptMessage, UserPromptMessage
from dify_graph.nodes.llm.protocols import CredentialsProvider, ModelFactory
from dify_graph.nodes.parameter_extractor.parameter_extractor_node import ParameterExtractorNode
@ -14,6 +13,7 @@ from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from extensions.ext_database import db
from tests.integration_tests.workflow.nodes.__mock.model import get_mocked_fetch_model_instance
from tests.workflow_test_utils import build_test_graph_init_params
"""FOR MOCK FIXTURES, DO NOT REMOVE"""
from tests.integration_tests.model_runtime.__mock.plugin_daemon import setup_model_mock
@ -43,11 +43,11 @@ def init_parameter_extractor_node(config: dict, memory=None):
"nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}, config],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -1,15 +1,15 @@
import time
import uuid
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.nodes.template_transform.template_renderer import TemplateRenderError
from dify_graph.nodes.template_transform.template_transform_node import TemplateTransformNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
class _SimpleJinja2Renderer:
@ -53,11 +53,11 @@ def test_execute_template_transform():
"nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}, config],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -2,16 +2,16 @@ import time
import uuid
from unittest.mock import MagicMock
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.tools.utils.configuration import ToolParameterConfigurationManager
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.node_events import StreamCompletedEvent
from dify_graph.nodes.tool.tool_node import ToolNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
def init_tool_node(config: dict):
@ -26,11 +26,11 @@ def init_tool_node(config: dict):
"nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}, config],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -12,7 +12,6 @@ from core.app.entities.app_invoke_entities import InvokeFrom, WorkflowAppGenerat
from core.app.workflow.layers import PersistenceWorkflowInfo, WorkflowPersistenceLayer
from core.repositories.sqlalchemy_workflow_execution_repository import SQLAlchemyWorkflowExecutionRepository
from core.repositories.sqlalchemy_workflow_node_execution_repository import SQLAlchemyWorkflowNodeExecutionRepository
from dify_graph.entities import GraphInitParams
from dify_graph.enums import WorkflowType
from dify_graph.graph import Graph
from dify_graph.graph_engine.command_channels.in_memory_channel import InMemoryChannel
@ -33,6 +32,7 @@ from models.account import Tenant, TenantAccountJoin, TenantAccountRole
from models.enums import CreatorUserRole, WorkflowRunTriggeredFrom
from models.model import App, AppMode, IconType
from models.workflow import Workflow, WorkflowNodeExecutionModel, WorkflowNodeExecutionTriggeredFrom, WorkflowRun
from tests.workflow_test_utils import build_test_graph_init_params
def _mock_form_repository_without_submission() -> HumanInputFormRepository:
@ -87,11 +87,11 @@ def _build_graph(
form_repository: HumanInputFormRepository,
) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
params = GraphInitParams(
tenant_id=tenant_id,
app_id=app_id,
params = build_test_graph_init_params(
workflow_id=workflow_id,
graph_config=graph_config,
tenant_id=tenant_id,
app_id=app_id,
user_id=user_id,
user_from="account",
invoke_from="debugger",

View File

@ -13,7 +13,6 @@ from core.app.apps.advanced_chat import app_generator as adv_app_gen_module
from core.app.apps.workflow import app_generator as wf_app_gen_module
from core.app.entities.app_invoke_entities import InvokeFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.entities.pause_reason import SchedulingPause
from dify_graph.entities.workflow_start_reason import WorkflowStartReason
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
@ -34,6 +33,7 @@ from dify_graph.nodes.end.entities import EndNodeData
from dify_graph.nodes.start.entities import StartNodeData
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
if "core.ops.ops_trace_manager" not in sys.modules:
ops_stub = ModuleType("core.ops.ops_trace_manager")
@ -142,11 +142,11 @@ def _build_graph_config(*, pause_on: str | None) -> dict[str, object]:
def _build_graph(runtime_state: GraphRuntimeState, *, pause_on: str | None) -> Graph:
graph_config = _build_graph_config(pause_on=pause_on)
params = GraphInitParams(
tenant_id="tenant",
app_id="app",
params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="service-api",

View File

@ -4,15 +4,13 @@ from typing import Any
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.graph import Graph
from dify_graph.graph.validation import GraphValidationError
from dify_graph.nodes import NodeType
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
def _build_iteration_graph(node_id: str) -> dict[str, Any]:
@ -53,14 +51,14 @@ def _build_loop_graph(node_id: str) -> dict[str, Any]:
def _make_factory(graph_config: dict[str, Any]) -> DifyNodeFactory:
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
user_from="account",
invoke_from="debugger",
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(

View File

@ -6,15 +6,15 @@ from dataclasses import dataclass
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import ErrorStrategy, NodeExecutionType, NodeType, UserFrom
from dify_graph.enums import ErrorStrategy, NodeExecutionType, NodeType
from dify_graph.graph import Graph
from dify_graph.graph.validation import GraphValidationError
from dify_graph.nodes.base.entities import BaseNodeData
from dify_graph.nodes.base.node import Node
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
class _TestNodeData(BaseNodeData):
@ -91,14 +91,14 @@ class _SimpleNodeFactory:
@pytest.fixture
def graph_init_dependencies() -> tuple[_SimpleNodeFactory, dict[str, object]]:
graph_config: dict[str, object] = {"edges": [], "nodes": []}
init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
user_from="account",
invoke_from="service-api",
call_depth=0,
)
variable_pool = VariablePool(system_variables=SystemVariable(user_id="user", files=[]), user_inputs={})

View File

@ -32,6 +32,7 @@ def test_deduct_quota_called_for_successful_llm_node() -> None:
node.execution_id = "execution-id"
node.node_type = NodeType.LLM
node.tenant_id = "tenant-id"
node.require_dify_context.return_value.tenant_id = "tenant-id"
node.model_instance = object()
result_event = _build_succeeded_event()
@ -52,6 +53,7 @@ def test_deduct_quota_called_for_question_classifier_node() -> None:
node.execution_id = "execution-id"
node.node_type = NodeType.QUESTION_CLASSIFIER
node.tenant_id = "tenant-id"
node.require_dify_context.return_value.tenant_id = "tenant-id"
node.model_instance = object()
result_event = _build_succeeded_event()
@ -72,6 +74,7 @@ def test_non_llm_node_is_ignored() -> None:
node.execution_id = "execution-id"
node.node_type = NodeType.START
node.tenant_id = "tenant-id"
node.require_dify_context.return_value.tenant_id = "tenant-id"
node._model_instance = object()
result_event = _build_succeeded_event()
@ -88,6 +91,7 @@ def test_quota_error_is_handled_in_layer() -> None:
node.execution_id = "execution-id"
node.node_type = NodeType.LLM
node.tenant_id = "tenant-id"
node.require_dify_context.return_value.tenant_id = "tenant-id"
node.model_instance = object()
result_event = _build_succeeded_event()
@ -109,6 +113,7 @@ def test_quota_deduction_exceeded_aborts_workflow_immediately() -> None:
node.execution_id = "execution-id"
node.node_type = NodeType.LLM
node.tenant_id = "tenant-id"
node.require_dify_context.return_value.tenant_id = "tenant-id"
node.model_instance = object()
node.graph_runtime_state = MagicMock()
node.graph_runtime_state.stop_event = stop_event

View File

@ -8,6 +8,7 @@ for workflows containing nodes that require third-party services.
import pytest
from dify_graph.enums import NodeType
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig, MockConfigBuilder, NodeMockConfig
from .test_table_runner import TableTestRunner, WorkflowTestCase
@ -199,22 +200,19 @@ def test_mock_config_builder():
def test_mock_factory_node_type_detection():
"""Test that MockNodeFactory correctly identifies nodes to mock."""
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
from .test_mock_factory import MockNodeFactory
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
graph_init_params = build_test_graph_init_params(
workflow_id="test",
graph_config={},
tenant_id="test",
app_id="test",
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(
variable_pool=VariablePool(environment_variables=[], conversation_variables=[], user_inputs={}),
@ -309,9 +307,7 @@ def test_workflow_without_auto_mock():
def test_register_custom_mock_node():
"""Test registering a custom mock implementation for a node type."""
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.nodes.template_transform import TemplateTransformNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
@ -323,15 +319,14 @@ def test_register_custom_mock_node():
# Custom mock implementation
pass
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
graph_init_params = build_test_graph_init_params(
workflow_id="test",
graph_config={},
tenant_id="test",
app_id="test",
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(
variable_pool=VariablePool(environment_variables=[], conversation_variables=[], user_inputs={}),

View File

@ -3,10 +3,9 @@
import time
from unittest.mock import MagicMock
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities.graph_init_params import GraphInitParams
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.pause_reason import SchedulingPause
from dify_graph.enums import UserFrom
from dify_graph.graph import Graph
from dify_graph.graph_engine import GraphEngine, GraphEngineConfig
from dify_graph.graph_engine.command_channels import InMemoryChannel
@ -41,13 +40,17 @@ def test_abort_command():
id="start",
config={"id": "start", "data": {"title": "start", "variables": []}},
graph_init_params=GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
),
graph_runtime_state=shared_runtime_state,
@ -151,13 +154,17 @@ def test_pause_command():
id="start",
config={"id": "start", "data": {"title": "start", "variables": []}},
graph_init_params=GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
),
graph_runtime_state=shared_runtime_state,
@ -207,13 +214,17 @@ def test_update_variables_command_updates_pool():
id="start",
config={"id": "start", "data": {"title": "start", "variables": []}},
graph_init_params=GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
),
graph_runtime_state=shared_runtime_state,

View File

@ -21,6 +21,7 @@ from dify_graph.nodes.start.entities import StartNodeData
from dify_graph.nodes.start.start_node import StartNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig
from .test_mock_nodes import MockLLMNode
@ -73,11 +74,11 @@ def _build_llm_node(
def _build_graph(runtime_state: GraphRuntimeState) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -4,7 +4,6 @@ from collections.abc import Iterable
from unittest import mock
from unittest.mock import MagicMock
from dify_graph.entities import GraphInitParams
from dify_graph.graph import Graph
from dify_graph.graph_events import (
GraphRunPausedEvent,
@ -35,6 +34,7 @@ from dify_graph.repositories.human_input_form_repository import HumanInputFormEn
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig
from .test_mock_nodes import MockLLMNode
@ -47,11 +47,11 @@ def _build_branching_graph(
graph_runtime_state: GraphRuntimeState | None = None,
) -> tuple[Graph, GraphRuntimeState]:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -3,7 +3,6 @@ import time
from unittest import mock
from unittest.mock import MagicMock
from dify_graph.entities import GraphInitParams
from dify_graph.graph import Graph
from dify_graph.graph_events import (
GraphRunPausedEvent,
@ -34,6 +33,7 @@ from dify_graph.repositories.human_input_form_repository import HumanInputFormEn
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig
from .test_mock_nodes import MockLLMNode
@ -46,11 +46,11 @@ def _build_llm_human_llm_graph(
graph_runtime_state: GraphRuntimeState | None = None,
) -> tuple[Graph, GraphRuntimeState]:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -1,7 +1,6 @@
import time
from unittest import mock
from dify_graph.entities import GraphInitParams
from dify_graph.graph import Graph
from dify_graph.graph_events import (
GraphRunStartedEvent,
@ -29,6 +28,7 @@ from dify_graph.nodes.start.start_node import StartNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.utils.condition.entities import Condition
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig
from .test_mock_nodes import MockLLMNode
@ -37,15 +37,10 @@ from .test_table_runner import TableTestRunner, WorkflowTestCase
def _build_if_else_graph(branch_value: str, mock_config: MockConfig) -> tuple[Graph, GraphRuntimeState]:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_init_params = build_test_graph_init_params(
graph_config=graph_config,
user_id="user",
user_from="account",
invoke_from="debugger",
call_depth=0,
)
variable_pool = VariablePool(

View File

@ -5,6 +5,8 @@ Simple test to verify MockNodeFactory works with iteration nodes.
import sys
from pathlib import Path
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
# Add api directory to path
api_dir = Path(__file__).parent.parent.parent.parent.parent.parent
sys.path.insert(0, str(api_dir))
@ -16,20 +18,23 @@ from tests.unit_tests.core.workflow.graph_engine.test_mock_factory import MockNo
def test_mock_factory_registers_iteration_node():
"""Test that MockNodeFactory has iteration node registered."""
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
# Create a MockNodeFactory instance
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
workflow_id="test",
graph_config={"nodes": [], "edges": []},
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(
@ -65,9 +70,8 @@ def test_mock_factory_registers_iteration_node():
def test_mock_iteration_node_preserves_config():
"""Test that MockIterationNode preserves mock configuration."""
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
from tests.unit_tests.core.workflow.graph_engine.test_mock_nodes import MockIterationNode
@ -76,13 +80,17 @@ def test_mock_iteration_node_preserves_config():
# Create minimal graph init params
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
workflow_id="test",
graph_config={"nodes": [], "edges": []},
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
@ -127,9 +135,8 @@ def test_mock_iteration_node_preserves_config():
def test_mock_loop_node_preserves_config():
"""Test that MockLoopNode preserves mock configuration."""
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
from tests.unit_tests.core.workflow.graph_engine.test_mock_nodes import MockLoopNode
@ -138,13 +145,17 @@ def test_mock_loop_node_preserves_config():
# Create minimal graph init params
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
workflow_id="test",
graph_config={"nodes": [], "edges": []},
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)

View File

@ -603,13 +603,9 @@ class MockIterationNode(MockNodeMixin, IterationNode):
# Create GraphInitParams from node attributes
graph_init_params = GraphInitParams(
tenant_id=self.tenant_id,
app_id=self.app_id,
workflow_id=self.workflow_id,
graph_config=self.graph_config,
user_id=self.user_id,
user_from=self.user_from.value,
invoke_from=self.invoke_from.value,
run_context=self.run_context,
call_depth=self.workflow_call_depth,
)
@ -679,13 +675,9 @@ class MockLoopNode(MockNodeMixin, LoopNode):
# Create GraphInitParams from node attributes
graph_init_params = GraphInitParams(
tenant_id=self.tenant_id,
app_id=self.app_id,
workflow_id=self.workflow_id,
graph_config=self.graph_config,
user_id=self.user_id,
user_from=self.user_from.value,
invoke_from=self.invoke_from.value,
run_context=self.run_context,
call_depth=self.workflow_call_depth,
)

View File

@ -6,6 +6,7 @@ to ensure they work correctly with the TableTestRunner.
"""
from configs import dify_config
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
from dify_graph.nodes.code.limits import CodeNodeLimits
from tests.unit_tests.core.workflow.graph_engine.test_mock_config import MockConfig, MockConfigBuilder, NodeMockConfig
@ -44,13 +45,17 @@ class TestMockTemplateTransformNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -103,13 +108,17 @@ class TestMockTemplateTransformNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -163,13 +172,17 @@ class TestMockTemplateTransformNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -221,13 +234,17 @@ class TestMockTemplateTransformNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -286,13 +303,17 @@ class TestMockCodeNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -348,13 +369,17 @@ class TestMockCodeNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -418,13 +443,17 @@ class TestMockCodeNode:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -490,13 +519,17 @@ class TestMockNodeFactory:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -531,13 +564,17 @@ class TestMockNodeFactory:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -582,13 +619,17 @@ class TestMockNodeFactory:
# Create test parameters
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config={},
user_id="test_user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)

View File

@ -5,6 +5,8 @@ Simple test to validate the auto-mock system without external dependencies.
import sys
from pathlib import Path
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
# Add api directory to path
api_dir = Path(__file__).parent.parent.parent.parent.parent.parent
sys.path.insert(0, str(api_dir))
@ -101,21 +103,24 @@ def test_node_mock_config():
def test_mock_factory_detection():
"""Test MockNodeFactory node type detection."""
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
print("Testing MockNodeFactory detection...")
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
workflow_id="test",
graph_config={},
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(
@ -154,21 +159,24 @@ def test_mock_factory_detection():
def test_mock_factory_registration():
"""Test registering and unregistering mock node types."""
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.runtime import GraphRuntimeState, VariablePool
print("Testing MockNodeFactory registration...")
graph_init_params = GraphInitParams(
tenant_id="test",
app_id="test",
workflow_id="test",
graph_config={},
user_id="test",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
graph_runtime_state = GraphRuntimeState(

View File

@ -4,7 +4,6 @@ from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any, Protocol
from dify_graph.entities import GraphInitParams
from dify_graph.entities.workflow_start_reason import WorkflowStartReason
from dify_graph.graph import Graph
from dify_graph.graph_engine.command_channels.in_memory_channel import InMemoryChannel
@ -32,6 +31,7 @@ from dify_graph.repositories.human_input_form_repository import (
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
class PauseStateStore(Protocol):
@ -126,11 +126,11 @@ def _build_runtime_state() -> GraphRuntimeState:
def _build_graph(runtime_state: GraphRuntimeState, repo: HumanInputFormRepository) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -4,7 +4,6 @@ from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any
from dify_graph.entities import GraphInitParams
from dify_graph.entities.workflow_start_reason import WorkflowStartReason
from dify_graph.graph import Graph
from dify_graph.graph_engine.command_channels.in_memory_channel import InMemoryChannel
@ -39,6 +38,7 @@ from dify_graph.repositories.human_input_form_repository import (
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig, NodeMockConfig
from .test_mock_nodes import MockLLMNode
@ -129,11 +129,11 @@ def _build_runtime_state() -> GraphRuntimeState:
def _build_graph(runtime_state: GraphRuntimeState, repo: HumanInputFormRepository, mock_config: MockConfig) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -12,11 +12,10 @@ import time
from unittest.mock import MagicMock, patch
from uuid import uuid4
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.model_manager import ModelInstance
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import NodeType, UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.graph_engine import GraphEngine, GraphEngineConfig
from dify_graph.graph_engine.command_channels import InMemoryChannel
@ -30,6 +29,7 @@ from dify_graph.node_events import NodeRunResult, StreamCompletedEvent
from dify_graph.nodes.llm.node import LLMNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
from .test_table_runner import TableTestRunner
@ -86,11 +86,11 @@ def test_parallel_streaming_workflow():
graph_config = workflow_config.get("graph", {})
# Create graph initialization parameters
init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
init_params = build_test_graph_init_params(
workflow_id="test_workflow",
graph_config=graph_config,
tenant_id="test_tenant",
app_id="test_app",
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.WEB_APP,
@ -99,8 +99,8 @@ def test_parallel_streaming_workflow():
# Create variable pool with system variables
system_variables = SystemVariable(
user_id=init_params.user_id,
app_id=init_params.app_id,
user_id="test_user",
app_id="test_app",
workflow_id=init_params.workflow_id,
files=[],
query="Tell me about yourself", # User query

View File

@ -4,7 +4,6 @@ from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Any
from dify_graph.entities import GraphInitParams
from dify_graph.entities.workflow_start_reason import WorkflowStartReason
from dify_graph.graph import Graph
from dify_graph.graph_engine.command_channels.in_memory_channel import InMemoryChannel
@ -40,6 +39,7 @@ from dify_graph.repositories.human_input_form_repository import (
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
from .test_mock_config import MockConfig, NodeMockConfig
from .test_mock_nodes import MockLLMNode
@ -121,11 +121,11 @@ def _build_runtime_state() -> GraphRuntimeState:
def _build_graph(runtime_state: GraphRuntimeState, repo: HumanInputFormRepository, mock_config: MockConfig) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="debugger",

View File

@ -3,7 +3,6 @@ import time
from typing import Any
from unittest.mock import MagicMock
from dify_graph.entities import GraphInitParams
from dify_graph.entities.workflow_start_reason import WorkflowStartReason
from dify_graph.graph import Graph
from dify_graph.graph_engine.command_channels.in_memory_channel import InMemoryChannel
@ -30,6 +29,7 @@ from dify_graph.repositories.human_input_form_repository import (
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from libs.datetime_utils import naive_utc_now
from tests.workflow_test_utils import build_test_graph_init_params
def _build_runtime_state() -> GraphRuntimeState:
@ -79,11 +79,11 @@ def _build_human_input_graph(
form_repository: HumanInputFormRepository,
) -> Graph:
graph_config: dict[str, object] = {"nodes": [], "edges": []}
params = GraphInitParams(
tenant_id="tenant",
app_id="app",
params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from="account",
invoke_from="service-api",

View File

@ -12,19 +12,21 @@ This module provides a robust table-driven testing framework with support for:
import logging
import time
from collections.abc import Callable, Sequence
from collections.abc import Callable, Mapping, Sequence
from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass, field
from functools import lru_cache
from pathlib import Path
from typing import Any
from typing import Any, cast
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.tools.utils.yaml_utils import _load_yaml_file
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities.graph_init_params import GraphInitParams
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY, GraphInitParams
from dify_graph.graph import Graph
from dify_graph.graph_engine import GraphEngine, GraphEngineConfig
from dify_graph.graph_engine.command_channels import InMemoryChannel
from dify_graph.graph_engine.layers.base import GraphEngineLayer
from dify_graph.graph_events import (
GraphEngineEvent,
GraphRunStartedEvent,
@ -48,6 +50,47 @@ from .test_mock_factory import MockNodeFactory
logger = logging.getLogger(__name__)
class _TableTestChildEngineBuilder:
def __init__(self, *, use_mock_factory: bool, mock_config: MockConfig | None) -> None:
self._use_mock_factory = use_mock_factory
self._mock_config = mock_config
def build_child_engine(
self,
*,
workflow_id: str,
graph_init_params: GraphInitParams,
graph_runtime_state: GraphRuntimeState,
graph_config: Mapping[str, Any],
root_node_id: str,
layers: Sequence[object] = (),
) -> GraphEngine:
if self._use_mock_factory:
node_factory = MockNodeFactory(
graph_init_params=graph_init_params,
graph_runtime_state=graph_runtime_state,
mock_config=self._mock_config,
)
else:
node_factory = DifyNodeFactory(graph_init_params=graph_init_params, graph_runtime_state=graph_runtime_state)
child_graph = Graph.init(graph_config=graph_config, node_factory=node_factory, root_node_id=root_node_id)
if not child_graph:
raise ValueError("child graph not found")
child_engine = GraphEngine(
workflow_id=workflow_id,
graph=child_graph,
graph_runtime_state=graph_runtime_state,
command_channel=InMemoryChannel(),
config=GraphEngineConfig(),
child_engine_builder=self,
)
for layer in layers:
child_engine.layer(cast(GraphEngineLayer, layer))
return child_engine
@dataclass
class WorkflowTestCase:
"""Represents a single test case for table-driven testing."""
@ -149,19 +192,23 @@ class WorkflowRunner:
raise ValueError("Fixture missing workflow.graph configuration")
graph_init_params = GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_id="test_workflow",
graph_config=graph_config,
user_id="test_user",
user_from="account",
invoke_from="debugger", # Set to debugger to avoid conversation_id requirement
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER, # Set to debugger to avoid conversation_id requirement
}
},
call_depth=0,
)
system_variables = SystemVariable(
user_id=graph_init_params.user_id,
app_id=graph_init_params.app_id,
user_id="test_user",
app_id="test_app",
workflow_id=graph_init_params.workflow_id,
files=[],
query=query,
@ -315,6 +362,10 @@ class TableTestRunner:
scale_up_threshold=self.graph_engine_scale_up_threshold,
scale_down_idle_time=self.graph_engine_scale_down_idle_time,
),
child_engine_builder=_TableTestChildEngineBuilder(
use_mock_factory=test_case.use_auto_mock,
mock_config=test_case.mock_config,
),
)
# Execute and collect events

View File

@ -2,15 +2,15 @@ import time
import uuid
from unittest.mock import MagicMock
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.nodes.answer.answer_node import AnswerNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from extensions.ext_database import db
from tests.workflow_test_utils import build_test_graph_init_params
def test_execute_answer():
@ -35,11 +35,11 @@ def test_execute_answer():
],
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -1,3 +1,4 @@
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.entities.workflow_node_execution import WorkflowNodeExecutionStatus
from dify_graph.node_events import NodeRunResult, StreamChunkEvent, StreamCompletedEvent
from dify_graph.nodes.datasource.datasource_node import DatasourceNode
@ -28,13 +29,17 @@ class _GraphState:
class _GraphParams:
tenant_id = "t1"
app_id = "app-1"
workflow_id = "wf-1"
graph_config = {}
user_id = "u1"
user_from = "account"
invoke_from = "debugger"
run_context = {
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "t1",
"app_id": "app-1",
"user_id": "u1",
"user_from": "account",
"invoke_from": "debugger",
}
}
call_depth = 0

View File

@ -4,16 +4,16 @@ from typing import Any
import httpx
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.helper.ssrf_proxy import ssrf_proxy
from core.tools.tool_file_manager import ToolFileManager
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.file.file_manager import file_manager
from dify_graph.nodes.http_request import HTTP_REQUEST_CONFIG_FILTER_KEY, HttpRequestNode, HttpRequestNodeConfig
from dify_graph.nodes.http_request.entities import HttpRequestNodeTimeout, Response
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
HTTP_REQUEST_CONFIG = HttpRequestNodeConfig(
max_connect_timeout=10,
@ -98,11 +98,11 @@ def _build_http_node(
],
"edges": [],
}
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params = build_test_graph_init_params(
workflow_id="workflow",
graph_config=graph_config,
tenant_id="tenant",
app_id="app",
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -9,6 +9,7 @@ import pytest
from pydantic import ValidationError
from dify_graph.entities import GraphInitParams
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.node_events import PauseRequestedEvent
from dify_graph.node_events.node import StreamCompletedEvent
from dify_graph.nodes.human_input.entities import (
@ -314,13 +315,17 @@ class TestHumanInputNodeVariableResolution:
variable_pool.add(("start", "name"), "Jane Doe")
runtime_state = GraphRuntimeState(variable_pool=variable_pool, start_at=0.0)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -384,13 +389,17 @@ class TestHumanInputNodeVariableResolution:
)
runtime_state = GraphRuntimeState(variable_pool=variable_pool, start_at=0.0)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -439,13 +448,17 @@ class TestHumanInputNodeVariableResolution:
)
runtime_state = GraphRuntimeState(variable_pool=variable_pool, start_at=0.0)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user-123",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user-123",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)
@ -550,13 +563,17 @@ class TestHumanInputNodeRenderedContent:
)
runtime_state = GraphRuntimeState(variable_pool=variable_pool, start_at=0.0)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user",
user_from="account",
invoke_from="debugger",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user",
"user_from": "account",
"invoke_from": "debugger",
}
},
call_depth=0,
)

View File

@ -1,9 +1,9 @@
import datetime
from types import SimpleNamespace
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities.graph_init_params import GraphInitParams
from dify_graph.enums import NodeType, UserFrom
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.enums import NodeType
from dify_graph.graph_events import (
NodeRunHumanInputFormFilledEvent,
NodeRunHumanInputFormTimeoutEvent,
@ -31,13 +31,17 @@ def _build_node(form_content: str = "Please enter your name:\n\n{{#$output.name#
start_at=0.0,
)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
@ -91,13 +95,17 @@ def _build_timeout_node() -> HumanInputNode:
start_at=0.0,
)
graph_init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
graph_config={"nodes": [], "edges": []},
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "tenant",
"app_id": "app",
"user_id": "user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)

View File

@ -0,0 +1,100 @@
from collections.abc import Mapping, Sequence
from typing import Any
import pytest
from dify_graph.entities import GraphInitParams
from dify_graph.nodes.iteration.exc import IterationGraphNotFoundError
from dify_graph.nodes.iteration.iteration_node import IterationNode
from dify_graph.runtime import (
ChildEngineBuilderNotConfiguredError,
ChildGraphNotFoundError,
GraphRuntimeState,
VariablePool,
)
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
class _MissingGraphBuilder:
def build_child_engine(
self,
*,
workflow_id: str,
graph_init_params: GraphInitParams,
graph_runtime_state: GraphRuntimeState,
graph_config: Mapping[str, Any],
root_node_id: str,
layers: Sequence[object] = (),
) -> object:
raise ChildGraphNotFoundError(f"child graph root node '{root_node_id}' not found")
def _build_runtime_state() -> GraphRuntimeState:
return GraphRuntimeState(
variable_pool=VariablePool(system_variables=SystemVariable.default(), user_inputs={}),
start_at=0.0,
)
def _build_iteration_node(
*,
graph_config: Mapping[str, Any],
runtime_state: GraphRuntimeState,
start_node_id: str,
) -> IterationNode:
init_params = build_test_graph_init_params(graph_config=graph_config)
return IterationNode(
id="iteration-node",
config={
"id": "iteration-node",
"data": {
"type": "iteration",
"title": "Iteration",
"iterator_selector": ["start", "items"],
"output_selector": ["iteration-node", "output"],
"start_node_id": start_node_id,
},
},
graph_init_params=init_params,
graph_runtime_state=runtime_state,
)
def test_graph_runtime_state_raises_specific_error_when_child_builder_is_missing():
runtime_state = _build_runtime_state()
graph_init_params = build_test_graph_init_params()
with pytest.raises(ChildEngineBuilderNotConfiguredError):
runtime_state.create_child_engine(
workflow_id="workflow",
graph_init_params=graph_init_params,
graph_runtime_state=_build_runtime_state(),
graph_config={},
root_node_id="root",
)
def test_iteration_node_only_translates_child_graph_not_found_error():
runtime_state = _build_runtime_state()
runtime_state.bind_child_engine_builder(_MissingGraphBuilder())
node = _build_iteration_node(
graph_config={"nodes": [{"id": "present-node"}], "edges": []},
runtime_state=runtime_state,
start_node_id="missing-node",
)
with pytest.raises(IterationGraphNotFoundError):
node._create_graph_engine(index=0, item="item")
def test_iteration_node_propagates_non_graph_not_found_errors():
runtime_state = _build_runtime_state()
node = _build_iteration_node(
graph_config={"nodes": [{"id": "start-node"}], "edges": []},
runtime_state=runtime_state,
start_node_id="start-node",
)
with pytest.raises(ChildEngineBuilderNotConfiguredError):
node._create_graph_engine(index=0, item="item")

View File

@ -4,9 +4,8 @@ from unittest.mock import Mock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import SystemVariableKey, UserFrom, WorkflowNodeExecutionStatus
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.enums import SystemVariableKey, WorkflowNodeExecutionStatus
from dify_graph.nodes.knowledge_index.entities import KnowledgeIndexNodeData
from dify_graph.nodes.knowledge_index.exc import KnowledgeIndexNodeError
from dify_graph.nodes.knowledge_index.knowledge_index_node import KnowledgeIndexNode
@ -15,16 +14,17 @@ from dify_graph.repositories.summary_index_service_protocol import SummaryIndexS
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables.segments import StringSegment
from tests.workflow_test_utils import build_test_graph_init_params
@pytest.fixture
def mock_graph_init_params():
"""Create mock GraphInitParams."""
return GraphInitParams(
tenant_id=str(uuid.uuid4()),
app_id=str(uuid.uuid4()),
return build_test_graph_init_params(
workflow_id=str(uuid.uuid4()),
graph_config={},
tenant_id=str(uuid.uuid4()),
app_id=str(uuid.uuid4()),
user_id=str(uuid.uuid4()),
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -4,9 +4,8 @@ from unittest.mock import Mock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.model_runtime.entities.llm_entities import LLMUsage
from dify_graph.nodes.knowledge_retrieval.entities import (
KnowledgeRetrievalNodeData,
@ -20,16 +19,17 @@ from dify_graph.repositories.rag_retrieval_protocol import RAGRetrievalProtocol,
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables import StringSegment
from tests.workflow_test_utils import build_test_graph_init_params
@pytest.fixture
def mock_graph_init_params():
"""Create mock GraphInitParams."""
return GraphInitParams(
tenant_id=str(uuid.uuid4()),
app_id=str(uuid.uuid4()),
return build_test_graph_init_params(
workflow_id=str(uuid.uuid4()),
graph_config={},
tenant_id=str(uuid.uuid4()),
app_id=str(uuid.uuid4()),
user_id=str(uuid.uuid4()),
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -1,14 +1,13 @@
from unittest.mock import MagicMock
import pytest
from dify_graph.graph_engine.entities.graph import Graph
from dify_graph.graph_engine.entities.graph_init_params import GraphInitParams
from dify_graph.graph_engine.entities.graph_runtime_state import GraphRuntimeState
from dify_graph.entities import GraphInitParams
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
from dify_graph.nodes.list_operator.node import ListOperatorNode
from dify_graph.runtime import GraphRuntimeState
from dify_graph.variables import ArrayNumberSegment, ArrayStringSegment
from models.workflow import WorkflowType
class TestListOperatorNode:
@ -22,43 +21,40 @@ class TestListOperatorNode:
mock_state.variable_pool = mock_variable_pool
return mock_state
@pytest.fixture
def mock_graph(self):
"""Create mock Graph."""
return MagicMock(spec=Graph)
@pytest.fixture
def graph_init_params(self):
"""Create GraphInitParams fixture."""
return GraphInitParams(
tenant_id="test",
app_id="test",
workflow_type=WorkflowType.WORKFLOW,
workflow_id="test",
graph_config={},
user_id="test",
user_from="test",
invoke_from="test",
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test",
"app_id": "test",
"user_id": "test",
"user_from": "test",
"invoke_from": "test",
}
},
call_depth=0,
)
@pytest.fixture
def list_operator_node_factory(self, graph_init_params, mock_graph, mock_graph_runtime_state):
def list_operator_node_factory(self, graph_init_params, mock_graph_runtime_state):
"""Factory fixture for creating ListOperatorNode instances."""
def _create_node(config, mock_variable):
mock_graph_runtime_state.variable_pool.get.return_value = mock_variable
return ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
return _create_node
def test_node_initialization(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_node_initialization(self, mock_graph_runtime_state, graph_init_params):
"""Test node initializes correctly."""
config = {
"title": "List Operator",
@ -70,9 +66,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -101,7 +96,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "banana", "cherry"]
def test_run_with_empty_array(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_empty_array(self, mock_graph_runtime_state, graph_init_params):
"""Test with empty array."""
config = {
"title": "Test",
@ -116,9 +111,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -129,7 +123,7 @@ class TestListOperatorNode:
assert result.outputs["first_record"] is None
assert result.outputs["last_record"] is None
def test_run_with_filter_contains(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_filter_contains(self, mock_graph_runtime_state, graph_init_params):
"""Test filter with contains condition."""
config = {
"title": "Test",
@ -148,9 +142,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -159,7 +152,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "pineapple"]
def test_run_with_filter_not_contains(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_filter_not_contains(self, mock_graph_runtime_state, graph_init_params):
"""Test filter with not contains condition."""
config = {
"title": "Test",
@ -178,9 +171,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -189,7 +181,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["banana", "cherry"]
def test_run_with_number_filter_greater_than(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_number_filter_greater_than(self, mock_graph_runtime_state, graph_init_params):
"""Test filter with greater than condition on numbers."""
config = {
"title": "Test",
@ -208,9 +200,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -219,7 +210,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == [7, 9, 11]
def test_run_with_order_ascending(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_order_ascending(self, mock_graph_runtime_state, graph_init_params):
"""Test ordering in ascending order."""
config = {
"title": "Test",
@ -237,9 +228,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -248,7 +238,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "banana", "cherry"]
def test_run_with_order_descending(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_order_descending(self, mock_graph_runtime_state, graph_init_params):
"""Test ordering in descending order."""
config = {
"title": "Test",
@ -266,9 +256,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -277,7 +266,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["cherry", "banana", "apple"]
def test_run_with_limit(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_limit(self, mock_graph_runtime_state, graph_init_params):
"""Test with limit enabled."""
config = {
"title": "Test",
@ -295,9 +284,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -306,7 +294,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "banana"]
def test_run_with_filter_order_and_limit(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_filter_order_and_limit(self, mock_graph_runtime_state, graph_init_params):
"""Test with filter, order, and limit combined."""
config = {
"title": "Test",
@ -331,9 +319,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -342,7 +329,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == [9, 8, 7]
def test_run_with_variable_not_found(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_variable_not_found(self, mock_graph_runtime_state, graph_init_params):
"""Test when variable is not found."""
config = {
"title": "Test",
@ -356,9 +343,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -367,7 +353,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.FAILED
assert "Variable not found" in result.error
def test_run_with_first_and_last_record(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_first_and_last_record(self, mock_graph_runtime_state, graph_init_params):
"""Test first_record and last_record outputs."""
config = {
"title": "Test",
@ -382,9 +368,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -394,7 +379,7 @@ class TestListOperatorNode:
assert result.outputs["first_record"] == "first"
assert result.outputs["last_record"] == "last"
def test_run_with_filter_startswith(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_filter_startswith(self, mock_graph_runtime_state, graph_init_params):
"""Test filter with startswith condition."""
config = {
"title": "Test",
@ -413,9 +398,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -424,7 +408,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "application"]
def test_run_with_filter_endswith(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_filter_endswith(self, mock_graph_runtime_state, graph_init_params):
"""Test filter with endswith condition."""
config = {
"title": "Test",
@ -443,9 +427,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -454,7 +437,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == ["apple", "pineapple", "table"]
def test_run_with_number_filter_equals(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_number_filter_equals(self, mock_graph_runtime_state, graph_init_params):
"""Test number filter with equals condition."""
config = {
"title": "Test",
@ -473,9 +456,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -484,7 +466,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == [5, 5]
def test_run_with_number_filter_not_equals(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_number_filter_not_equals(self, mock_graph_runtime_state, graph_init_params):
"""Test number filter with not equals condition."""
config = {
"title": "Test",
@ -503,9 +485,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)
@ -514,7 +495,7 @@ class TestListOperatorNode:
assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED
assert result.outputs["result"].value == [1, 3, 7, 9]
def test_run_with_number_order_ascending(self, mock_graph, mock_graph_runtime_state, graph_init_params):
def test_run_with_number_order_ascending(self, mock_graph_runtime_state, graph_init_params):
"""Test number ordering in ascending order."""
config = {
"title": "Test",
@ -532,9 +513,8 @@ class TestListOperatorNode:
node = ListOperatorNode(
id="test",
config=config,
config={"id": "test", "data": config},
graph_init_params=graph_init_params,
graph=mock_graph,
graph_runtime_state=mock_graph_runtime_state,
)

View File

@ -5,14 +5,13 @@ from unittest import mock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity
from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity, UserFrom
from core.app.llm.model_access import DifyCredentialsProvider, DifyModelFactory, fetch_model_config
from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle
from core.entities.provider_entities import CustomConfiguration, SystemConfiguration
from core.model_manager import ModelInstance
from core.prompt.entities.advanced_prompt_entities import MemoryConfig
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.file import File, FileTransferMethod, FileType
from dify_graph.model_runtime.entities.common_entities import I18nObject
from dify_graph.model_runtime.entities.message_entities import (
@ -41,6 +40,7 @@ from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables import ArrayAnySegment, ArrayFileSegment, NoneSegment
from models.provider import ProviderType
from tests.workflow_test_utils import build_test_graph_init_params
class MockTokenBufferMemory:
@ -76,11 +76,11 @@ def llm_node_data() -> LLMNodeData:
@pytest.fixture
def graph_init_params() -> GraphInitParams:
return GraphInitParams(
tenant_id="1",
app_id="1",
return build_test_graph_init_params(
workflow_id="1",
graph_config={},
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,

View File

@ -2,15 +2,13 @@ from unittest.mock import MagicMock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities import GraphInitParams
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.enums import ErrorStrategy, NodeType, WorkflowNodeExecutionStatus
from dify_graph.graph import Graph
from dify_graph.nodes.template_transform.template_renderer import TemplateRenderError
from dify_graph.nodes.template_transform.template_transform_node import TemplateTransformNode
from dify_graph.runtime import GraphRuntimeState
from models.enums import UserFrom
from models.workflow import WorkflowType
from tests.workflow_test_utils import build_test_graph_init_params
class TestTemplateTransformNode:
@ -32,12 +30,11 @@ class TestTemplateTransformNode:
@pytest.fixture
def graph_init_params(self):
"""Create a mock GraphInitParams."""
return GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
workflow_type=WorkflowType.WORKFLOW,
return build_test_graph_init_params(
workflow_id="test_workflow",
graph_config={},
tenant_id="test_tenant",
app_id="test_app",
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -2,13 +2,14 @@ from collections.abc import Mapping
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom as LegacyInvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import InvokeFrom, NodeType, UserFrom
from dify_graph.enums import NodeType
from dify_graph.nodes.base.entities import BaseNodeData
from dify_graph.nodes.base.node import Node
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from tests.workflow_test_utils import build_test_graph_init_params
class _SampleNodeData(BaseNodeData):
@ -27,15 +28,10 @@ class _SampleNode(Node[_SampleNodeData]):
def _build_context(graph_config: Mapping[str, object]) -> tuple[GraphInitParams, GraphRuntimeState]:
init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
init_params = build_test_graph_init_params(
graph_config=graph_config,
user_id="user",
user_from="account",
invoke_from="debugger",
call_depth=0,
)
runtime_state = GraphRuntimeState(
variable_pool=VariablePool(system_variables=SystemVariable(user_id="user", files=[]), user_inputs={}),
@ -57,21 +53,17 @@ def test_node_hydrates_data_during_initialization():
assert node.node_data.foo == "bar"
assert node.title == "Sample"
assert node.user_from == UserFrom.ACCOUNT
assert node.invoke_from == InvokeFrom.DEBUGGER
dify_ctx = node.require_dify_context()
assert dify_ctx.user_from == "account"
assert dify_ctx.invoke_from == "debugger"
def test_node_normalizes_legacy_invoke_from_enum():
def test_node_accepts_invoke_from_enum():
graph_config: dict[str, object] = {}
init_params = GraphInitParams(
tenant_id="tenant",
app_id="app",
workflow_id="workflow",
init_params = build_test_graph_init_params(
graph_config=graph_config,
user_id="user",
user_from=UserFrom.ACCOUNT,
invoke_from=LegacyInvokeFrom.DEBUGGER,
call_depth=0,
invoke_from=InvokeFrom.DEBUGGER,
)
runtime_state = GraphRuntimeState(
variable_pool=VariablePool(system_variables=SystemVariable(user_id="user", files=[]), user_inputs={}),
@ -85,8 +77,12 @@ def test_node_normalizes_legacy_invoke_from_enum():
graph_runtime_state=runtime_state,
)
assert node.user_from == UserFrom.ACCOUNT
assert node.invoke_from == InvokeFrom.DEBUGGER
dify_ctx = node.require_dify_context()
assert dify_ctx.user_from == UserFrom.ACCOUNT
assert dify_ctx.invoke_from == InvokeFrom.DEBUGGER
assert node.get_run_context_value("missing") is None
with pytest.raises(ValueError):
node.require_run_context_value("missing")
def test_missing_generic_argument_raises_type_error():

View File

@ -5,9 +5,9 @@ import pandas as pd
import pytest
from docx.oxml.text.paragraph import CT_P
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities import GraphInitParams
from dify_graph.enums import NodeType, UserFrom, WorkflowNodeExecutionStatus
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
from dify_graph.file import File, FileTransferMethod
from dify_graph.node_events import NodeRunResult
from dify_graph.nodes.document_extractor import DocumentExtractorNode, DocumentExtractorNodeData
@ -20,15 +20,16 @@ from dify_graph.nodes.document_extractor.node import (
from dify_graph.variables import ArrayFileSegment
from dify_graph.variables.segments import ArrayStringSegment
from dify_graph.variables.variables import StringVariable
from tests.workflow_test_utils import build_test_graph_init_params
@pytest.fixture
def graph_init_params() -> GraphInitParams:
return GraphInitParams(
tenant_id="test_tenant",
app_id="test_app",
return build_test_graph_init_params(
workflow_id="test_workflow",
graph_config={},
tenant_id="test_tenant",
app_id="test_app",
user_id="test_user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -4,10 +4,10 @@ from unittest.mock import MagicMock, Mock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.file import File, FileTransferMethod, FileType
from dify_graph.graph import Graph
from dify_graph.nodes.if_else.entities import IfElseNodeData
@ -17,16 +17,17 @@ from dify_graph.system_variable import SystemVariable
from dify_graph.utils.condition.entities import Condition, SubCondition, SubVariableCondition
from dify_graph.variables import ArrayFileSegment
from extensions.ext_database import db
from tests.workflow_test_utils import build_test_graph_init_params
def test_execute_if_else_result_true():
graph_config = {"edges": [], "nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}]}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
@ -128,11 +129,11 @@ def test_execute_if_else_result_false():
# Create a simple graph for IfElse node testing
graph_config = {"edges": [], "nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}]}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
@ -229,14 +230,18 @@ def test_array_file_contains_file_name():
# Create properly configured mock for graph_init_params
graph_init_params = Mock()
graph_init_params.tenant_id = "test_tenant"
graph_init_params.app_id = "test_app"
graph_init_params.workflow_id = "test_workflow"
graph_init_params.graph_config = {}
graph_init_params.user_id = "test_user"
graph_init_params.user_from = UserFrom.ACCOUNT
graph_init_params.invoke_from = InvokeFrom.SERVICE_API
graph_init_params.call_depth = 0
graph_init_params.run_context = {
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
}
node = IfElseNode(
id=str(uuid.uuid4()),
@ -298,11 +303,11 @@ def test_execute_if_else_boolean_conditions(condition: Condition):
"""Test IfElseNode with boolean conditions using various operators"""
graph_config = {"edges": [], "nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}]}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
@ -353,11 +358,11 @@ def test_execute_if_else_boolean_false_conditions():
"""Test IfElseNode with boolean conditions that should evaluate to false"""
graph_config = {"edges": [], "nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}]}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
@ -422,11 +427,11 @@ def test_execute_if_else_boolean_cases_structure():
"""Test IfElseNode with boolean conditions using the new cases structure"""
graph_config = {"edges": [], "nodes": [{"data": {"type": "start", "title": "Start"}, "id": "start"}]}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
init_params = build_test_graph_init_params(
workflow_id="1",
graph_config=graph_config,
tenant_id="1",
app_id="1",
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,

View File

@ -2,8 +2,9 @@ from unittest.mock import MagicMock
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.enums import UserFrom, WorkflowNodeExecutionStatus
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.enums import WorkflowNodeExecutionStatus
from dify_graph.file import File, FileTransferMethod, FileType
from dify_graph.nodes.list_operator.entities import (
ExtractConfig,
@ -41,14 +42,18 @@ def list_operator_node():
}
# Create properly configured mock for graph_init_params
graph_init_params = MagicMock()
graph_init_params.tenant_id = "test_tenant"
graph_init_params.app_id = "test_app"
graph_init_params.workflow_id = "test_workflow"
graph_init_params.graph_config = {}
graph_init_params.user_id = "test_user"
graph_init_params.user_from = UserFrom.ACCOUNT
graph_init_params.invoke_from = InvokeFrom.SERVICE_API
graph_init_params.call_depth = 0
graph_init_params.run_context = {
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "test_tenant",
"app_id": "test_app",
"user_id": "test_user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
}
node = ListOperatorNode(
id="test_node_id",

View File

@ -4,12 +4,12 @@ import time
import pytest
from pydantic import ValidationError as PydanticValidationError
from dify_graph.entities import GraphInitParams
from dify_graph.nodes.start.entities import StartNodeData
from dify_graph.nodes.start.start_node import StartNode
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables.input_entities import VariableEntity, VariableEntityType
from tests.workflow_test_utils import build_test_graph_init_params
def make_start_node(user_inputs, variables):
@ -32,11 +32,11 @@ def make_start_node(user_inputs, variables):
return StartNode(
id="start",
config=config,
graph_init_params=GraphInitParams(
tenant_id="tenant",
app_id="app",
graph_init_params=build_test_graph_init_params(
workflow_id="wf",
graph_config={},
tenant_id="tenant",
app_id="app",
user_id="u",
user_from="account",
invoke_from="debugger",

View File

@ -10,13 +10,13 @@ import pytest
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.utils.message_transformer import ToolFileMessageTransformer
from dify_graph.entities import GraphInitParams
from dify_graph.file import File, FileTransferMethod, FileType
from dify_graph.model_runtime.entities.llm_entities import LLMUsage
from dify_graph.node_events import StreamChunkEvent, StreamCompletedEvent
from dify_graph.runtime import GraphRuntimeState, VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables.segments import ArrayFileSegment
from tests.workflow_test_utils import build_test_graph_init_params
if TYPE_CHECKING: # pragma: no cover - imported for type checking only
from dify_graph.nodes.tool.tool_node import ToolNode
@ -54,11 +54,11 @@ def tool_node(monkeypatch) -> ToolNode:
"edges": [],
}
init_params = GraphInitParams(
tenant_id="tenant-id",
app_id="app-id",
init_params = build_test_graph_init_params(
workflow_id="workflow-id",
graph_config=graph_config,
tenant_id="tenant-id",
app_id="app-id",
user_id="user-id",
user_from="account",
invoke_from="debugger",

View File

@ -2,10 +2,10 @@ import time
import uuid
from uuid import uuid4
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.graph import Graph
from dify_graph.graph_events.node import NodeRunSucceededEvent
from dify_graph.nodes.variable_assigner.common import helpers as common_helpers
@ -43,13 +43,17 @@ def test_overwrite_string_variable():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -141,13 +145,17 @@ def test_append_variable_to_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -236,13 +244,17 @@ def test_clear_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)

View File

@ -2,10 +2,10 @@ import time
import uuid
from uuid import uuid4
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from dify_graph.entities import GraphInitParams
from dify_graph.enums import UserFrom
from dify_graph.entities.graph_init_params import DIFY_RUN_CONTEXT_KEY
from dify_graph.graph import Graph
from dify_graph.nodes.variable_assigner.v2 import VariableAssignerNode
from dify_graph.nodes.variable_assigner.v2.enums import InputType, Operation
@ -85,13 +85,17 @@ def test_remove_first_from_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -169,13 +173,17 @@ def test_remove_last_from_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -250,13 +258,17 @@ def test_remove_first_from_empty_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -331,13 +343,17 @@ def test_remove_last_from_empty_array():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
@ -404,13 +420,17 @@ def test_node_factory_creates_variable_assigner_node():
}
init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_id="1",
graph_config=graph_config,
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.DEBUGGER,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.DEBUGGER,
}
},
call_depth=0,
)
variable_pool = VariablePool(

View File

@ -8,10 +8,9 @@ when passing files to downstream LLM nodes.
from unittest.mock import Mock, patch
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities.graph_init_params import GraphInitParams
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.enums import UserFrom
from dify_graph.nodes.trigger_webhook.entities import (
ContentType,
Method,
@ -22,7 +21,6 @@ from dify_graph.nodes.trigger_webhook.node import TriggerWebhookNode
from dify_graph.runtime.graph_runtime_state import GraphRuntimeState
from dify_graph.runtime.variable_pool import VariablePool
from dify_graph.system_variable import SystemVariable
from models.workflow import WorkflowType
def create_webhook_node(
@ -37,14 +35,17 @@ def create_webhook_node(
}
graph_init_params = GraphInitParams(
tenant_id=tenant_id,
app_id="test-app",
workflow_type=WorkflowType.WORKFLOW,
workflow_id="test-workflow",
graph_config={},
user_id="test-user",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": tenant_id,
"app_id": "test-app",
"user_id": "test-user",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)

View File

@ -2,10 +2,9 @@ from unittest.mock import patch
import pytest
from core.app.entities.app_invoke_entities import InvokeFrom
from dify_graph.entities.graph_init_params import GraphInitParams
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.enums import UserFrom
from dify_graph.file import File, FileTransferMethod, FileType
from dify_graph.nodes.trigger_webhook.entities import (
ContentType,
@ -19,7 +18,6 @@ from dify_graph.runtime.graph_runtime_state import GraphRuntimeState
from dify_graph.runtime.variable_pool import VariablePool
from dify_graph.system_variable import SystemVariable
from dify_graph.variables import FileVariable, StringVariable
from models.workflow import WorkflowType
def create_webhook_node(webhook_data: WebhookData, variable_pool: VariablePool) -> TriggerWebhookNode:
@ -30,14 +28,17 @@ def create_webhook_node(webhook_data: WebhookData, variable_pool: VariablePool)
}
graph_init_params = GraphInitParams(
tenant_id="1",
app_id="1",
workflow_type=WorkflowType.WORKFLOW,
workflow_id="1",
graph_config={},
user_id="1",
user_from=UserFrom.ACCOUNT,
invoke_from=InvokeFrom.SERVICE_API,
run_context={
DIFY_RUN_CONTEXT_KEY: {
"tenant_id": "1",
"app_id": "1",
"user_id": "1",
"user_from": UserFrom.ACCOUNT,
"invoke_from": InvokeFrom.SERVICE_API,
}
},
call_depth=0,
)
runtime_state = GraphRuntimeState(

View File

@ -2,9 +2,8 @@
from unittest.mock import MagicMock, patch
from core.app.entities.app_invoke_entities import InvokeFrom
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.workflow_entry import WorkflowEntry
from dify_graph.enums import UserFrom
from dify_graph.graph_engine.command_channels.redis_channel import RedisChannel
from dify_graph.runtime import GraphRuntimeState, VariablePool

View File

@ -0,0 +1,53 @@
from collections.abc import Mapping
from typing import Any
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom, build_dify_run_context
from dify_graph.entities.graph_init_params import GraphInitParams
def build_test_run_context(
*,
tenant_id: str = "tenant",
app_id: str = "app",
user_id: str = "user",
user_from: UserFrom | str = UserFrom.ACCOUNT,
invoke_from: InvokeFrom | str = InvokeFrom.DEBUGGER,
extra_context: Mapping[str, Any] | None = None,
) -> dict[str, Any]:
normalized_user_from = user_from if isinstance(user_from, UserFrom) else UserFrom(user_from)
normalized_invoke_from = invoke_from if isinstance(invoke_from, InvokeFrom) else InvokeFrom(invoke_from)
return build_dify_run_context(
tenant_id=tenant_id,
app_id=app_id,
user_id=user_id,
user_from=normalized_user_from,
invoke_from=normalized_invoke_from,
extra_context=extra_context,
)
def build_test_graph_init_params(
*,
workflow_id: str = "workflow",
graph_config: Mapping[str, Any] | None = None,
call_depth: int = 0,
tenant_id: str = "tenant",
app_id: str = "app",
user_id: str = "user",
user_from: UserFrom | str = UserFrom.ACCOUNT,
invoke_from: InvokeFrom | str = InvokeFrom.DEBUGGER,
extra_context: Mapping[str, Any] | None = None,
) -> GraphInitParams:
return GraphInitParams(
workflow_id=workflow_id,
graph_config=graph_config or {},
run_context=build_test_run_context(
tenant_id=tenant_id,
app_id=app_id,
user_id=user_id,
user_from=user_from,
invoke_from=invoke_from,
extra_context=extra_context,
),
call_depth=call_depth,
)