mirror of
https://gitee.com/dify_ai/dify.git
synced 2025-12-07 03:45:27 +08:00
Compare commits
3 Commits
feat/dynam
...
refactor/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b964db6bb6 | ||
|
|
f20190ad56 | ||
|
|
03e61ba09f |
@@ -31,7 +31,7 @@ from extensions.ext_database import db
|
||||
from factories import file_factory
|
||||
from models.account import Account
|
||||
from models.model import App, Conversation, EndUser, Message
|
||||
from models.workflow import Workflow
|
||||
from models.workflow import Workflow, WorkflowNodeExecutionTriggeredFrom
|
||||
from services.conversation_service import ConversationService
|
||||
from services.errors.message import MessageNotExistsError
|
||||
|
||||
@@ -167,6 +167,9 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
# Default for advanced chat app
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
@@ -235,6 +238,9 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
# For debugging
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP,
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
@@ -301,6 +307,8 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP, # For debugging
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -28,6 +28,7 @@ from core.repository.workflow_node_execution_repository import WorkflowNodeExecu
|
||||
from extensions.ext_database import db
|
||||
from factories import file_factory
|
||||
from models import Account, App, EndUser, Workflow
|
||||
from models.workflow import WorkflowNodeExecutionTriggeredFrom
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -142,6 +143,8 @@ class WorkflowAppGenerator(BaseAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN, # Default for workflow app
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
@@ -268,6 +271,8 @@ class WorkflowAppGenerator(BaseAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP, # For debugging
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
@@ -333,6 +338,8 @@ class WorkflowAppGenerator(BaseAppGenerator):
|
||||
params={
|
||||
"tenant_id": application_generate_entity.app_config.tenant_id,
|
||||
"app_id": application_generate_entity.app_config.app_id,
|
||||
"workflow_id": workflow.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP, # For debugging
|
||||
"session_factory": session_factory,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ from pydantic import BaseModel, ConfigDict
|
||||
|
||||
from core.model_runtime.entities.llm_entities import LLMResult
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import AgentNodeStrategyInit
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class TaskState(BaseModel):
|
||||
|
||||
@@ -51,6 +51,7 @@ from core.ops.entities.trace_entity import TraceTaskName
|
||||
from core.ops.ops_trace_manager import TraceQueueManager, TraceTask
|
||||
from core.repository.workflow_node_execution_repository import WorkflowNodeExecutionRepository
|
||||
from core.tools.tool_manager import ToolManager
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.nodes import NodeType
|
||||
@@ -62,7 +63,6 @@ from models.model import EndUser
|
||||
from models.workflow import (
|
||||
Workflow,
|
||||
WorkflowNodeExecution,
|
||||
WorkflowNodeExecutionStatus,
|
||||
WorkflowNodeExecutionTriggeredFrom,
|
||||
WorkflowRun,
|
||||
WorkflowRunStatus,
|
||||
|
||||
@@ -32,6 +32,7 @@ from core.ops.utils import filter_none_values
|
||||
from core.repository.repository_factory import RepositoryFactory
|
||||
from extensions.ext_database import db
|
||||
from models.model import EndUser
|
||||
from models.workflow import WorkflowNodeExecutionTriggeredFrom
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -114,7 +115,13 @@ class LangFuseDataTrace(BaseTraceInstance):
|
||||
# through workflow_run_id get all_nodes_execution using repository
|
||||
session_factory = sessionmaker(bind=db.engine)
|
||||
workflow_node_execution_repository = RepositoryFactory.create_workflow_node_execution_repository(
|
||||
params={"tenant_id": trace_info.tenant_id, "session_factory": session_factory},
|
||||
params={
|
||||
"tenant_id": trace_info.tenant_id,
|
||||
"app_id": trace_info.metadata.get("app_id"),
|
||||
"workflow_id": trace_info.workflow_data.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
"session_factory": session_factory,
|
||||
},
|
||||
)
|
||||
|
||||
# Get all executions for this workflow run
|
||||
@@ -233,7 +240,7 @@ class LangFuseDataTrace(BaseTraceInstance):
|
||||
|
||||
self.add_generation(langfuse_generation_data=node_generation_data)
|
||||
|
||||
def message_trace(self, trace_info: MessageTraceInfo, **kwargs):
|
||||
def message_trace(self, trace_info: MessageTraceInfo):
|
||||
# get message file data
|
||||
file_list = trace_info.file_list
|
||||
metadata = trace_info.metadata
|
||||
|
||||
@@ -31,6 +31,7 @@ from core.ops.utils import filter_none_values, generate_dotted_order
|
||||
from core.repository.repository_factory import RepositoryFactory
|
||||
from extensions.ext_database import db
|
||||
from models.model import EndUser, MessageFile
|
||||
from models.workflow import WorkflowNodeExecutionTriggeredFrom
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -141,6 +142,8 @@ class LangSmithDataTrace(BaseTraceInstance):
|
||||
params={
|
||||
"tenant_id": trace_info.tenant_id,
|
||||
"app_id": trace_info.metadata.get("app_id"),
|
||||
"workflow_id": trace_info.workflow_data.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
"session_factory": session_factory,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -25,6 +25,7 @@ from core.ops.entities.trace_entity import (
|
||||
from core.repository.repository_factory import RepositoryFactory
|
||||
from extensions.ext_database import db
|
||||
from models.model import EndUser, MessageFile
|
||||
from models.workflow import WorkflowNodeExecutionTriggeredFrom
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -154,6 +155,8 @@ class OpikDataTrace(BaseTraceInstance):
|
||||
params={
|
||||
"tenant_id": trace_info.tenant_id,
|
||||
"app_id": trace_info.metadata.get("app_id"),
|
||||
"workflow_id": trace_info.workflow_data.id,
|
||||
"triggered_from": WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
"session_factory": session_factory,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from .node_execution_entities import WorkflowNodeExecutionStatus
|
||||
|
||||
__all__ = ["WorkflowNodeExecutionStatus"]
|
||||
|
||||
@@ -5,7 +5,8 @@ from typing import Any, Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .node_execution_entities import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class NodeRunMetadataKey(StrEnum):
|
||||
|
||||
64
api/core/workflow/entities/node_execution_entities.py
Normal file
64
api/core/workflow/entities/node_execution_entities.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from datetime import datetime
|
||||
from enum import StrEnum
|
||||
from typing import Any, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class WorkflowNodeExecutionStatus(StrEnum):
|
||||
"""
|
||||
Workflow Node Execution Status Enum
|
||||
"""
|
||||
|
||||
RUNNING = "running"
|
||||
SUCCEEDED = "succeeded"
|
||||
FAILED = "failed"
|
||||
EXCEPTION = "exception"
|
||||
RETRY = "retry"
|
||||
|
||||
|
||||
class WorkflowNodeExecution(BaseModel):
|
||||
"""
|
||||
Core Workflow Node Execution Model
|
||||
|
||||
A minimal Pydantic model for workflow node execution that doesn't contain
|
||||
fields like tenant_id, app_id, etc. that aren't needed by the pure workflow core.
|
||||
|
||||
This model contains only the essential fields needed for the workflow core functionality.
|
||||
"""
|
||||
|
||||
id: str = Field(..., description="Execution ID")
|
||||
node_execution_id: Optional[str] = Field(None, description="Node execution ID, used for tracking execution")
|
||||
index: int = Field(..., description="Execution sequence number, used for displaying Tracing Node order")
|
||||
predecessor_node_id: Optional[str] = Field(
|
||||
None, description="Predecessor node ID, used for displaying execution path"
|
||||
)
|
||||
node_id: str = Field(..., description="Node ID")
|
||||
node_type: str = Field(..., description="Node type, such as 'start'")
|
||||
title: str = Field(..., description="Node title")
|
||||
|
||||
# Data fields
|
||||
inputs: Optional[dict[str, Any]] = Field(None, description="All predecessor node variable content used in the node")
|
||||
process_data: Optional[dict[str, Any]] = Field(None, description="Node process data")
|
||||
outputs: Optional[dict[str, Any]] = Field(None, description="Node output variables")
|
||||
|
||||
# Status and error information
|
||||
status: WorkflowNodeExecutionStatus = Field(WorkflowNodeExecutionStatus.RUNNING, description="Execution status")
|
||||
error: Optional[str] = Field(None, description="Error reason if status is failed")
|
||||
error_type: Optional[str] = Field(None, description="Error type if status is failed")
|
||||
|
||||
# Timing and performance
|
||||
elapsed_time: float = Field(0.0, description="Time consumption (s)")
|
||||
created_at: datetime = Field(default_factory=datetime.now, description="Run time")
|
||||
finished_at: Optional[datetime] = Field(None, description="End time")
|
||||
|
||||
# Metadata
|
||||
execution_metadata: Optional[dict[str, Any]] = Field(None, description="Execution metadata")
|
||||
|
||||
# For iteration/loop tracking
|
||||
workflow_run_id: Optional[str] = Field(None, description="Workflow run ID")
|
||||
|
||||
class Config:
|
||||
"""Pydantic model configuration"""
|
||||
|
||||
arbitrary_types_allowed = True
|
||||
@@ -5,8 +5,8 @@ from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class RouteNodeState(BaseModel):
|
||||
|
||||
@@ -14,6 +14,7 @@ from flask import Flask, current_app
|
||||
from configs import dify_config
|
||||
from core.app.apps.base_app_queue_manager import GenerateTaskStoppedError
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import AgentNodeStrategyInit, NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool, VariableValue
|
||||
from core.workflow.graph_engine.condition_handlers.condition_manager import ConditionManager
|
||||
@@ -54,7 +55,7 @@ from core.workflow.nodes.event import RunCompletedEvent, RunRetrieverResourceEve
|
||||
from core.workflow.nodes.node_mapping import NODE_TYPE_CLASSES_MAPPING
|
||||
from extensions.ext_database import db
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from core.provider_manager import ProviderManager
|
||||
from core.tools.entities.tool_entities import ToolParameter, ToolProviderType
|
||||
from core.tools.tool_manager import ToolManager
|
||||
from core.variables.segments import StringSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
@@ -25,7 +26,6 @@ from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
||||
from extensions.ext_database import db
|
||||
from factories.agent_factory import get_plugin_agent_strategy
|
||||
from models.model import Conversation
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class AgentNode(ToolNode):
|
||||
|
||||
@@ -2,6 +2,7 @@ from collections.abc import Mapping, Sequence
|
||||
from typing import Any, cast
|
||||
|
||||
from core.variables import ArrayFileSegment, FileSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.answer.answer_stream_generate_router import AnswerStreamGeneratorRouter
|
||||
from core.workflow.nodes.answer.entities import (
|
||||
@@ -13,7 +14,6 @@ from core.workflow.nodes.answer.entities import (
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class AnswerNode(BaseNode[AnswerNodeData]):
|
||||
|
||||
@@ -3,10 +3,10 @@ from abc import abstractmethod
|
||||
from collections.abc import Generator, Mapping, Sequence
|
||||
from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union, cast
|
||||
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.enums import CONTINUE_ON_ERROR_NODE_TYPE, RETRY_ON_ERROR_NODE_TYPE, NodeType
|
||||
from core.workflow.nodes.event import NodeEvent, RunCompletedEvent
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import BaseNodeData
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ from core.helper.code_executor.code_node_provider import CodeNodeProvider
|
||||
from core.helper.code_executor.javascript.javascript_code_provider import JavascriptCodeProvider
|
||||
from core.helper.code_executor.python3.python3_code_provider import Python3CodeProvider
|
||||
from core.variables.segments import ArrayFileSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.code.entities import CodeNodeData
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .exc import (
|
||||
CodeNodeError,
|
||||
|
||||
@@ -23,10 +23,10 @@ from core.file import File, FileTransferMethod, file_manager
|
||||
from core.helper import ssrf_proxy
|
||||
from core.variables import ArrayFileSegment
|
||||
from core.variables.segments import FileSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import DocumentExtractorNodeData
|
||||
from .exc import DocumentExtractorError, FileDownloadError, TextExtractionError, UnsupportedFileTypeError
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.end.entities import EndNodeData
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class EndNode(BaseNode[EndNodeData]):
|
||||
|
||||
@@ -3,8 +3,8 @@ from datetime import datetime
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class RunCompletedEvent(BaseModel):
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Any, Optional
|
||||
from configs import dify_config
|
||||
from core.file import File, FileTransferMethod
|
||||
from core.tools.tool_file_manager import ToolFileManager
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_entities import VariableSelector
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
@@ -13,7 +14,6 @@ from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.http_request.executor import Executor
|
||||
from core.workflow.utils import variable_template_parser
|
||||
from factories import file_factory
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import (
|
||||
HttpRequestNodeData,
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import Literal
|
||||
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
@@ -9,7 +10,6 @@ from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.if_else.entities import IfElseNodeData
|
||||
from core.workflow.utils.condition.entities import Condition
|
||||
from core.workflow.utils.condition.processor import ConditionProcessor
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class IfElseNode(BaseNode[IfElseNodeData]):
|
||||
|
||||
@@ -11,6 +11,7 @@ from flask import Flask, current_app
|
||||
|
||||
from configs import dify_config
|
||||
from core.variables import ArrayVariable, IntegerVariable, NoneVariable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import (
|
||||
NodeRunMetadataKey,
|
||||
NodeRunResult,
|
||||
@@ -37,7 +38,6 @@ from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.event import NodeEvent, RunCompletedEvent
|
||||
from core.workflow.nodes.iteration.entities import ErrorHandleMode, IterationNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .exc import (
|
||||
InvalidIteratorValueError,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.iteration.entities import IterationStartNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class IterationStartNode(BaseNode[IterationStartNodeData]):
|
||||
|
||||
@@ -23,6 +23,7 @@ from core.rag.entities.metadata_entities import Condition, MetadataCondition
|
||||
from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
||||
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
||||
from core.variables import StringSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.event.event import ModelInvokeCompletedEvent
|
||||
@@ -41,7 +42,6 @@ from extensions.ext_database import db
|
||||
from extensions.ext_redis import redis_client
|
||||
from libs.json_in_md_parser import parse_and_check_json_markdown
|
||||
from models.dataset import Dataset, DatasetMetadata, Document, RateLimitLog
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
from services.feature_service import FeatureService
|
||||
|
||||
from .entities import KnowledgeRetrievalNodeData, ModelConfig
|
||||
|
||||
@@ -3,10 +3,10 @@ from typing import Any, Literal, Union
|
||||
|
||||
from core.file import File
|
||||
from core.variables import ArrayFileSegment, ArrayNumberSegment, ArrayStringSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import ListOperatorNodeData
|
||||
from .exc import InvalidConditionError, InvalidFilterValueError, InvalidKeyError, ListOperatorError
|
||||
|
||||
@@ -51,6 +51,7 @@ from core.variables import (
|
||||
StringSegment,
|
||||
)
|
||||
from core.workflow.constants import SYSTEM_VARIABLE_NODE_ID
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.entities.variable_entities import VariableSelector
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
@@ -75,7 +76,6 @@ from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
||||
from extensions.ext_database import db
|
||||
from models.model import Conversation
|
||||
from models.provider import Provider, ProviderType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import (
|
||||
LLMNodeChatModelMessage,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.loop.entities import LoopEndNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class LoopEndNode(BaseNode[LoopEndNodeData]):
|
||||
|
||||
@@ -15,6 +15,7 @@ from core.variables import (
|
||||
SegmentType,
|
||||
StringSegment,
|
||||
)
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.graph_engine.entities.event import (
|
||||
BaseGraphEvent,
|
||||
@@ -37,7 +38,6 @@ from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.event import NodeEvent, RunCompletedEvent
|
||||
from core.workflow.nodes.loop.entities import LoopNodeData
|
||||
from core.workflow.utils.condition.processor import ConditionProcessor
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.loop.entities import LoopStartNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class LoopStartNode(BaseNode[LoopStartNodeData]):
|
||||
|
||||
@@ -25,13 +25,13 @@ from core.prompt.advanced_prompt_transform import AdvancedPromptTransform
|
||||
from core.prompt.entities.advanced_prompt_entities import ChatModelMessage, CompletionModelPromptTemplate
|
||||
from core.prompt.simple_prompt_transform import ModelMode
|
||||
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.llm import LLMNode, ModelConfig
|
||||
from core.workflow.utils import variable_template_parser
|
||||
from extensions.ext_database import db
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import ParameterExtractorNodeData
|
||||
from .exc import (
|
||||
|
||||
@@ -10,6 +10,7 @@ from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.prompt.advanced_prompt_transform import AdvancedPromptTransform
|
||||
from core.prompt.simple_prompt_transform import ModelMode
|
||||
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.event import ModelInvokeCompletedEvent
|
||||
@@ -20,7 +21,6 @@ from core.workflow.nodes.llm import (
|
||||
)
|
||||
from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
||||
from libs.json_in_md_parser import parse_and_check_json_markdown
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .entities import QuestionClassifierNodeData
|
||||
from .exc import InvalidModelTypeError
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from core.workflow.constants import SYSTEM_VARIABLE_NODE_ID
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.start.entities import StartNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class StartNode(BaseNode[StartNodeData]):
|
||||
|
||||
@@ -3,11 +3,11 @@ from collections.abc import Mapping, Sequence
|
||||
from typing import Any, Optional
|
||||
|
||||
from core.helper.code_executor.code_executor import CodeExecutionError, CodeExecutor, CodeLanguage
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.template_transform.entities import TemplateTransformNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
MAX_TEMPLATE_TRANSFORM_OUTPUT_LENGTH = int(os.environ.get("TEMPLATE_TRANSFORM_MAX_LENGTH", "80000"))
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from core.tools.tool_engine import ToolEngine
|
||||
from core.tools.utils.message_transformer import ToolFileMessageTransformer
|
||||
from core.variables.segments import ArrayAnySegment
|
||||
from core.variables.variables import ArrayAnyVariable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
@@ -25,7 +26,6 @@ from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
||||
from extensions.ext_database import db
|
||||
from factories import file_factory
|
||||
from models import ToolFile
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
from services.tools.builtin_tools_manage_service import BuiltinToolManageService
|
||||
|
||||
from .entities import ToolNodeData
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.variable_aggregator.entities import VariableAssignerNodeData
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
class VariableAggregatorNode(BaseNode[VariableAssignerNodeData]):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from core.variables import SegmentType, Variable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.variable_assigner.common import helpers as common_helpers
|
||||
from core.workflow.nodes.variable_assigner.common.exc import VariableOperatorNodeError
|
||||
from factories import variable_factory
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from .node_data import VariableAssignerData, WriteMode
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ from typing import Any, cast
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.variables import SegmentType, Variable
|
||||
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.base import BaseNode
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from core.workflow.nodes.variable_assigner.common import helpers as common_helpers
|
||||
from core.workflow.nodes.variable_assigner.common.exc import VariableOperatorNodeError
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
from . import helpers
|
||||
from .constants import EMPTY_VALUE_MAPPING
|
||||
|
||||
@@ -85,7 +85,6 @@ from .workflow import (
|
||||
WorkflowAppLog,
|
||||
WorkflowAppLogCreatedFrom,
|
||||
WorkflowNodeExecution,
|
||||
WorkflowNodeExecutionStatus,
|
||||
WorkflowNodeExecutionTriggeredFrom,
|
||||
WorkflowRun,
|
||||
WorkflowRunStatus,
|
||||
|
||||
@@ -524,18 +524,6 @@ class WorkflowNodeExecutionTriggeredFrom(StrEnum):
|
||||
WORKFLOW_RUN = "workflow-run"
|
||||
|
||||
|
||||
class WorkflowNodeExecutionStatus(StrEnum):
|
||||
"""
|
||||
Workflow Node Execution Status Enum
|
||||
"""
|
||||
|
||||
RUNNING = "running"
|
||||
SUCCEEDED = "succeeded"
|
||||
FAILED = "failed"
|
||||
EXCEPTION = "exception"
|
||||
RETRY = "retry"
|
||||
|
||||
|
||||
class WorkflowNodeExecution(Base):
|
||||
"""
|
||||
Workflow Node Execution
|
||||
|
||||
@@ -11,7 +11,7 @@ from typing import Any
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from configs import dify_config
|
||||
from core.repository.repository_factory import RepositoryFactory
|
||||
from core.repository import RepositoryFactory
|
||||
from extensions.ext_database import db
|
||||
from repositories.workflow_node_execution import SQLAlchemyWorkflowNodeExecutionRepository
|
||||
|
||||
@@ -58,6 +58,11 @@ def create_workflow_node_execution_repository(params: Mapping[str, Any]) -> SQLA
|
||||
params: Parameters for creating the repository, including:
|
||||
- tenant_id: Required. The tenant ID for multi-tenancy.
|
||||
- app_id: Optional. The application ID for filtering.
|
||||
- workflow_id: Optional. The workflow ID for filtering.
|
||||
- triggered_from: Optional. The triggered_from value for filtering
|
||||
(WorkflowNodeExecutionTriggeredFrom enum).
|
||||
- created_by_role: Optional. The creator role for new executions.
|
||||
- created_by: Optional. The creator ID for new executions.
|
||||
- session_factory: Optional. A SQLAlchemy sessionmaker instance. If not provided,
|
||||
a new sessionmaker will be created using the global database engine.
|
||||
|
||||
@@ -74,6 +79,10 @@ def create_workflow_node_execution_repository(params: Mapping[str, Any]) -> SQLA
|
||||
|
||||
# Extract optional parameters
|
||||
app_id = params.get("app_id")
|
||||
workflow_id = params.get("workflow_id")
|
||||
triggered_from = params.get("triggered_from")
|
||||
created_by_role = params.get("created_by_role")
|
||||
created_by = params.get("created_by")
|
||||
|
||||
# Use the session_factory from params if provided, otherwise create one using the global db engine
|
||||
session_factory = params.get("session_factory")
|
||||
@@ -83,5 +92,11 @@ def create_workflow_node_execution_repository(params: Mapping[str, Any]) -> SQLA
|
||||
|
||||
# Create and return the repository
|
||||
return SQLAlchemyWorkflowNodeExecutionRepository(
|
||||
session_factory=session_factory, tenant_id=tenant_id, app_id=app_id
|
||||
session_factory=session_factory,
|
||||
tenant_id=tenant_id,
|
||||
app_id=app_id,
|
||||
workflow_id=workflow_id,
|
||||
triggered_from=triggered_from,
|
||||
created_by_role=created_by_role,
|
||||
created_by=created_by,
|
||||
)
|
||||
|
||||
@@ -11,7 +11,8 @@ from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from core.repository.workflow_node_execution_repository import OrderConfig
|
||||
from models.workflow import WorkflowNodeExecution, WorkflowNodeExecutionStatus, WorkflowNodeExecutionTriggeredFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from models.workflow import WorkflowNodeExecution, WorkflowNodeExecutionTriggeredFrom
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,14 +26,27 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
to the database. This prevents long-running connections in the workflow core.
|
||||
"""
|
||||
|
||||
def __init__(self, session_factory: sessionmaker | Engine, tenant_id: str, app_id: Optional[str] = None):
|
||||
def __init__(
|
||||
self,
|
||||
session_factory: sessionmaker | Engine,
|
||||
tenant_id: str,
|
||||
app_id: str | None = None,
|
||||
workflow_id: str | None = None,
|
||||
triggered_from: WorkflowNodeExecutionTriggeredFrom | None = None,
|
||||
created_by_role: str | None = None,
|
||||
created_by: str | None = None,
|
||||
):
|
||||
"""
|
||||
Initialize the repository with a SQLAlchemy sessionmaker or engine and tenant context.
|
||||
Initialize the repository with a SQLAlchemy sessionmaker or engine and context parameters.
|
||||
|
||||
Args:
|
||||
session_factory: SQLAlchemy sessionmaker or engine for creating sessions
|
||||
tenant_id: Tenant ID for multi-tenancy
|
||||
app_id: Optional app ID for filtering by application
|
||||
app_id: App ID for filtering by application (optional)
|
||||
workflow_id: Workflow ID for filtering by workflow (optional)
|
||||
triggered_from: Triggered_from value (WorkflowNodeExecutionTriggeredFrom enum) (optional)
|
||||
created_by_role: Creator role (e.g., 'account', 'end_user') (optional)
|
||||
created_by: Creator ID (optional)
|
||||
"""
|
||||
# If an engine is provided, create a sessionmaker from it
|
||||
if isinstance(session_factory, Engine):
|
||||
@@ -46,6 +60,10 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
|
||||
self._tenant_id = tenant_id
|
||||
self._app_id = app_id
|
||||
self._workflow_id = workflow_id
|
||||
self._triggered_from = triggered_from
|
||||
self._created_by_role = created_by_role
|
||||
self._created_by = created_by
|
||||
|
||||
def save(self, execution: WorkflowNodeExecution) -> None:
|
||||
"""
|
||||
@@ -55,14 +73,25 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
execution: The WorkflowNodeExecution instance to save
|
||||
"""
|
||||
with self._session_factory() as session:
|
||||
# Ensure tenant_id is set
|
||||
if not execution.tenant_id:
|
||||
execution.tenant_id = self._tenant_id
|
||||
# Always set tenant_id from the repository context
|
||||
execution.tenant_id = self._tenant_id
|
||||
|
||||
# Set app_id if provided and not already set
|
||||
if self._app_id and not execution.app_id:
|
||||
# Set other fields only if they are provided in the repository
|
||||
if self._app_id is not None:
|
||||
execution.app_id = self._app_id
|
||||
|
||||
if self._workflow_id is not None:
|
||||
execution.workflow_id = self._workflow_id
|
||||
|
||||
if self._triggered_from is not None:
|
||||
execution.triggered_from = self._triggered_from
|
||||
|
||||
if self._created_by_role is not None:
|
||||
execution.created_by_role = self._created_by_role
|
||||
|
||||
if self._created_by is not None:
|
||||
execution.created_by = self._created_by
|
||||
|
||||
session.add(execution)
|
||||
session.commit()
|
||||
|
||||
@@ -82,9 +111,16 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
WorkflowNodeExecution.tenant_id == self._tenant_id,
|
||||
)
|
||||
|
||||
# Apply additional filters if provided
|
||||
if self._app_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.app_id == self._app_id)
|
||||
|
||||
if self._workflow_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.workflow_id == self._workflow_id)
|
||||
|
||||
if self._triggered_from:
|
||||
stmt = stmt.where(WorkflowNodeExecution.triggered_from == self._triggered_from)
|
||||
|
||||
return session.scalar(stmt)
|
||||
|
||||
def get_by_workflow_run(
|
||||
@@ -108,12 +144,24 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
stmt = select(WorkflowNodeExecution).where(
|
||||
WorkflowNodeExecution.workflow_run_id == workflow_run_id,
|
||||
WorkflowNodeExecution.tenant_id == self._tenant_id,
|
||||
WorkflowNodeExecution.triggered_from == WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
)
|
||||
|
||||
# Use the triggered_from from the instance if provided, otherwise use the default
|
||||
if self._triggered_from:
|
||||
stmt = stmt.where(WorkflowNodeExecution.triggered_from == self._triggered_from)
|
||||
else:
|
||||
# Default behavior for backward compatibility
|
||||
stmt = stmt.where(
|
||||
WorkflowNodeExecution.triggered_from == WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN
|
||||
)
|
||||
|
||||
# Apply additional filters if provided
|
||||
if self._app_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.app_id == self._app_id)
|
||||
|
||||
if self._workflow_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.workflow_id == self._workflow_id)
|
||||
|
||||
# Apply ordering if provided
|
||||
if order_config and order_config.order_by:
|
||||
order_columns: list[UnaryExpression] = []
|
||||
@@ -146,12 +194,24 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
WorkflowNodeExecution.workflow_run_id == workflow_run_id,
|
||||
WorkflowNodeExecution.tenant_id == self._tenant_id,
|
||||
WorkflowNodeExecution.status == WorkflowNodeExecutionStatus.RUNNING,
|
||||
WorkflowNodeExecution.triggered_from == WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN,
|
||||
)
|
||||
|
||||
# Use the triggered_from from the instance if provided, otherwise use the default
|
||||
if self._triggered_from:
|
||||
stmt = stmt.where(WorkflowNodeExecution.triggered_from == self._triggered_from)
|
||||
else:
|
||||
# Default behavior for backward compatibility
|
||||
stmt = stmt.where(
|
||||
WorkflowNodeExecution.triggered_from == WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN
|
||||
)
|
||||
|
||||
# Apply additional filters if provided
|
||||
if self._app_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.app_id == self._app_id)
|
||||
|
||||
if self._workflow_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.workflow_id == self._workflow_id)
|
||||
|
||||
return session.scalars(stmt).all()
|
||||
|
||||
def update(self, execution: WorkflowNodeExecution) -> None:
|
||||
@@ -162,35 +222,96 @@ class SQLAlchemyWorkflowNodeExecutionRepository:
|
||||
execution: The WorkflowNodeExecution instance to update
|
||||
"""
|
||||
with self._session_factory() as session:
|
||||
# Ensure tenant_id is set
|
||||
if not execution.tenant_id:
|
||||
execution.tenant_id = self._tenant_id
|
||||
# Always set tenant_id from the repository context
|
||||
execution.tenant_id = self._tenant_id
|
||||
|
||||
# Set app_id if provided and not already set
|
||||
if self._app_id and not execution.app_id:
|
||||
# Set other fields only if they are provided in the repository
|
||||
if self._app_id is not None:
|
||||
execution.app_id = self._app_id
|
||||
|
||||
if self._workflow_id is not None:
|
||||
execution.workflow_id = self._workflow_id
|
||||
|
||||
if self._triggered_from is not None:
|
||||
execution.triggered_from = self._triggered_from
|
||||
|
||||
if self._created_by_role is not None:
|
||||
execution.created_by_role = self._created_by_role
|
||||
|
||||
if self._created_by is not None:
|
||||
execution.created_by = self._created_by
|
||||
|
||||
session.merge(execution)
|
||||
session.commit()
|
||||
|
||||
def update_context(
|
||||
self,
|
||||
app_id: str | None = None,
|
||||
workflow_id: str | None = None,
|
||||
triggered_from: WorkflowNodeExecutionTriggeredFrom | None = None,
|
||||
created_by_role: str | None = None,
|
||||
created_by: str | None = None,
|
||||
) -> None:
|
||||
"""
|
||||
Update the repository's context parameters.
|
||||
|
||||
This method allows updating the repository's context parameters after initialization.
|
||||
Only parameters that are not None will be updated.
|
||||
|
||||
Args:
|
||||
app_id: New app ID for filtering
|
||||
workflow_id: New workflow ID for filtering
|
||||
triggered_from: New triggered_from value (WorkflowNodeExecutionTriggeredFrom enum)
|
||||
created_by_role: New creator role
|
||||
created_by: New creator ID
|
||||
"""
|
||||
if app_id is not None:
|
||||
self._app_id = app_id
|
||||
if workflow_id is not None:
|
||||
self._workflow_id = workflow_id
|
||||
if triggered_from is not None:
|
||||
self._triggered_from = triggered_from
|
||||
if created_by_role is not None:
|
||||
self._created_by_role = created_by_role
|
||||
if created_by is not None:
|
||||
self._created_by = created_by
|
||||
|
||||
def clear(self) -> None:
|
||||
"""
|
||||
Clear all WorkflowNodeExecution records for the current tenant_id and app_id.
|
||||
Clear all WorkflowNodeExecution records for the current tenant_id and other filters.
|
||||
|
||||
This method deletes all WorkflowNodeExecution records that match the tenant_id
|
||||
and app_id (if provided) associated with this repository instance.
|
||||
and other filters (app_id, workflow_id, triggered_from) associated with this repository instance.
|
||||
"""
|
||||
with self._session_factory() as session:
|
||||
stmt = delete(WorkflowNodeExecution).where(WorkflowNodeExecution.tenant_id == self._tenant_id)
|
||||
|
||||
# Apply additional filters if provided
|
||||
if self._app_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.app_id == self._app_id)
|
||||
|
||||
if self._workflow_id:
|
||||
stmt = stmt.where(WorkflowNodeExecution.workflow_id == self._workflow_id)
|
||||
|
||||
if self._triggered_from:
|
||||
stmt = stmt.where(WorkflowNodeExecution.triggered_from == self._triggered_from)
|
||||
|
||||
result = session.execute(stmt)
|
||||
session.commit()
|
||||
|
||||
# Build log message with all applied filters
|
||||
filter_parts = []
|
||||
if self._tenant_id:
|
||||
filter_parts.append(f"tenant {self._tenant_id}")
|
||||
if self._app_id:
|
||||
filter_parts.append(f"app {self._app_id}")
|
||||
|
||||
if self._workflow_id:
|
||||
filter_parts.append(f"workflow {self._workflow_id}")
|
||||
|
||||
if self._triggered_from:
|
||||
filter_parts.append(f"triggered_from {self._triggered_from}")
|
||||
|
||||
filters_str = " and ".join(filter_parts)
|
||||
deleted_count = result.rowcount
|
||||
logger.info(
|
||||
f"Cleared {deleted_count} workflow node execution records for tenant {self._tenant_id}"
|
||||
+ (f" and app {self._app_id}" if self._app_id else "")
|
||||
)
|
||||
logger.info(f"Cleared {deleted_count} workflow node execution records for {filters_str}")
|
||||
|
||||
@@ -133,6 +133,8 @@ class WorkflowRunService:
|
||||
params={
|
||||
"tenant_id": app_model.tenant_id,
|
||||
"app_id": app_model.id,
|
||||
"workflow_id": workflow_run.workflow_id,
|
||||
"triggered_from": workflow_run.triggered_from,
|
||||
"session_factory": db.session.get_bind(),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ from core.app.apps.workflow.app_config_manager import WorkflowAppConfigManager
|
||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||
from core.repository import RepositoryFactory
|
||||
from core.variables import Variable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.errors import WorkflowNodeRunFailedError
|
||||
from core.workflow.graph_engine.entities.event import InNodeEvent
|
||||
@@ -32,7 +33,6 @@ from models.tools import WorkflowToolProvider
|
||||
from models.workflow import (
|
||||
Workflow,
|
||||
WorkflowNodeExecution,
|
||||
WorkflowNodeExecutionStatus,
|
||||
WorkflowNodeExecutionTriggeredFrom,
|
||||
WorkflowType,
|
||||
)
|
||||
@@ -289,6 +289,10 @@ class WorkflowService:
|
||||
params={
|
||||
"tenant_id": app_model.tenant_id,
|
||||
"app_id": app_model.id,
|
||||
"workflow_id": draft_workflow.id,
|
||||
"triggered_from": workflow_node_execution.triggered_from,
|
||||
"created_by_role": workflow_node_execution.created_by_role,
|
||||
"created_by": workflow_node_execution.created_by,
|
||||
"session_factory": db.session.get_bind(),
|
||||
}
|
||||
)
|
||||
@@ -388,7 +392,7 @@ class WorkflowService:
|
||||
workflow_node_execution = WorkflowNodeExecution()
|
||||
workflow_node_execution.id = str(uuid4())
|
||||
workflow_node_execution.tenant_id = tenant_id
|
||||
workflow_node_execution.triggered_from = WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP.value
|
||||
workflow_node_execution.triggered_from = WorkflowNodeExecutionTriggeredFrom.SINGLE_STEP
|
||||
workflow_node_execution.index = 1
|
||||
workflow_node_execution.node_id = node_id
|
||||
workflow_node_execution.node_type = node_instance.node_type
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import cast
|
||||
import pytest
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
@@ -15,7 +16,7 @@ from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntime
|
||||
from core.workflow.nodes.code.code_node import CodeNode
|
||||
from core.workflow.nodes.code.entities import CodeNodeData
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
from tests.integration_tests.workflow.nodes.__mock.code_executor import setup_code_executor_mock
|
||||
|
||||
CODE_MAX_STRING_LENGTH = int(getenv("CODE_MAX_STRING_LENGTH", "10000"))
|
||||
|
||||
@@ -8,6 +8,7 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -17,7 +18,7 @@ from core.workflow.nodes.event import RunCompletedEvent
|
||||
from core.workflow.nodes.llm.node import LLMNode
|
||||
from extensions.ext_database import db
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
from tests.integration_tests.workflow.nodes.__mock.model import get_mocked_fetch_model_config
|
||||
|
||||
"""FOR MOCK FIXTURES, DO NOT REMOVE"""
|
||||
|
||||
@@ -4,6 +4,7 @@ import uuid
|
||||
import pytest
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -11,7 +12,7 @@ from core.workflow.graph_engine.entities.graph_init_params import GraphInitParam
|
||||
from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntimeState
|
||||
from core.workflow.nodes.template_transform.template_transform_node import TemplateTransformNode
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
from tests.integration_tests.workflow.nodes.__mock.code_executor import setup_code_executor_mock
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from unittest.mock import MagicMock
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.tools.utils.configuration import ToolParameterConfigurationManager
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -12,7 +13,7 @@ from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntime
|
||||
from core.workflow.nodes.event.event import RunCompletedEvent
|
||||
from core.workflow.nodes.tool.tool_node import ToolNode
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def init_tool_node(config: dict):
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
from flask import Flask
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
@@ -25,7 +26,7 @@ from core.workflow.nodes.event import RunCompletedEvent, RunStreamChunkEvent
|
||||
from core.workflow.nodes.llm.node import LLMNode
|
||||
from core.workflow.nodes.question_classifier.question_classifier_node import QuestionClassifierNode
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -3,6 +3,7 @@ import uuid
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -11,7 +12,7 @@ from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntime
|
||||
from core.workflow.nodes.answer.answer_node import AnswerNode
|
||||
from extensions.ext_database import db
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def test_execute_answer():
|
||||
|
||||
@@ -3,6 +3,7 @@ import httpx
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.file import File, FileTransferMethod, FileType
|
||||
from core.variables import ArrayFileVariable, FileVariable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.graph_engine import Graph, GraphInitParams, GraphRuntimeState
|
||||
from core.workflow.nodes.answer import AnswerStreamGenerateRoute
|
||||
@@ -15,7 +16,7 @@ from core.workflow.nodes.http_request import (
|
||||
HttpRequestNodeData,
|
||||
)
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def test_http_request_node_binary_file(monkeypatch):
|
||||
|
||||
@@ -3,6 +3,7 @@ import uuid
|
||||
from unittest.mock import patch
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
@@ -14,7 +15,7 @@ from core.workflow.nodes.iteration.entities import ErrorHandleMode
|
||||
from core.workflow.nodes.iteration.iteration_node import IterationNode
|
||||
from core.workflow.nodes.template_transform.template_transform_node import TemplateTransformNode
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def test_run():
|
||||
|
||||
@@ -3,6 +3,7 @@ import uuid
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -11,7 +12,7 @@ from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntime
|
||||
from core.workflow.nodes.answer.answer_node import AnswerNode
|
||||
from extensions.ext_database import db
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def test_execute_answer():
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.event import (
|
||||
@@ -14,7 +15,7 @@ from core.workflow.graph_engine.graph_engine import GraphEngine
|
||||
from core.workflow.nodes.event.event import RunCompletedEvent, RunStreamChunkEvent
|
||||
from core.workflow.nodes.llm.node import LLMNode
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
class ContinueOnErrorTestHelper:
|
||||
|
||||
@@ -6,6 +6,7 @@ from docx.oxml.text.paragraph import CT_P
|
||||
from core.file import File, FileTransferMethod
|
||||
from core.variables import ArrayFileSegment
|
||||
from core.variables.variables import StringVariable
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.nodes.document_extractor import DocumentExtractorNode, DocumentExtractorNodeData
|
||||
from core.workflow.nodes.document_extractor.node import (
|
||||
@@ -14,7 +15,6 @@ from core.workflow.nodes.document_extractor.node import (
|
||||
_extract_text_from_plain_text,
|
||||
)
|
||||
from core.workflow.nodes.enums import NodeType
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -5,6 +5,7 @@ from unittest.mock import MagicMock, Mock
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.file import File, FileTransferMethod, FileType
|
||||
from core.variables import ArrayFileSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.enums import SystemVariableKey
|
||||
from core.workflow.graph_engine.entities.graph import Graph
|
||||
@@ -15,7 +16,7 @@ from core.workflow.nodes.if_else.if_else_node import IfElseNode
|
||||
from core.workflow.utils.condition.entities import Condition, SubCondition, SubVariableCondition
|
||||
from extensions.ext_database import db
|
||||
from models.enums import UserFrom
|
||||
from models.workflow import WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models.workflow import WorkflowType
|
||||
|
||||
|
||||
def test_execute_if_else_result_true():
|
||||
|
||||
@@ -4,6 +4,7 @@ import pytest
|
||||
|
||||
from core.file import File, FileTransferMethod, FileType
|
||||
from core.variables import ArrayFileSegment
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.nodes.list_operator.entities import (
|
||||
ExtractConfig,
|
||||
FilterBy,
|
||||
@@ -14,7 +15,6 @@ from core.workflow.nodes.list_operator.entities import (
|
||||
)
|
||||
from core.workflow.nodes.list_operator.exc import InvalidKeyError
|
||||
from core.workflow.nodes.list_operator.node import ListOperatorNode, _get_file_extract_string_func
|
||||
from models.workflow import WorkflowNodeExecutionStatus
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -5,6 +5,7 @@ import pytest
|
||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolProviderType
|
||||
from core.tools.errors import ToolInvokeError
|
||||
from core.workflow.entities import WorkflowNodeExecutionStatus
|
||||
from core.workflow.entities.node_entities import NodeRunResult
|
||||
from core.workflow.entities.variable_pool import VariablePool
|
||||
from core.workflow.graph_engine import Graph, GraphInitParams, GraphRuntimeState
|
||||
@@ -14,7 +15,7 @@ from core.workflow.nodes.enums import ErrorStrategy
|
||||
from core.workflow.nodes.event import RunCompletedEvent
|
||||
from core.workflow.nodes.tool import ToolNode
|
||||
from core.workflow.nodes.tool.entities import ToolNodeData
|
||||
from models import UserFrom, WorkflowNodeExecutionStatus, WorkflowType
|
||||
from models import UserFrom, WorkflowType
|
||||
|
||||
|
||||
def _create_tool_node():
|
||||
|
||||
Reference in New Issue
Block a user