mirror of
https://github.com/langgenius/dify.git
synced 2026-02-19 01:14:44 +08:00
refactor(workflow-file): move core.file to core.workflow.file (#32252)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
6824eda1c6
commit
7656d514b9
@ -115,18 +115,15 @@ ignore_imports =
|
|||||||
core.workflow.nodes.datasource.datasource_node -> models.tools
|
core.workflow.nodes.datasource.datasource_node -> models.tools
|
||||||
core.workflow.nodes.datasource.datasource_node -> services.datasource_provider_service
|
core.workflow.nodes.datasource.datasource_node -> services.datasource_provider_service
|
||||||
core.workflow.nodes.document_extractor.node -> configs
|
core.workflow.nodes.document_extractor.node -> configs
|
||||||
core.workflow.nodes.document_extractor.node -> core.file.file_manager
|
|
||||||
core.workflow.nodes.document_extractor.node -> core.helper.ssrf_proxy
|
core.workflow.nodes.document_extractor.node -> core.helper.ssrf_proxy
|
||||||
core.workflow.nodes.http_request.entities -> configs
|
core.workflow.nodes.http_request.entities -> configs
|
||||||
core.workflow.nodes.http_request.executor -> configs
|
core.workflow.nodes.http_request.executor -> configs
|
||||||
core.workflow.nodes.http_request.executor -> core.file.file_manager
|
|
||||||
core.workflow.nodes.http_request.node -> configs
|
core.workflow.nodes.http_request.node -> configs
|
||||||
core.workflow.nodes.http_request.node -> core.tools.tool_file_manager
|
core.workflow.nodes.http_request.node -> core.tools.tool_file_manager
|
||||||
core.workflow.nodes.iteration.iteration_node -> core.app.workflow.node_factory
|
core.workflow.nodes.iteration.iteration_node -> core.app.workflow.node_factory
|
||||||
core.workflow.nodes.knowledge_index.knowledge_index_node -> core.rag.index_processor.index_processor_factory
|
core.workflow.nodes.knowledge_index.knowledge_index_node -> core.rag.index_processor.index_processor_factory
|
||||||
core.workflow.nodes.llm.llm_utils -> configs
|
core.workflow.nodes.llm.llm_utils -> configs
|
||||||
core.workflow.nodes.llm.llm_utils -> core.app.entities.app_invoke_entities
|
core.workflow.nodes.llm.llm_utils -> core.app.entities.app_invoke_entities
|
||||||
core.workflow.nodes.llm.llm_utils -> core.file.models
|
|
||||||
core.workflow.nodes.llm.llm_utils -> core.model_manager
|
core.workflow.nodes.llm.llm_utils -> core.model_manager
|
||||||
core.workflow.nodes.llm.llm_utils -> core.model_runtime.model_providers.__base.large_language_model
|
core.workflow.nodes.llm.llm_utils -> core.model_runtime.model_providers.__base.large_language_model
|
||||||
core.workflow.nodes.llm.llm_utils -> models.model
|
core.workflow.nodes.llm.llm_utils -> models.model
|
||||||
@ -162,36 +159,10 @@ ignore_imports =
|
|||||||
core.workflow.nodes.llm.llm_utils -> core.entities.provider_entities
|
core.workflow.nodes.llm.llm_utils -> core.entities.provider_entities
|
||||||
core.workflow.nodes.parameter_extractor.parameter_extractor_node -> core.model_manager
|
core.workflow.nodes.parameter_extractor.parameter_extractor_node -> core.model_manager
|
||||||
core.workflow.nodes.question_classifier.question_classifier_node -> core.model_manager
|
core.workflow.nodes.question_classifier.question_classifier_node -> core.model_manager
|
||||||
core.workflow.node_events.node -> core.file
|
|
||||||
core.workflow.nodes.agent.agent_node -> core.file
|
|
||||||
core.workflow.nodes.datasource.datasource_node -> core.file
|
|
||||||
core.workflow.nodes.datasource.datasource_node -> core.file.enums
|
|
||||||
core.workflow.nodes.document_extractor.node -> core.file
|
|
||||||
core.workflow.nodes.http_request.executor -> core.file.enums
|
|
||||||
core.workflow.nodes.http_request.node -> core.file
|
|
||||||
core.workflow.nodes.http_request.node -> core.file.file_manager
|
|
||||||
core.workflow.nodes.knowledge_retrieval.knowledge_retrieval_node -> core.file.models
|
|
||||||
core.workflow.nodes.list_operator.node -> core.file
|
|
||||||
core.workflow.nodes.llm.file_saver -> core.file
|
|
||||||
core.workflow.nodes.llm.llm_utils -> core.variables.segments
|
core.workflow.nodes.llm.llm_utils -> core.variables.segments
|
||||||
core.workflow.nodes.llm.node -> core.file
|
|
||||||
core.workflow.nodes.llm.node -> core.file.file_manager
|
|
||||||
core.workflow.nodes.llm.node -> core.file.models
|
|
||||||
core.workflow.nodes.loop.entities -> core.variables.types
|
core.workflow.nodes.loop.entities -> core.variables.types
|
||||||
core.workflow.nodes.parameter_extractor.parameter_extractor_node -> core.file
|
|
||||||
core.workflow.nodes.protocols -> core.file
|
|
||||||
core.workflow.nodes.question_classifier.question_classifier_node -> core.file.models
|
|
||||||
core.workflow.nodes.tool.tool_node -> core.file
|
|
||||||
core.workflow.nodes.tool.tool_node -> core.tools.utils.message_transformer
|
core.workflow.nodes.tool.tool_node -> core.tools.utils.message_transformer
|
||||||
core.workflow.nodes.tool.tool_node -> models
|
core.workflow.nodes.tool.tool_node -> models
|
||||||
core.workflow.nodes.trigger_webhook.node -> core.file
|
|
||||||
core.workflow.runtime.variable_pool -> core.file
|
|
||||||
core.workflow.runtime.variable_pool -> core.file.file_manager
|
|
||||||
core.workflow.system_variable -> core.file.models
|
|
||||||
core.workflow.utils.condition.processor -> core.file
|
|
||||||
core.workflow.utils.condition.processor -> core.file.file_manager
|
|
||||||
core.workflow.workflow_entry -> core.file.models
|
|
||||||
core.workflow.workflow_type_encoder -> core.file.models
|
|
||||||
core.workflow.nodes.agent.agent_node -> models.model
|
core.workflow.nodes.agent.agent_node -> models.model
|
||||||
core.workflow.nodes.code.code_node -> core.helper.code_executor.code_node_provider
|
core.workflow.nodes.code.code_node -> core.helper.code_executor.code_node_provider
|
||||||
core.workflow.nodes.code.code_node -> core.helper.code_executor.javascript.javascript_code_provider
|
core.workflow.nodes.code.code_node -> core.helper.code_executor.javascript.javascript_code_provider
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from typing import Any, TypeAlias
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, computed_field
|
from pydantic import BaseModel, ConfigDict, computed_field
|
||||||
|
|
||||||
from core.file import helpers as file_helpers
|
from core.workflow.file import helpers as file_helpers
|
||||||
from models.model import IconType
|
from models.model import IconType
|
||||||
|
|
||||||
JSONValue: TypeAlias = str | int | float | bool | None | dict[str, Any] | list[Any]
|
JSONValue: TypeAlias = str | int | float | bool | None | dict[str, Any] | list[Any]
|
||||||
|
|||||||
@ -23,10 +23,10 @@ from controllers.console.wraps import (
|
|||||||
is_admin_or_owner_required,
|
is_admin_or_owner_required,
|
||||||
setup_required,
|
setup_required,
|
||||||
)
|
)
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.ops.ops_trace_manager import OpsTraceManager
|
from core.ops.ops_trace_manager import OpsTraceManager
|
||||||
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
||||||
from core.workflow.enums import NodeType, WorkflowExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowExecutionStatus
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from libs.login import current_account_with_tenant, login_required
|
from libs.login import current_account_with_tenant, login_required
|
||||||
from models import App, DatasetPermissionEnum, Workflow
|
from models import App, DatasetPermissionEnum, Workflow
|
||||||
|
|||||||
@ -20,7 +20,6 @@ from core.app.app_config.features.file_upload.manager import FileUploadConfigMan
|
|||||||
from core.app.apps.base_app_queue_manager import AppQueueManager
|
from core.app.apps.base_app_queue_manager import AppQueueManager
|
||||||
from core.app.apps.workflow.app_generator import SKIP_PREPARE_USER_INPUTS_KEY
|
from core.app.apps.workflow.app_generator import SKIP_PREPARE_USER_INPUTS_KEY
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.file.models import File
|
|
||||||
from core.helper.trace_id_helper import get_external_trace_id
|
from core.helper.trace_id_helper import get_external_trace_id
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||||
from core.plugin.impl.exc import PluginInvokeError
|
from core.plugin.impl.exc import PluginInvokeError
|
||||||
@ -31,6 +30,7 @@ from core.trigger.debug.event_selectors import (
|
|||||||
select_trigger_debug_events,
|
select_trigger_debug_events,
|
||||||
)
|
)
|
||||||
from core.workflow.enums import NodeType
|
from core.workflow.enums import NodeType
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.graph_engine.manager import GraphEngineManager
|
from core.workflow.graph_engine.manager import GraphEngineManager
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories import file_factory, variable_factory
|
from factories import file_factory, variable_factory
|
||||||
|
|||||||
@ -15,11 +15,11 @@ from controllers.console.app.error import (
|
|||||||
from controllers.console.app.wraps import get_app_model
|
from controllers.console.app.wraps import get_app_model
|
||||||
from controllers.console.wraps import account_initialization_required, edit_permission_required, setup_required
|
from controllers.console.wraps import account_initialization_required, edit_permission_required, setup_required
|
||||||
from controllers.web.error import InvalidArgumentError, NotFoundError
|
from controllers.web.error import InvalidArgumentError, NotFoundError
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.variables.segment_group import SegmentGroup
|
from core.variables.segment_group import SegmentGroup
|
||||||
from core.variables.segments import ArrayFileSegment, FileSegment, Segment
|
from core.variables.segments import ArrayFileSegment, FileSegment, Segment
|
||||||
from core.variables.types import SegmentType
|
from core.variables.types import SegmentType
|
||||||
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, SYSTEM_VARIABLE_NODE_ID
|
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, SYSTEM_VARIABLE_NODE_ID
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories.file_factory import build_from_mapping, build_from_mappings
|
from factories.file_factory import build_from_mapping, build_from_mappings
|
||||||
from factories.variable_factory import build_segment_with_type
|
from factories.variable_factory import build_segment_with_type
|
||||||
|
|||||||
@ -12,8 +12,8 @@ from controllers.common.errors import (
|
|||||||
UnsupportedFileTypeError,
|
UnsupportedFileTypeError,
|
||||||
)
|
)
|
||||||
from controllers.console import console_ns
|
from controllers.console import console_ns
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from fields.file_fields import FileWithSignedUrl, RemoteFileInfo
|
from fields.file_fields import FileWithSignedUrl, RemoteFileInfo
|
||||||
from libs.login import current_account_with_tenant, login_required
|
from libs.login import current_account_with_tenant, login_required
|
||||||
|
|||||||
@ -7,8 +7,8 @@ from pydantic import BaseModel, Field
|
|||||||
from werkzeug.exceptions import Forbidden
|
from werkzeug.exceptions import Forbidden
|
||||||
|
|
||||||
import services
|
import services
|
||||||
from core.file.helpers import verify_plugin_file_signature
|
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
|
from core.workflow.file.helpers import verify_plugin_file_signature
|
||||||
from fields.file_fields import FileResponse
|
from fields.file_fields import FileResponse
|
||||||
|
|
||||||
from ..common.errors import (
|
from ..common.errors import (
|
||||||
|
|||||||
@ -4,7 +4,6 @@ from controllers.console.wraps import setup_required
|
|||||||
from controllers.inner_api import inner_api_ns
|
from controllers.inner_api import inner_api_ns
|
||||||
from controllers.inner_api.plugin.wraps import get_user_tenant, plugin_data
|
from controllers.inner_api.plugin.wraps import get_user_tenant, plugin_data
|
||||||
from controllers.inner_api.wraps import plugin_inner_api_only
|
from controllers.inner_api.wraps import plugin_inner_api_only
|
||||||
from core.file.helpers import get_signed_file_url_for_plugin
|
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||||
from core.plugin.backwards_invocation.app import PluginAppBackwardsInvocation
|
from core.plugin.backwards_invocation.app import PluginAppBackwardsInvocation
|
||||||
from core.plugin.backwards_invocation.base import BaseBackwardsInvocationResponse
|
from core.plugin.backwards_invocation.base import BaseBackwardsInvocationResponse
|
||||||
@ -30,6 +29,7 @@ from core.plugin.entities.request import (
|
|||||||
RequestRequestUploadFile,
|
RequestRequestUploadFile,
|
||||||
)
|
)
|
||||||
from core.tools.entities.tool_entities import ToolProviderType
|
from core.tools.entities.tool_entities import ToolProviderType
|
||||||
|
from core.workflow.file.helpers import get_signed_file_url_for_plugin
|
||||||
from libs.helper import length_prefixed_response
|
from libs.helper import length_prefixed_response
|
||||||
from models import Account, Tenant
|
from models import Account, Tenant
|
||||||
from models.model import EndUser
|
from models.model import EndUser
|
||||||
|
|||||||
@ -10,8 +10,8 @@ from controllers.common.errors import (
|
|||||||
RemoteFileUploadError,
|
RemoteFileUploadError,
|
||||||
UnsupportedFileTypeError,
|
UnsupportedFileTypeError,
|
||||||
)
|
)
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from fields.file_fields import FileWithSignedUrl, RemoteFileInfo
|
from fields.file_fields import FileWithSignedUrl, RemoteFileInfo
|
||||||
from services.file_service import FileService
|
from services.file_service import FileService
|
||||||
|
|||||||
@ -17,7 +17,6 @@ from core.app.entities.app_invoke_entities import (
|
|||||||
)
|
)
|
||||||
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
||||||
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
||||||
from core.file import file_manager
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
@ -40,6 +39,7 @@ from core.tools.entities.tool_entities import (
|
|||||||
)
|
)
|
||||||
from core.tools.tool_manager import ToolManager
|
from core.tools.tool_manager import ToolManager
|
||||||
from core.tools.utils.dataset_retriever_tool import DatasetRetrieverTool
|
from core.tools.utils.dataset_retriever_tool import DatasetRetrieverTool
|
||||||
|
from core.workflow.file import file_manager
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories import file_factory
|
from factories import file_factory
|
||||||
from models.enums import CreatorUserRole
|
from models.enums import CreatorUserRole
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from core.agent.cot_agent_runner import CotAgentRunner
|
from core.agent.cot_agent_runner import CotAgentRunner
|
||||||
from core.file import file_manager
|
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
AssistantPromptMessage,
|
AssistantPromptMessage,
|
||||||
PromptMessage,
|
PromptMessage,
|
||||||
@ -11,6 +10,7 @@ from core.model_runtime.entities import (
|
|||||||
)
|
)
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent, PromptMessageContentUnionTypes
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent, PromptMessageContentUnionTypes
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||||
|
from core.workflow.file import file_manager
|
||||||
|
|
||||||
|
|
||||||
class CotChatAgentRunner(CotAgentRunner):
|
class CotChatAgentRunner(CotAgentRunner):
|
||||||
|
|||||||
@ -7,7 +7,6 @@ from typing import Any, Union
|
|||||||
from core.agent.base_agent_runner import BaseAgentRunner
|
from core.agent.base_agent_runner import BaseAgentRunner
|
||||||
from core.app.apps.base_app_queue_manager import PublishFrom
|
from core.app.apps.base_app_queue_manager import PublishFrom
|
||||||
from core.app.entities.queue_entities import QueueAgentThoughtEvent, QueueMessageEndEvent, QueueMessageFileEvent
|
from core.app.entities.queue_entities import QueueAgentThoughtEvent, QueueMessageEndEvent, QueueMessageFileEvent
|
||||||
from core.file import file_manager
|
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
AssistantPromptMessage,
|
AssistantPromptMessage,
|
||||||
LLMResult,
|
LLMResult,
|
||||||
@ -25,6 +24,7 @@ from core.model_runtime.entities.message_entities import ImagePromptMessageConte
|
|||||||
from core.prompt.agent_history_prompt_transform import AgentHistoryPromptTransform
|
from core.prompt.agent_history_prompt_transform import AgentHistoryPromptTransform
|
||||||
from core.tools.entities.tool_entities import ToolInvokeMeta
|
from core.tools.entities.tool_entities import ToolInvokeMeta
|
||||||
from core.tools.tool_engine import ToolEngine
|
from core.tools.tool_engine import ToolEngine
|
||||||
|
from core.workflow.file import file_manager
|
||||||
from core.workflow.nodes.agent.exc import AgentMaxIterationError
|
from core.workflow.nodes.agent.exc import AgentMaxIterationError
|
||||||
from models.model import Message
|
from models.model import Message
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,9 @@ from typing import Any, Literal
|
|||||||
from jsonschema import Draft7Validator, SchemaError
|
from jsonschema import Draft7Validator, SchemaError
|
||||||
from pydantic import BaseModel, Field, field_validator
|
from pydantic import BaseModel, Field, field_validator
|
||||||
|
|
||||||
from core.file import FileTransferMethod, FileType, FileUploadConfig
|
|
||||||
from core.model_runtime.entities.llm_entities import LLMMode
|
from core.model_runtime.entities.llm_entities import LLMMode
|
||||||
from core.model_runtime.entities.message_entities import PromptMessageRole
|
from core.model_runtime.entities.message_entities import PromptMessageRole
|
||||||
|
from core.workflow.file import FileTransferMethod, FileType, FileUploadConfig
|
||||||
from models.model import AppMode
|
from models.model import AppMode
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ from collections.abc import Mapping
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from constants import DEFAULT_FILE_NUMBER_LIMITS
|
from constants import DEFAULT_FILE_NUMBER_LIMITS
|
||||||
from core.file import FileUploadConfig
|
from core.workflow.file import FileUploadConfig
|
||||||
|
|
||||||
|
|
||||||
class FileUploadConfigManager:
|
class FileUploadConfigManager:
|
||||||
|
|||||||
@ -5,8 +5,8 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from core.app.app_config.entities import VariableEntityType
|
from core.app.app_config.entities import VariableEntityType
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.file import File, FileUploadConfig
|
|
||||||
from core.workflow.enums import NodeType
|
from core.workflow.enums import NodeType
|
||||||
|
from core.workflow.file import File, FileUploadConfig
|
||||||
from core.workflow.repositories.draft_variable_repository import (
|
from core.workflow.repositories.draft_variable_repository import (
|
||||||
DraftVariableSaver,
|
DraftVariableSaver,
|
||||||
DraftVariableSaverFactory,
|
DraftVariableSaverFactory,
|
||||||
|
|||||||
@ -22,7 +22,6 @@ from core.app.entities.queue_entities import (
|
|||||||
from core.app.features.annotation_reply.annotation_reply import AnnotationReplyFeature
|
from core.app.features.annotation_reply.annotation_reply import AnnotationReplyFeature
|
||||||
from core.app.features.hosting_moderation.hosting_moderation import HostingModerationFeature
|
from core.app.features.hosting_moderation.hosting_moderation import HostingModerationFeature
|
||||||
from core.external_data_tool.external_data_fetch import ExternalDataFetch
|
from core.external_data_tool.external_data_fetch import ExternalDataFetch
|
||||||
from core.file.enums import FileTransferMethod, FileType
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
|
||||||
@ -39,12 +38,13 @@ from core.prompt.advanced_prompt_transform import AdvancedPromptTransform
|
|||||||
from core.prompt.entities.advanced_prompt_entities import ChatModelMessage, CompletionModelPromptTemplate, MemoryConfig
|
from core.prompt.entities.advanced_prompt_entities import ChatModelMessage, CompletionModelPromptTemplate, MemoryConfig
|
||||||
from core.prompt.simple_prompt_transform import ModelMode, SimplePromptTransform
|
from core.prompt.simple_prompt_transform import ModelMode, SimplePromptTransform
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
|
from core.workflow.file.enums import FileTransferMethod, FileType
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models.enums import CreatorUserRole
|
from models.enums import CreatorUserRole
|
||||||
from models.model import App, AppMode, Message, MessageAnnotation, MessageFile
|
from models.model import App, AppMode, Message, MessageAnnotation, MessageFile
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@ -11,12 +11,12 @@ from core.app.entities.app_invoke_entities import (
|
|||||||
)
|
)
|
||||||
from core.app.entities.queue_entities import QueueAnnotationReplyEvent
|
from core.app.entities.queue_entities import QueueAnnotationReplyEvent
|
||||||
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
||||||
from core.file import File
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
||||||
from core.moderation.base import ModerationError
|
from core.moderation.base import ModerationError
|
||||||
from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
||||||
|
from core.workflow.file import File
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models.model import App, Conversation, Message
|
from models.model import App, Conversation, Message
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,6 @@ from core.app.entities.task_entities import (
|
|||||||
WorkflowPauseStreamResponse,
|
WorkflowPauseStreamResponse,
|
||||||
WorkflowStartStreamResponse,
|
WorkflowStartStreamResponse,
|
||||||
)
|
)
|
||||||
from core.file import FILE_MODEL_IDENTITY, File
|
|
||||||
from core.plugin.impl.datasource import PluginDatasourceManager
|
from core.plugin.impl.datasource import PluginDatasourceManager
|
||||||
from core.tools.entities.tool_entities import ToolProviderType
|
from core.tools.entities.tool_entities import ToolProviderType
|
||||||
from core.tools.tool_manager import ToolManager
|
from core.tools.tool_manager import ToolManager
|
||||||
@ -60,6 +59,7 @@ from core.workflow.enums import (
|
|||||||
WorkflowNodeExecutionMetadataKey,
|
WorkflowNodeExecutionMetadataKey,
|
||||||
WorkflowNodeExecutionStatus,
|
WorkflowNodeExecutionStatus,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import FILE_MODEL_IDENTITY, File
|
||||||
from core.workflow.runtime import GraphRuntimeState
|
from core.workflow.runtime import GraphRuntimeState
|
||||||
from core.workflow.system_variable import SystemVariable
|
from core.workflow.system_variable import SystemVariable
|
||||||
from core.workflow.workflow_entry import WorkflowEntry
|
from core.workflow.workflow_entry import WorkflowEntry
|
||||||
|
|||||||
@ -10,11 +10,11 @@ from core.app.entities.app_invoke_entities import (
|
|||||||
CompletionAppGenerateEntity,
|
CompletionAppGenerateEntity,
|
||||||
)
|
)
|
||||||
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCallbackHandler
|
||||||
from core.file import File
|
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
||||||
from core.moderation.base import ModerationError
|
from core.moderation.base import ModerationError
|
||||||
from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
||||||
|
from core.workflow.file import File
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models.model import App, Message
|
from models.model import App, Message
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,8 @@ from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validat
|
|||||||
from constants import UUID_NIL
|
from constants import UUID_NIL
|
||||||
from core.app.app_config.entities import EasyUIBasedAppConfig, WorkflowUIBasedAppConfig
|
from core.app.app_config.entities import EasyUIBasedAppConfig, WorkflowUIBasedAppConfig
|
||||||
from core.entities.provider_configuration import ProviderModelBundle
|
from core.entities.provider_configuration import ProviderModelBundle
|
||||||
from core.file import File, FileUploadConfig
|
|
||||||
from core.model_runtime.entities.model_entities import AIModelEntity
|
from core.model_runtime.entities.model_entities import AIModelEntity
|
||||||
|
from core.workflow.file import File, FileUploadConfig
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.ops.ops_trace_manager import TraceQueueManager
|
from core.ops.ops_trace_manager import TraceQueueManager
|
||||||
|
|||||||
@ -45,8 +45,6 @@ from core.app.entities.task_entities import (
|
|||||||
from core.app.task_pipeline.based_generate_task_pipeline import BasedGenerateTaskPipeline
|
from core.app.task_pipeline.based_generate_task_pipeline import BasedGenerateTaskPipeline
|
||||||
from core.app.task_pipeline.message_cycle_manager import MessageCycleManager
|
from core.app.task_pipeline.message_cycle_manager import MessageCycleManager
|
||||||
from core.base.tts import AppGeneratorTTSPublisher, AudioTrunk
|
from core.base.tts import AppGeneratorTTSPublisher, AudioTrunk
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.file.enums import FileTransferMethod
|
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage
|
||||||
from core.model_runtime.entities.message_entities import (
|
from core.model_runtime.entities.message_entities import (
|
||||||
@ -59,6 +57,8 @@ from core.ops.ops_trace_manager import TraceQueueManager, TraceTask
|
|||||||
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
||||||
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
||||||
from core.tools.signature import sign_tool_file
|
from core.tools.signature import sign_tool_file
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
|
from core.workflow.file.enums import FileTransferMethod
|
||||||
from events.message_event import message_was_created
|
from events.message_event import message_was_created
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from libs.datetime_utils import naive_utc_now
|
from libs.datetime_utils import naive_utc_now
|
||||||
|
|||||||
47
api/core/app/workflow/file_runtime.py
Normal file
47
api/core/app/workflow/file_runtime.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
|
|
||||||
|
from configs import dify_config
|
||||||
|
from core.helper.ssrf_proxy import ssrf_proxy
|
||||||
|
from core.tools.signature import sign_tool_file
|
||||||
|
from core.workflow.file.protocols import HttpResponseProtocol, WorkflowFileRuntimeProtocol
|
||||||
|
from core.workflow.file.runtime import set_workflow_file_runtime
|
||||||
|
from extensions.ext_storage import storage
|
||||||
|
|
||||||
|
|
||||||
|
class DifyWorkflowFileRuntime(WorkflowFileRuntimeProtocol):
|
||||||
|
"""Production runtime wiring for ``core.workflow.file``."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_url(self) -> str:
|
||||||
|
return dify_config.FILES_URL
|
||||||
|
|
||||||
|
@property
|
||||||
|
def internal_files_url(self) -> str | None:
|
||||||
|
return dify_config.INTERNAL_FILES_URL
|
||||||
|
|
||||||
|
@property
|
||||||
|
def secret_key(self) -> str:
|
||||||
|
return dify_config.SECRET_KEY
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_access_timeout(self) -> int:
|
||||||
|
return dify_config.FILES_ACCESS_TIMEOUT
|
||||||
|
|
||||||
|
@property
|
||||||
|
def multimodal_send_format(self) -> str:
|
||||||
|
return dify_config.MULTIMODAL_SEND_FORMAT
|
||||||
|
|
||||||
|
def http_get(self, url: str, *, follow_redirects: bool = True) -> HttpResponseProtocol:
|
||||||
|
return ssrf_proxy.get(url, follow_redirects=follow_redirects)
|
||||||
|
|
||||||
|
def storage_load(self, path: str, *, stream: bool = False) -> bytes | Generator:
|
||||||
|
return storage.load(path, stream=stream)
|
||||||
|
|
||||||
|
def sign_tool_file(self, *, tool_file_id: str, extension: str, for_external: bool = True) -> str:
|
||||||
|
return sign_tool_file(tool_file_id=tool_file_id, extension=extension, for_external=for_external)
|
||||||
|
|
||||||
|
|
||||||
|
def bind_dify_workflow_file_runtime() -> None:
|
||||||
|
set_workflow_file_runtime(DifyWorkflowFileRuntime())
|
||||||
@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, final
|
|||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file.file_manager import file_manager
|
|
||||||
from core.helper.code_executor.code_executor import CodeExecutor
|
from core.helper.code_executor.code_executor import CodeExecutor
|
||||||
from core.helper.code_executor.code_node_provider import CodeNodeProvider
|
from core.helper.code_executor.code_node_provider import CodeNodeProvider
|
||||||
from core.helper.ssrf_proxy import ssrf_proxy
|
from core.helper.ssrf_proxy import ssrf_proxy
|
||||||
@ -12,6 +11,7 @@ from core.rag.retrieval.dataset_retrieval import DatasetRetrieval
|
|||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
from core.workflow.entities.graph_config import NodeConfigDict
|
from core.workflow.entities.graph_config import NodeConfigDict
|
||||||
from core.workflow.enums import NodeType
|
from core.workflow.enums import NodeType
|
||||||
|
from core.workflow.file.file_manager import file_manager
|
||||||
from core.workflow.graph.graph import NodeFactory
|
from core.workflow.graph.graph import NodeFactory
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
from core.workflow.nodes.code.code_node import CodeNode
|
from core.workflow.nodes.code.code_node import CodeNode
|
||||||
|
|||||||
@ -213,6 +213,6 @@ class DatasourceFileManager:
|
|||||||
|
|
||||||
|
|
||||||
# init tool_file_parser
|
# init tool_file_parser
|
||||||
# from core.file.datasource_file_parser import datasource_file_manager
|
# from core.workflow.file.datasource_file_parser import datasource_file_manager
|
||||||
#
|
#
|
||||||
# datasource_file_manager["manager"] = DatasourceFileManager
|
# datasource_file_manager["manager"] = DatasourceFileManager
|
||||||
|
|||||||
@ -3,8 +3,8 @@ from collections.abc import Generator
|
|||||||
from mimetypes import guess_extension, guess_type
|
from mimetypes import guess_extension, guess_type
|
||||||
|
|
||||||
from core.datasource.entities.datasource_entities import DatasourceMessage
|
from core.datasource.entities.datasource_entities import DatasourceMessage
|
||||||
from core.file import File, FileTransferMethod, FileType
|
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from models.tools import ToolFile
|
from models.tools import ToolFile
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@ -10,12 +10,12 @@ from pydantic import BaseModel
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.entities.provider_entities import BasicProviderConfig
|
from core.entities.provider_entities import BasicProviderConfig
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.helper import encrypter
|
from core.helper import encrypter
|
||||||
from core.helper.provider_cache import NoOpProviderCredentialCache
|
from core.helper.provider_cache import NoOpProviderCredentialCache
|
||||||
from core.mcp.types import OAuthClientInformation, OAuthClientMetadata, OAuthTokens
|
from core.mcp.types import OAuthClientInformation, OAuthClientMetadata, OAuthTokens
|
||||||
from core.tools.entities.common_entities import I18nObject
|
from core.tools.entities.common_entities import I18nObject
|
||||||
from core.tools.entities.tool_entities import ToolProviderType
|
from core.tools.entities.tool_entities import ToolProviderType
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from models.tools import MCPToolProvider
|
from models.tools import MCPToolProvider
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
from collections.abc import Callable
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
|
||||||
|
|
||||||
_tool_file_manager_factory: Callable[[], "ToolFileManager"] | None = None
|
|
||||||
|
|
||||||
|
|
||||||
def set_tool_file_manager_factory(factory: Callable[[], "ToolFileManager"]):
|
|
||||||
global _tool_file_manager_factory
|
|
||||||
_tool_file_manager_factory = factory
|
|
||||||
@ -4,7 +4,6 @@ from sqlalchemy import select
|
|||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
|
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
|
||||||
from core.file import file_manager
|
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
AssistantPromptMessage,
|
AssistantPromptMessage,
|
||||||
@ -16,6 +15,7 @@ from core.model_runtime.entities import (
|
|||||||
)
|
)
|
||||||
from core.model_runtime.entities.message_entities import PromptMessageContentUnionTypes
|
from core.model_runtime.entities.message_entities import PromptMessageContentUnionTypes
|
||||||
from core.prompt.utils.extract_thread_messages import extract_thread_messages
|
from core.prompt.utils.extract_thread_messages import extract_thread_messages
|
||||||
|
from core.workflow.file import file_manager
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories import file_factory
|
from factories import file_factory
|
||||||
from models.model import AppMode, Conversation, Message, MessageFile
|
from models.model import AppMode, Conversation, Message, MessageFile
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from core.file.models import File
|
|
||||||
from core.tools.entities.tool_entities import ToolSelector
|
from core.tools.entities.tool_entities import ToolSelector
|
||||||
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
|
|
||||||
def convert_parameters_to_plugin_format(parameters: dict[str, Any]) -> dict[str, Any]:
|
def convert_parameters_to_plugin_format(parameters: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
|||||||
@ -2,8 +2,6 @@ from collections.abc import Mapping, Sequence
|
|||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
||||||
from core.file import file_manager
|
|
||||||
from core.file.models import File
|
|
||||||
from core.helper.code_executor.jinja2.jinja2_formatter import Jinja2Formatter
|
from core.helper.code_executor.jinja2.jinja2_formatter import Jinja2Formatter
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
@ -18,6 +16,8 @@ from core.model_runtime.entities.message_entities import ImagePromptMessageConte
|
|||||||
from core.prompt.entities.advanced_prompt_entities import ChatModelMessage, CompletionModelPromptTemplate, MemoryConfig
|
from core.prompt.entities.advanced_prompt_entities import ChatModelMessage, CompletionModelPromptTemplate, MemoryConfig
|
||||||
from core.prompt.prompt_transform import PromptTransform
|
from core.prompt.prompt_transform import PromptTransform
|
||||||
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
||||||
|
from core.workflow.file import file_manager
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.runtime import VariablePool
|
from core.workflow.runtime import VariablePool
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ from typing import TYPE_CHECKING, Any, cast
|
|||||||
|
|
||||||
from core.app.app_config.entities import PromptTemplateEntity
|
from core.app.app_config.entities import PromptTemplateEntity
|
||||||
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
||||||
from core.file import file_manager
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_runtime.entities.message_entities import (
|
from core.model_runtime.entities.message_entities import (
|
||||||
ImagePromptMessageContent,
|
ImagePromptMessageContent,
|
||||||
@ -19,10 +18,11 @@ from core.model_runtime.entities.message_entities import (
|
|||||||
from core.prompt.entities.advanced_prompt_entities import MemoryConfig
|
from core.prompt.entities.advanced_prompt_entities import MemoryConfig
|
||||||
from core.prompt.prompt_transform import PromptTransform
|
from core.prompt.prompt_transform import PromptTransform
|
||||||
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
||||||
|
from core.workflow.file import file_manager
|
||||||
from models.model import AppMode
|
from models.model import AppMode
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
|
|
||||||
class ModelMode(StrEnum):
|
class ModelMode(StrEnum):
|
||||||
|
|||||||
@ -9,7 +9,6 @@ from typing import Any, cast
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
from core.entities.knowledge_entities import PreviewDetail
|
from core.entities.knowledge_entities import PreviewDetail
|
||||||
from core.file import File, FileTransferMethod, FileType, file_manager
|
|
||||||
from core.llm_generator.prompts import DEFAULT_GENERATOR_SUMMARY_PROMPT
|
from core.llm_generator.prompts import DEFAULT_GENERATOR_SUMMARY_PROMPT
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities.llm_entities import LLMResult, LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMResult, LLMUsage
|
||||||
@ -35,6 +34,7 @@ from core.rag.index_processor.index_processor_base import BaseIndexProcessor
|
|||||||
from core.rag.models.document import AttachmentDocument, Document, MultimodalGeneralStructureChunk
|
from core.rag.models.document import AttachmentDocument, Document, MultimodalGeneralStructureChunk
|
||||||
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
||||||
from core.tools.utils.text_processing_utils import remove_leading_symbols
|
from core.tools.utils.text_processing_utils import remove_leading_symbols
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType, file_manager
|
||||||
from core.workflow.nodes.llm import llm_utils
|
from core.workflow.nodes.llm import llm_utils
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories.file_factory import build_from_mapping
|
from factories.file_factory import build_from_mapping
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from typing import Any
|
|||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
|
|
||||||
|
|
||||||
class ChildDocument(BaseModel):
|
class ChildDocument(BaseModel):
|
||||||
|
|||||||
@ -23,7 +23,6 @@ from core.callback_handler.index_tool_callback_handler import DatasetIndexToolCa
|
|||||||
from core.db.session_factory import session_factory
|
from core.db.session_factory import session_factory
|
||||||
from core.entities.agent_entities import PlanningStrategy
|
from core.entities.agent_entities import PlanningStrategy
|
||||||
from core.entities.model_entities import ModelStatus
|
from core.entities.model_entities import ModelStatus
|
||||||
from core.file import File, FileTransferMethod, FileType
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance, ModelManager
|
from core.model_manager import ModelInstance, ModelManager
|
||||||
from core.model_runtime.entities.llm_entities import LLMResult, LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMResult, LLMUsage
|
||||||
@ -61,6 +60,7 @@ from core.rag.retrieval.template_prompts import (
|
|||||||
)
|
)
|
||||||
from core.tools.signature import sign_upload_file
|
from core.tools.signature import sign_upload_file
|
||||||
from core.tools.utils.dataset_retriever.dataset_retriever_base_tool import DatasetRetrieverBaseTool
|
from core.tools.utils.dataset_retriever.dataset_retriever_base_tool import DatasetRetrieverBaseTool
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from core.workflow.nodes.knowledge_retrieval import exc
|
from core.workflow.nodes.knowledge_retrieval import exc
|
||||||
from core.workflow.repositories.rag_retrieval_protocol import (
|
from core.workflow.repositories.rag_retrieval_protocol import (
|
||||||
KnowledgeRetrievalRequest,
|
KnowledgeRetrievalRequest,
|
||||||
|
|||||||
@ -2,14 +2,14 @@ import io
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from core.file.enums import FileType
|
|
||||||
from core.file.file_manager import download
|
|
||||||
from core.model_manager import ModelManager
|
from core.model_manager import ModelManager
|
||||||
from core.model_runtime.entities.model_entities import ModelType
|
from core.model_runtime.entities.model_entities import ModelType
|
||||||
from core.plugin.entities.parameters import PluginParameterOption
|
from core.plugin.entities.parameters import PluginParameterOption
|
||||||
from core.tools.builtin_tool.tool import BuiltinTool
|
from core.tools.builtin_tool.tool import BuiltinTool
|
||||||
from core.tools.entities.common_entities import I18nObject
|
from core.tools.entities.common_entities import I18nObject
|
||||||
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
||||||
|
from core.workflow.file.enums import FileType
|
||||||
|
from core.workflow.file.file_manager import download
|
||||||
from services.model_provider_service import ModelProviderService
|
from services.model_provider_service import ModelProviderService
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,13 @@ from urllib.parse import urlencode
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from core.file.file_manager import download
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
from core.tools.__base.tool import Tool
|
from core.tools.__base.tool import Tool
|
||||||
from core.tools.__base.tool_runtime import ToolRuntime
|
from core.tools.__base.tool_runtime import ToolRuntime
|
||||||
from core.tools.entities.tool_bundle import ApiToolBundle
|
from core.tools.entities.tool_bundle import ApiToolBundle
|
||||||
from core.tools.entities.tool_entities import ToolEntity, ToolInvokeMessage, ToolProviderType
|
from core.tools.entities.tool_entities import ToolEntity, ToolInvokeMessage, ToolProviderType
|
||||||
from core.tools.errors import ToolInvokeError, ToolParameterValidationError, ToolProviderCredentialValidationError
|
from core.tools.errors import ToolInvokeError, ToolParameterValidationError, ToolProviderCredentialValidationError
|
||||||
|
from core.workflow.file.file_manager import download
|
||||||
|
|
||||||
API_TOOL_DEFAULT_TIMEOUT = (
|
API_TOOL_DEFAULT_TIMEOUT = (
|
||||||
int(getenv("API_TOOL_DEFAULT_CONNECT_TIMEOUT", "10")),
|
int(getenv("API_TOOL_DEFAULT_CONNECT_TIMEOUT", "10")),
|
||||||
|
|||||||
@ -12,8 +12,6 @@ from yarl import URL
|
|||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
from core.callback_handler.agent_tool_callback_handler import DifyAgentCallbackHandler
|
||||||
from core.callback_handler.workflow_tool_callback_handler import DifyWorkflowCallbackHandler
|
from core.callback_handler.workflow_tool_callback_handler import DifyWorkflowCallbackHandler
|
||||||
from core.file import FileType
|
|
||||||
from core.file.models import FileTransferMethod
|
|
||||||
from core.ops.ops_trace_manager import TraceQueueManager
|
from core.ops.ops_trace_manager import TraceQueueManager
|
||||||
from core.tools.__base.tool import Tool
|
from core.tools.__base.tool import Tool
|
||||||
from core.tools.entities.tool_entities import (
|
from core.tools.entities.tool_entities import (
|
||||||
@ -33,6 +31,8 @@ from core.tools.errors import (
|
|||||||
)
|
)
|
||||||
from core.tools.utils.message_transformer import ToolFileMessageTransformer, safe_json_value
|
from core.tools.utils.message_transformer import ToolFileMessageTransformer, safe_json_value
|
||||||
from core.tools.workflow_as_tool.tool import WorkflowTool
|
from core.tools.workflow_as_tool.tool import WorkflowTool
|
||||||
|
from core.workflow.file import FileType
|
||||||
|
from core.workflow.file.models import FileTransferMethod
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models.enums import CreatorUserRole
|
from models.enums import CreatorUserRole
|
||||||
from models.model import Message, MessageFile
|
from models.model import Message, MessageFile
|
||||||
|
|||||||
@ -243,7 +243,7 @@ class ToolFileManager:
|
|||||||
|
|
||||||
|
|
||||||
# init tool_file_parser
|
# init tool_file_parser
|
||||||
from core.file.tool_file_parser import set_tool_file_manager_factory
|
from core.workflow.file.tool_file_parser import set_tool_file_manager_factory
|
||||||
|
|
||||||
|
|
||||||
def _factory() -> ToolFileManager:
|
def _factory() -> ToolFileManager:
|
||||||
|
|||||||
@ -8,9 +8,9 @@ from uuid import UUID
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.file import File, FileTransferMethod, FileType
|
|
||||||
from core.tools.entities.tool_entities import ToolInvokeMessage
|
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from libs.login import current_user
|
from libs.login import current_user
|
||||||
from models import Account
|
from models import Account
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ from typing import Any, cast
|
|||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
from core.db.session_factory import session_factory
|
from core.db.session_factory import session_factory
|
||||||
from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod
|
|
||||||
from core.model_runtime.entities.llm_entities import LLMUsage, LLMUsageMetadata
|
from core.model_runtime.entities.llm_entities import LLMUsage, LLMUsageMetadata
|
||||||
from core.tools.__base.tool import Tool
|
from core.tools.__base.tool import Tool
|
||||||
from core.tools.__base.tool_runtime import ToolRuntime
|
from core.tools.__base.tool_runtime import ToolRuntime
|
||||||
@ -19,6 +18,7 @@ from core.tools.entities.tool_entities import (
|
|||||||
ToolProviderType,
|
ToolProviderType,
|
||||||
)
|
)
|
||||||
from core.tools.errors import ToolInvokeError
|
from core.tools.errors import ToolInvokeError
|
||||||
|
from core.workflow.file import FILE_MODEL_IDENTITY, File, FileTransferMethod
|
||||||
from factories.file_factory import build_from_mapping
|
from factories.file_factory import build_from_mapping
|
||||||
from models import Account, Tenant
|
from models import Account, Tenant
|
||||||
from models.model import App, EndUser
|
from models.model import App, EndUser
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from typing import Annotated, Any, TypeAlias
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Discriminator, Tag, field_validator
|
from pydantic import BaseModel, ConfigDict, Discriminator, Tag, field_validator
|
||||||
|
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
|
|
||||||
from .types import SegmentType
|
from .types import SegmentType
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ from collections.abc import Mapping
|
|||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
|
||||||
from configs import dify_config
|
|
||||||
from core.helper import ssrf_proxy
|
|
||||||
from core.model_runtime.entities import (
|
from core.model_runtime.entities import (
|
||||||
AudioPromptMessageContent,
|
AudioPromptMessageContent,
|
||||||
DocumentPromptMessageContent,
|
DocumentPromptMessageContent,
|
||||||
@ -11,12 +11,11 @@ from core.model_runtime.entities import (
|
|||||||
VideoPromptMessageContent,
|
VideoPromptMessageContent,
|
||||||
)
|
)
|
||||||
from core.model_runtime.entities.message_entities import PromptMessageContentUnionTypes
|
from core.model_runtime.entities.message_entities import PromptMessageContentUnionTypes
|
||||||
from core.tools.signature import sign_tool_file
|
|
||||||
from extensions.ext_storage import storage
|
|
||||||
|
|
||||||
from . import helpers
|
from . import helpers
|
||||||
from .enums import FileAttribute
|
from .enums import FileAttribute
|
||||||
from .models import File, FileTransferMethod, FileType
|
from .models import File, FileTransferMethod, FileType
|
||||||
|
from .runtime import get_workflow_file_runtime
|
||||||
|
|
||||||
|
|
||||||
def get_attr(*, file: File, attr: FileAttribute):
|
def get_attr(*, file: File, attr: FileAttribute):
|
||||||
@ -45,26 +44,7 @@ def to_prompt_message_content(
|
|||||||
*,
|
*,
|
||||||
image_detail_config: ImagePromptMessageContent.DETAIL | None = None,
|
image_detail_config: ImagePromptMessageContent.DETAIL | None = None,
|
||||||
) -> PromptMessageContentUnionTypes:
|
) -> PromptMessageContentUnionTypes:
|
||||||
"""
|
"""Convert a file to prompt message content."""
|
||||||
Convert a file to prompt message content.
|
|
||||||
|
|
||||||
This function converts files to their appropriate prompt message content types.
|
|
||||||
For supported file types (IMAGE, AUDIO, VIDEO, DOCUMENT), it creates the
|
|
||||||
corresponding message content with proper encoding/URL.
|
|
||||||
|
|
||||||
For unsupported file types, instead of raising an error, it returns a
|
|
||||||
TextPromptMessageContent with a descriptive message about the file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
f: The file to convert
|
|
||||||
image_detail_config: Optional detail configuration for image files
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
PromptMessageContentUnionTypes: The appropriate message content type
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If file extension or mime_type is missing
|
|
||||||
"""
|
|
||||||
if f.extension is None:
|
if f.extension is None:
|
||||||
raise ValueError("Missing file extension")
|
raise ValueError("Missing file extension")
|
||||||
if f.mime_type is None:
|
if f.mime_type is None:
|
||||||
@ -77,15 +57,13 @@ def to_prompt_message_content(
|
|||||||
FileType.DOCUMENT: DocumentPromptMessageContent,
|
FileType.DOCUMENT: DocumentPromptMessageContent,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if file type is supported
|
|
||||||
if f.type not in prompt_class_map:
|
if f.type not in prompt_class_map:
|
||||||
# For unsupported file types, return a text description
|
|
||||||
return TextPromptMessageContent(data=f"[Unsupported file type: {f.filename} ({f.type.value})]")
|
return TextPromptMessageContent(data=f"[Unsupported file type: {f.filename} ({f.type.value})]")
|
||||||
|
|
||||||
# Process supported file types
|
send_format = get_workflow_file_runtime().multimodal_send_format
|
||||||
params = {
|
params = {
|
||||||
"base64_data": _get_encoded_string(f) if dify_config.MULTIMODAL_SEND_FORMAT == "base64" else "",
|
"base64_data": _get_encoded_string(f) if send_format == "base64" else "",
|
||||||
"url": _to_url(f) if dify_config.MULTIMODAL_SEND_FORMAT == "url" else "",
|
"url": _to_url(f) if send_format == "url" else "",
|
||||||
"format": f.extension.removeprefix("."),
|
"format": f.extension.removeprefix("."),
|
||||||
"mime_type": f.mime_type,
|
"mime_type": f.mime_type,
|
||||||
"filename": f.filename or "",
|
"filename": f.filename or "",
|
||||||
@ -96,7 +74,7 @@ def to_prompt_message_content(
|
|||||||
return prompt_class_map[f.type].model_validate(params)
|
return prompt_class_map[f.type].model_validate(params)
|
||||||
|
|
||||||
|
|
||||||
def download(f: File, /):
|
def download(f: File, /) -> bytes:
|
||||||
if f.transfer_method in (
|
if f.transfer_method in (
|
||||||
FileTransferMethod.TOOL_FILE,
|
FileTransferMethod.TOOL_FILE,
|
||||||
FileTransferMethod.LOCAL_FILE,
|
FileTransferMethod.LOCAL_FILE,
|
||||||
@ -106,39 +84,26 @@ def download(f: File, /):
|
|||||||
elif f.transfer_method == FileTransferMethod.REMOTE_URL:
|
elif f.transfer_method == FileTransferMethod.REMOTE_URL:
|
||||||
if f.remote_url is None:
|
if f.remote_url is None:
|
||||||
raise ValueError("Missing file remote_url")
|
raise ValueError("Missing file remote_url")
|
||||||
response = ssrf_proxy.get(f.remote_url, follow_redirects=True)
|
response = get_workflow_file_runtime().http_get(f.remote_url, follow_redirects=True)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.content
|
return response.content
|
||||||
raise ValueError(f"unsupported transfer method: {f.transfer_method}")
|
raise ValueError(f"unsupported transfer method: {f.transfer_method}")
|
||||||
|
|
||||||
|
|
||||||
def _download_file_content(path: str, /):
|
def _download_file_content(path: str, /) -> bytes:
|
||||||
"""
|
"""Download and return a file from storage as bytes."""
|
||||||
Download and return the contents of a file as bytes.
|
data = get_workflow_file_runtime().storage_load(path, stream=False)
|
||||||
|
|
||||||
This function loads the file from storage and ensures it's in bytes format.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
path (str): The path to the file in storage.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bytes: The contents of the file as a bytes object.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the loaded file is not a bytes object.
|
|
||||||
"""
|
|
||||||
data = storage.load(path, stream=False)
|
|
||||||
if not isinstance(data, bytes):
|
if not isinstance(data, bytes):
|
||||||
raise ValueError(f"file {path} is not a bytes object")
|
raise ValueError(f"file {path} is not a bytes object")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def _get_encoded_string(f: File, /):
|
def _get_encoded_string(f: File, /) -> str:
|
||||||
match f.transfer_method:
|
match f.transfer_method:
|
||||||
case FileTransferMethod.REMOTE_URL:
|
case FileTransferMethod.REMOTE_URL:
|
||||||
if f.remote_url is None:
|
if f.remote_url is None:
|
||||||
raise ValueError("Missing file remote_url")
|
raise ValueError("Missing file remote_url")
|
||||||
response = ssrf_proxy.get(f.remote_url, follow_redirects=True)
|
response = get_workflow_file_runtime().http_get(f.remote_url, follow_redirects=True)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
data = response.content
|
data = response.content
|
||||||
case FileTransferMethod.LOCAL_FILE:
|
case FileTransferMethod.LOCAL_FILE:
|
||||||
@ -148,8 +113,7 @@ def _get_encoded_string(f: File, /):
|
|||||||
case FileTransferMethod.DATASOURCE_FILE:
|
case FileTransferMethod.DATASOURCE_FILE:
|
||||||
data = _download_file_content(f.storage_key)
|
data = _download_file_content(f.storage_key)
|
||||||
|
|
||||||
encoded_string = base64.b64encode(data).decode("utf-8")
|
return base64.b64encode(data).decode("utf-8")
|
||||||
return encoded_string
|
|
||||||
|
|
||||||
|
|
||||||
def _to_url(f: File, /):
|
def _to_url(f: File, /):
|
||||||
@ -162,21 +126,15 @@ def _to_url(f: File, /):
|
|||||||
raise ValueError("Missing file related_id")
|
raise ValueError("Missing file related_id")
|
||||||
return f.remote_url or helpers.get_signed_file_url(upload_file_id=f.related_id)
|
return f.remote_url or helpers.get_signed_file_url(upload_file_id=f.related_id)
|
||||||
elif f.transfer_method == FileTransferMethod.TOOL_FILE:
|
elif f.transfer_method == FileTransferMethod.TOOL_FILE:
|
||||||
# add sign url
|
|
||||||
if f.related_id is None or f.extension is None:
|
if f.related_id is None or f.extension is None:
|
||||||
raise ValueError("Missing file related_id or extension")
|
raise ValueError("Missing file related_id or extension")
|
||||||
return sign_tool_file(tool_file_id=f.related_id, extension=f.extension)
|
return helpers.get_signed_tool_file_url(tool_file_id=f.related_id, extension=f.extension)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported transfer method: {f.transfer_method}")
|
raise ValueError(f"Unsupported transfer method: {f.transfer_method}")
|
||||||
|
|
||||||
|
|
||||||
class FileManager:
|
class FileManager:
|
||||||
"""
|
"""Adapter exposing file manager helpers behind FileManagerProtocol."""
|
||||||
Adapter exposing file manager helpers behind FileManagerProtocol.
|
|
||||||
|
|
||||||
This is intentionally a thin wrapper over the existing module-level functions so callers can inject it
|
|
||||||
where a protocol-typed file manager is expected.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def download(self, f: File, /) -> bytes:
|
def download(self, f: File, /) -> bytes:
|
||||||
return download(f)
|
return download(f)
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
@ -5,20 +7,21 @@ import os
|
|||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from configs import dify_config
|
from .runtime import get_workflow_file_runtime
|
||||||
|
|
||||||
|
|
||||||
def get_signed_file_url(upload_file_id: str, as_attachment=False, for_external: bool = True) -> str:
|
def get_signed_file_url(upload_file_id: str, as_attachment: bool = False, for_external: bool = True) -> str:
|
||||||
base_url = dify_config.FILES_URL if for_external else (dify_config.INTERNAL_FILES_URL or dify_config.FILES_URL)
|
runtime = get_workflow_file_runtime()
|
||||||
|
base_url = runtime.files_url if for_external else (runtime.internal_files_url or runtime.files_url)
|
||||||
url = f"{base_url}/files/{upload_file_id}/file-preview"
|
url = f"{base_url}/files/{upload_file_id}/file-preview"
|
||||||
|
|
||||||
timestamp = str(int(time.time()))
|
timestamp = str(int(time.time()))
|
||||||
nonce = os.urandom(16).hex()
|
nonce = os.urandom(16).hex()
|
||||||
key = dify_config.SECRET_KEY.encode()
|
key = runtime.secret_key.encode()
|
||||||
msg = f"file-preview|{upload_file_id}|{timestamp}|{nonce}"
|
msg = f"file-preview|{upload_file_id}|{timestamp}|{nonce}"
|
||||||
sign = hmac.new(key, msg.encode(), hashlib.sha256).digest()
|
sign = hmac.new(key, msg.encode(), hashlib.sha256).digest()
|
||||||
encoded_sign = base64.urlsafe_b64encode(sign).decode()
|
encoded_sign = base64.urlsafe_b64encode(sign).decode()
|
||||||
query = {"timestamp": timestamp, "nonce": nonce, "sign": encoded_sign}
|
query: dict[str, str] = {"timestamp": timestamp, "nonce": nonce, "sign": encoded_sign}
|
||||||
if as_attachment:
|
if as_attachment:
|
||||||
query["as_attachment"] = "true"
|
query["as_attachment"] = "true"
|
||||||
query_string = urllib.parse.urlencode(query)
|
query_string = urllib.parse.urlencode(query)
|
||||||
@ -27,57 +30,63 @@ def get_signed_file_url(upload_file_id: str, as_attachment=False, for_external:
|
|||||||
|
|
||||||
|
|
||||||
def get_signed_file_url_for_plugin(filename: str, mimetype: str, tenant_id: str, user_id: str) -> str:
|
def get_signed_file_url_for_plugin(filename: str, mimetype: str, tenant_id: str, user_id: str) -> str:
|
||||||
# Plugin access should use internal URL for Docker network communication
|
runtime = get_workflow_file_runtime()
|
||||||
base_url = dify_config.INTERNAL_FILES_URL or dify_config.FILES_URL
|
# Plugin access should use internal URL for Docker network communication.
|
||||||
|
base_url = runtime.internal_files_url or runtime.files_url
|
||||||
url = f"{base_url}/files/upload/for-plugin"
|
url = f"{base_url}/files/upload/for-plugin"
|
||||||
timestamp = str(int(time.time()))
|
timestamp = str(int(time.time()))
|
||||||
nonce = os.urandom(16).hex()
|
nonce = os.urandom(16).hex()
|
||||||
key = dify_config.SECRET_KEY.encode()
|
key = runtime.secret_key.encode()
|
||||||
msg = f"upload|{filename}|{mimetype}|{tenant_id}|{user_id}|{timestamp}|{nonce}"
|
msg = f"upload|{filename}|{mimetype}|{tenant_id}|{user_id}|{timestamp}|{nonce}"
|
||||||
sign = hmac.new(key, msg.encode(), hashlib.sha256).digest()
|
sign = hmac.new(key, msg.encode(), hashlib.sha256).digest()
|
||||||
encoded_sign = base64.urlsafe_b64encode(sign).decode()
|
encoded_sign = base64.urlsafe_b64encode(sign).decode()
|
||||||
return f"{url}?timestamp={timestamp}&nonce={nonce}&sign={encoded_sign}&user_id={user_id}&tenant_id={tenant_id}"
|
return f"{url}?timestamp={timestamp}&nonce={nonce}&sign={encoded_sign}&user_id={user_id}&tenant_id={tenant_id}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_signed_tool_file_url(tool_file_id: str, extension: str, for_external: bool = True) -> str:
|
||||||
|
runtime = get_workflow_file_runtime()
|
||||||
|
return runtime.sign_tool_file(tool_file_id=tool_file_id, extension=extension, for_external=for_external)
|
||||||
|
|
||||||
|
|
||||||
def verify_plugin_file_signature(
|
def verify_plugin_file_signature(
|
||||||
*, filename: str, mimetype: str, tenant_id: str, user_id: str, timestamp: str, nonce: str, sign: str
|
*, filename: str, mimetype: str, tenant_id: str, user_id: str, timestamp: str, nonce: str, sign: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
runtime = get_workflow_file_runtime()
|
||||||
data_to_sign = f"upload|{filename}|{mimetype}|{tenant_id}|{user_id}|{timestamp}|{nonce}"
|
data_to_sign = f"upload|{filename}|{mimetype}|{tenant_id}|{user_id}|{timestamp}|{nonce}"
|
||||||
secret_key = dify_config.SECRET_KEY.encode()
|
secret_key = runtime.secret_key.encode()
|
||||||
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
||||||
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
||||||
|
|
||||||
# verify signature
|
|
||||||
if sign != recalculated_encoded_sign:
|
if sign != recalculated_encoded_sign:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
current_time = int(time.time())
|
current_time = int(time.time())
|
||||||
return current_time - int(timestamp) <= dify_config.FILES_ACCESS_TIMEOUT
|
return current_time - int(timestamp) <= runtime.files_access_timeout
|
||||||
|
|
||||||
|
|
||||||
def verify_image_signature(*, upload_file_id: str, timestamp: str, nonce: str, sign: str) -> bool:
|
def verify_image_signature(*, upload_file_id: str, timestamp: str, nonce: str, sign: str) -> bool:
|
||||||
|
runtime = get_workflow_file_runtime()
|
||||||
data_to_sign = f"image-preview|{upload_file_id}|{timestamp}|{nonce}"
|
data_to_sign = f"image-preview|{upload_file_id}|{timestamp}|{nonce}"
|
||||||
secret_key = dify_config.SECRET_KEY.encode()
|
secret_key = runtime.secret_key.encode()
|
||||||
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
||||||
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
||||||
|
|
||||||
# verify signature
|
|
||||||
if sign != recalculated_encoded_sign:
|
if sign != recalculated_encoded_sign:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
current_time = int(time.time())
|
current_time = int(time.time())
|
||||||
return current_time - int(timestamp) <= dify_config.FILES_ACCESS_TIMEOUT
|
return current_time - int(timestamp) <= runtime.files_access_timeout
|
||||||
|
|
||||||
|
|
||||||
def verify_file_signature(*, upload_file_id: str, timestamp: str, nonce: str, sign: str) -> bool:
|
def verify_file_signature(*, upload_file_id: str, timestamp: str, nonce: str, sign: str) -> bool:
|
||||||
|
runtime = get_workflow_file_runtime()
|
||||||
data_to_sign = f"file-preview|{upload_file_id}|{timestamp}|{nonce}"
|
data_to_sign = f"file-preview|{upload_file_id}|{timestamp}|{nonce}"
|
||||||
secret_key = dify_config.SECRET_KEY.encode()
|
secret_key = runtime.secret_key.encode()
|
||||||
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
recalculated_sign = hmac.new(secret_key, data_to_sign.encode(), hashlib.sha256).digest()
|
||||||
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
recalculated_encoded_sign = base64.urlsafe_b64encode(recalculated_sign).decode()
|
||||||
|
|
||||||
# verify signature
|
|
||||||
if sign != recalculated_encoded_sign:
|
if sign != recalculated_encoded_sign:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
current_time = int(time.time())
|
current_time = int(time.time())
|
||||||
return current_time - int(timestamp) <= dify_config.FILES_ACCESS_TIMEOUT
|
return current_time - int(timestamp) <= runtime.files_access_timeout
|
||||||
@ -1,16 +1,26 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pydantic import BaseModel, Field, model_validator
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
||||||
from core.tools.signature import sign_tool_file
|
|
||||||
|
|
||||||
from . import helpers
|
from . import helpers
|
||||||
from .constants import FILE_MODEL_IDENTITY
|
from .constants import FILE_MODEL_IDENTITY
|
||||||
from .enums import FileTransferMethod, FileType
|
from .enums import FileTransferMethod, FileType
|
||||||
|
|
||||||
|
|
||||||
|
def sign_tool_file(*, tool_file_id: str, extension: str, for_external: bool = True) -> str:
|
||||||
|
"""Compatibility shim for tests and legacy callers patching ``models.sign_tool_file``."""
|
||||||
|
return helpers.get_signed_tool_file_url(
|
||||||
|
tool_file_id=tool_file_id,
|
||||||
|
extension=extension,
|
||||||
|
for_external=for_external,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ImageConfig(BaseModel):
|
class ImageConfig(BaseModel):
|
||||||
"""
|
"""
|
||||||
NOTE: This part of validation is deprecated, but still used in app features "Image Upload".
|
NOTE: This part of validation is deprecated, but still used in app features "Image Upload".
|
||||||
@ -122,7 +132,11 @@ class File(BaseModel):
|
|||||||
elif self.transfer_method in [FileTransferMethod.TOOL_FILE, FileTransferMethod.DATASOURCE_FILE]:
|
elif self.transfer_method in [FileTransferMethod.TOOL_FILE, FileTransferMethod.DATASOURCE_FILE]:
|
||||||
assert self.related_id is not None
|
assert self.related_id is not None
|
||||||
assert self.extension is not None
|
assert self.extension is not None
|
||||||
return sign_tool_file(tool_file_id=self.related_id, extension=self.extension, for_external=for_external)
|
return sign_tool_file(
|
||||||
|
tool_file_id=self.related_id,
|
||||||
|
extension=self.extension,
|
||||||
|
for_external=for_external,
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def to_plugin_parameter(self) -> dict[str, Any]:
|
def to_plugin_parameter(self) -> dict[str, Any]:
|
||||||
@ -137,7 +151,7 @@ class File(BaseModel):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@model_validator(mode="after")
|
@model_validator(mode="after")
|
||||||
def validate_after(self):
|
def validate_after(self) -> File:
|
||||||
match self.transfer_method:
|
match self.transfer_method:
|
||||||
case FileTransferMethod.REMOTE_URL:
|
case FileTransferMethod.REMOTE_URL:
|
||||||
if not self.remote_url:
|
if not self.remote_url:
|
||||||
@ -160,5 +174,5 @@ class File(BaseModel):
|
|||||||
return self._storage_key
|
return self._storage_key
|
||||||
|
|
||||||
@storage_key.setter
|
@storage_key.setter
|
||||||
def storage_key(self, value: str):
|
def storage_key(self, value: str) -> None:
|
||||||
self._storage_key = value
|
self._storage_key = value
|
||||||
43
api/core/workflow/file/protocols.py
Normal file
43
api/core/workflow/file/protocols.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
class HttpResponseProtocol(Protocol):
|
||||||
|
"""Subset of response behavior needed by workflow file helpers."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content(self) -> bytes: ...
|
||||||
|
|
||||||
|
def raise_for_status(self) -> object: ...
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowFileRuntimeProtocol(Protocol):
|
||||||
|
"""Runtime dependencies required by ``core.workflow.file``.
|
||||||
|
|
||||||
|
Implementations are expected to be provided by integration layers (for example,
|
||||||
|
``core.app.workflow.file_runtime``) so the workflow package avoids importing
|
||||||
|
application infrastructure modules directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_url(self) -> str: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def internal_files_url(self) -> str | None: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def secret_key(self) -> str: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_access_timeout(self) -> int: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def multimodal_send_format(self) -> str: ...
|
||||||
|
|
||||||
|
def http_get(self, url: str, *, follow_redirects: bool = True) -> HttpResponseProtocol: ...
|
||||||
|
|
||||||
|
def storage_load(self, path: str, *, stream: bool = False) -> bytes | Generator: ...
|
||||||
|
|
||||||
|
def sign_tool_file(self, *, tool_file_id: str, extension: str, for_external: bool = True) -> str: ...
|
||||||
58
api/core/workflow/file/runtime.py
Normal file
58
api/core/workflow/file/runtime.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
|
from typing import NoReturn
|
||||||
|
|
||||||
|
from .protocols import HttpResponseProtocol, WorkflowFileRuntimeProtocol
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowFileRuntimeNotConfiguredError(RuntimeError):
|
||||||
|
"""Raised when workflow file runtime dependencies were not configured."""
|
||||||
|
|
||||||
|
|
||||||
|
class _UnconfiguredWorkflowFileRuntime(WorkflowFileRuntimeProtocol):
|
||||||
|
def _raise(self) -> NoReturn:
|
||||||
|
raise WorkflowFileRuntimeNotConfiguredError(
|
||||||
|
"workflow file runtime is not configured, call set_workflow_file_runtime(...) first"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_url(self) -> str:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def internal_files_url(self) -> str | None:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def secret_key(self) -> str:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def files_access_timeout(self) -> int:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def multimodal_send_format(self) -> str:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
def http_get(self, url: str, *, follow_redirects: bool = True) -> HttpResponseProtocol:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
def storage_load(self, path: str, *, stream: bool = False) -> bytes | Generator:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
def sign_tool_file(self, *, tool_file_id: str, extension: str, for_external: bool = True) -> str:
|
||||||
|
self._raise()
|
||||||
|
|
||||||
|
|
||||||
|
_runtime: WorkflowFileRuntimeProtocol = _UnconfiguredWorkflowFileRuntime()
|
||||||
|
|
||||||
|
|
||||||
|
def set_workflow_file_runtime(runtime: WorkflowFileRuntimeProtocol) -> None:
|
||||||
|
global _runtime
|
||||||
|
_runtime = runtime
|
||||||
|
|
||||||
|
|
||||||
|
def get_workflow_file_runtime() -> WorkflowFileRuntimeProtocol:
|
||||||
|
return _runtime
|
||||||
9
api/core/workflow/file/tool_file_parser.py
Normal file
9
api/core/workflow/file/tool_file_parser.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from collections.abc import Callable
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
_tool_file_manager_factory: Callable[[], Any] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def set_tool_file_manager_factory(factory: Callable[[], Any]):
|
||||||
|
global _tool_file_manager_factory
|
||||||
|
_tool_file_manager_factory = factory
|
||||||
@ -3,10 +3,10 @@ from datetime import datetime
|
|||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from core.file import File
|
|
||||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||||
from core.rag.entities.citation_metadata import RetrievalSourceMetadata
|
from core.rag.entities.citation_metadata import RetrievalSourceMetadata
|
||||||
from core.workflow.entities.pause_reason import PauseReason
|
from core.workflow.entities.pause_reason import PauseReason
|
||||||
|
from core.workflow.file import File
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
|
|
||||||
from .base import NodeEventBase
|
from .base import NodeEventBase
|
||||||
|
|||||||
@ -11,7 +11,6 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from core.agent.entities import AgentToolEntity
|
from core.agent.entities import AgentToolEntity
|
||||||
from core.agent.plugin_entities import AgentStrategyParameter
|
from core.agent.plugin_entities import AgentStrategyParameter
|
||||||
from core.file import File, FileTransferMethod
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance, ModelManager
|
from core.model_manager import ModelInstance, ModelManager
|
||||||
from core.model_runtime.entities.llm_entities import LLMUsage, LLMUsageMetadata
|
from core.model_runtime.entities.llm_entities import LLMUsage, LLMUsageMetadata
|
||||||
@ -33,6 +32,7 @@ from core.workflow.enums import (
|
|||||||
WorkflowNodeExecutionMetadataKey,
|
WorkflowNodeExecutionMetadataKey,
|
||||||
WorkflowNodeExecutionStatus,
|
WorkflowNodeExecutionStatus,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import File, FileTransferMethod
|
||||||
from core.workflow.node_events import (
|
from core.workflow.node_events import (
|
||||||
AgentLogEvent,
|
AgentLogEvent,
|
||||||
NodeEventBase,
|
NodeEventBase,
|
||||||
|
|||||||
@ -14,13 +14,13 @@ from core.datasource.entities.datasource_entities import (
|
|||||||
from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin
|
from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin
|
||||||
from core.datasource.online_drive.online_drive_plugin import OnlineDriveDatasourcePlugin
|
from core.datasource.online_drive.online_drive_plugin import OnlineDriveDatasourcePlugin
|
||||||
from core.datasource.utils.message_transformer import DatasourceFileMessageTransformer
|
from core.datasource.utils.message_transformer import DatasourceFileMessageTransformer
|
||||||
from core.file import File
|
|
||||||
from core.file.enums import FileTransferMethod, FileType
|
|
||||||
from core.plugin.impl.exc import PluginDaemonClientSideError
|
from core.plugin.impl.exc import PluginDaemonClientSideError
|
||||||
from core.variables.segments import ArrayAnySegment
|
from core.variables.segments import ArrayAnySegment
|
||||||
from core.variables.variables import ArrayAnyVariable
|
from core.variables.variables import ArrayAnyVariable
|
||||||
from core.workflow.entities.workflow_node_execution import WorkflowNodeExecutionStatus
|
from core.workflow.entities.workflow_node_execution import WorkflowNodeExecutionStatus
|
||||||
from core.workflow.enums import NodeExecutionType, NodeType, SystemVariableKey
|
from core.workflow.enums import NodeExecutionType, NodeType, SystemVariableKey
|
||||||
|
from core.workflow.file import File
|
||||||
|
from core.workflow.file.enums import FileTransferMethod, FileType
|
||||||
from core.workflow.node_events import NodeRunResult, StreamChunkEvent, StreamCompletedEvent
|
from core.workflow.node_events import NodeRunResult, StreamChunkEvent, StreamCompletedEvent
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
from core.workflow.nodes.base.variable_template_parser import VariableTemplateParser
|
from core.workflow.nodes.base.variable_template_parser import VariableTemplateParser
|
||||||
|
|||||||
@ -21,11 +21,11 @@ from docx.table import Table
|
|||||||
from docx.text.paragraph import Paragraph
|
from docx.text.paragraph import Paragraph
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file import File, FileTransferMethod, file_manager
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
from core.variables import ArrayFileSegment
|
from core.variables import ArrayFileSegment
|
||||||
from core.variables.segments import ArrayStringSegment, FileSegment
|
from core.variables.segments import ArrayStringSegment, FileSegment
|
||||||
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
||||||
|
from core.workflow.file import File, FileTransferMethod, file_manager
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
|
|
||||||
|
|||||||
@ -11,10 +11,10 @@ import httpx
|
|||||||
from json_repair import repair_json
|
from json_repair import repair_json
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file.enums import FileTransferMethod
|
|
||||||
from core.file.file_manager import file_manager as default_file_manager
|
|
||||||
from core.helper.ssrf_proxy import ssrf_proxy
|
from core.helper.ssrf_proxy import ssrf_proxy
|
||||||
from core.variables.segments import ArrayFileSegment, FileSegment
|
from core.variables.segments import ArrayFileSegment, FileSegment
|
||||||
|
from core.workflow.file.enums import FileTransferMethod
|
||||||
|
from core.workflow.file.file_manager import file_manager as default_file_manager
|
||||||
from core.workflow.runtime import VariablePool
|
from core.workflow.runtime import VariablePool
|
||||||
|
|
||||||
from ..protocols import FileManagerProtocol, HttpClientProtocol
|
from ..protocols import FileManagerProtocol, HttpClientProtocol
|
||||||
|
|||||||
@ -4,12 +4,12 @@ from collections.abc import Callable, Mapping, Sequence
|
|||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file import File, FileTransferMethod
|
|
||||||
from core.file.file_manager import file_manager as default_file_manager
|
|
||||||
from core.helper.ssrf_proxy import ssrf_proxy
|
from core.helper.ssrf_proxy import ssrf_proxy
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
from core.variables.segments import ArrayFileSegment
|
from core.variables.segments import ArrayFileSegment
|
||||||
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
||||||
|
from core.workflow.file import File, FileTransferMethod
|
||||||
|
from core.workflow.file.file_manager import file_manager as default_file_manager
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes.base import variable_template_parser
|
from core.workflow.nodes.base import variable_template_parser
|
||||||
from core.workflow.nodes.base.entities import VariableSelector
|
from core.workflow.nodes.base.entities import VariableSelector
|
||||||
|
|||||||
@ -30,7 +30,7 @@ from .exc import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
from core.workflow.runtime import GraphRuntimeState
|
from core.workflow.runtime import GraphRuntimeState
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
from collections.abc import Callable, Sequence
|
from collections.abc import Callable, Sequence
|
||||||
from typing import Any, TypeAlias, TypeVar
|
from typing import Any, TypeAlias, TypeVar
|
||||||
|
|
||||||
from core.file import File
|
|
||||||
from core.variables import ArrayFileSegment, ArrayNumberSegment, ArrayStringSegment
|
from core.variables import ArrayFileSegment, ArrayNumberSegment, ArrayStringSegment
|
||||||
from core.variables.segments import ArrayAnySegment, ArrayBooleanSegment, ArraySegment
|
from core.variables.segments import ArrayAnySegment, ArrayBooleanSegment, ArraySegment
|
||||||
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowNodeExecutionStatus
|
||||||
|
from core.workflow.file import File
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
|
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import typing as tp
|
|||||||
from sqlalchemy import Engine
|
from sqlalchemy import Engine
|
||||||
|
|
||||||
from constants.mimetypes import DEFAULT_EXTENSION, DEFAULT_MIME_TYPE
|
from constants.mimetypes import DEFAULT_EXTENSION, DEFAULT_MIME_TYPE
|
||||||
from core.file import File, FileTransferMethod, FileType
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
from core.tools.signature import sign_tool_file
|
from core.tools.signature import sign_tool_file
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from extensions.ext_database import db as global_db
|
from extensions.ext_database import db as global_db
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ from sqlalchemy.orm import Session
|
|||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
||||||
from core.entities.provider_entities import ProviderQuotaType, QuotaUnit
|
from core.entities.provider_entities import ProviderQuotaType, QuotaUnit
|
||||||
from core.file.models import File
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance, ModelManager
|
from core.model_manager import ModelInstance, ModelManager
|
||||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||||
@ -16,6 +15,7 @@ from core.model_runtime.model_providers.__base.large_language_model import Large
|
|||||||
from core.prompt.entities.advanced_prompt_entities import MemoryConfig
|
from core.prompt.entities.advanced_prompt_entities import MemoryConfig
|
||||||
from core.variables.segments import ArrayAnySegment, ArrayFileSegment, FileSegment, NoneSegment, StringSegment
|
from core.variables.segments import ArrayAnySegment, ArrayFileSegment, FileSegment, NoneSegment, StringSegment
|
||||||
from core.workflow.enums import SystemVariableKey
|
from core.workflow.enums import SystemVariableKey
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.nodes.llm.entities import ModelConfig
|
from core.workflow.nodes.llm.entities import ModelConfig
|
||||||
from core.workflow.runtime import VariablePool
|
from core.workflow.runtime import VariablePool
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
|
|||||||
@ -12,7 +12,6 @@ from typing import TYPE_CHECKING, Any, Literal
|
|||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
||||||
from core.file import File, FileTransferMethod, FileType, file_manager
|
|
||||||
from core.helper.code_executor import CodeExecutor, CodeLanguage
|
from core.helper.code_executor import CodeExecutor, CodeLanguage
|
||||||
from core.llm_generator.output_parser.errors import OutputParserError
|
from core.llm_generator.output_parser.errors import OutputParserError
|
||||||
from core.llm_generator.output_parser.structured_output import invoke_llm_with_structured_output
|
from core.llm_generator.output_parser.structured_output import invoke_llm_with_structured_output
|
||||||
@ -65,6 +64,7 @@ from core.workflow.enums import (
|
|||||||
WorkflowNodeExecutionMetadataKey,
|
WorkflowNodeExecutionMetadataKey,
|
||||||
WorkflowNodeExecutionStatus,
|
WorkflowNodeExecutionStatus,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import File, FileTransferMethod, FileType, file_manager
|
||||||
from core.workflow.node_events import (
|
from core.workflow.node_events import (
|
||||||
ModelInvokeCompletedEvent,
|
ModelInvokeCompletedEvent,
|
||||||
NodeEventBase,
|
NodeEventBase,
|
||||||
@ -101,7 +101,7 @@ from .exc import (
|
|||||||
from .file_saver import FileSaverImpl, LLMFileSaver
|
from .file_saver import FileSaverImpl, LLMFileSaver
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
from core.workflow.runtime import GraphRuntimeState
|
from core.workflow.runtime import GraphRuntimeState
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@ -71,9 +71,9 @@ class LoopNode(LLMUsageTrackingMixin, Node[LoopNodeData]):
|
|||||||
if self.node_data.loop_variables:
|
if self.node_data.loop_variables:
|
||||||
value_processor: dict[Literal["constant", "variable"], Callable[[LoopVariableData], Segment | None]] = {
|
value_processor: dict[Literal["constant", "variable"], Callable[[LoopVariableData], Segment | None]] = {
|
||||||
"constant": lambda var: self._get_segment_for_constant(var.var_type, var.value),
|
"constant": lambda var: self._get_segment_for_constant(var.var_type, var.value),
|
||||||
"variable": lambda var: self.graph_runtime_state.variable_pool.get(var.value)
|
"variable": lambda var: (
|
||||||
if isinstance(var.value, list)
|
self.graph_runtime_state.variable_pool.get(var.value) if isinstance(var.value, list) else None
|
||||||
else None,
|
),
|
||||||
}
|
}
|
||||||
for loop_variable in self.node_data.loop_variables:
|
for loop_variable in self.node_data.loop_variables:
|
||||||
if loop_variable.value_type not in value_processor:
|
if loop_variable.value_type not in value_processor:
|
||||||
|
|||||||
@ -6,7 +6,6 @@ from collections.abc import Mapping, Sequence
|
|||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity
|
||||||
from core.file import File
|
|
||||||
from core.memory.token_buffer_memory import TokenBufferMemory
|
from core.memory.token_buffer_memory import TokenBufferMemory
|
||||||
from core.model_manager import ModelInstance
|
from core.model_manager import ModelInstance
|
||||||
from core.model_runtime.entities import ImagePromptMessageContent
|
from core.model_runtime.entities import ImagePromptMessageContent
|
||||||
@ -28,6 +27,7 @@ from core.prompt.simple_prompt_transform import ModelMode
|
|||||||
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
from core.prompt.utils.prompt_message_util import PromptMessageUtil
|
||||||
from core.variables.types import ArrayValidation, SegmentType
|
from core.variables.types import ArrayValidation, SegmentType
|
||||||
from core.workflow.enums import NodeType, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
|
||||||
|
from core.workflow.file import File
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes.base import variable_template_parser
|
from core.workflow.nodes.base import variable_template_parser
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
|
|||||||
@ -2,7 +2,7 @@ from typing import Any, Protocol
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
|
|
||||||
|
|
||||||
class HttpClientProtocol(Protocol):
|
class HttpClientProtocol(Protocol):
|
||||||
|
|||||||
@ -39,7 +39,7 @@ from .template_prompts import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
from core.workflow.runtime import GraphRuntimeState
|
from core.workflow.runtime import GraphRuntimeState
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ from sqlalchemy import select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from core.callback_handler.workflow_tool_callback_handler import DifyWorkflowCallbackHandler
|
from core.callback_handler.workflow_tool_callback_handler import DifyWorkflowCallbackHandler
|
||||||
from core.file import File, FileTransferMethod
|
|
||||||
from core.model_runtime.entities.llm_entities import LLMUsage
|
from core.model_runtime.entities.llm_entities import LLMUsage
|
||||||
from core.tools.__base.tool import Tool
|
from core.tools.__base.tool import Tool
|
||||||
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
||||||
@ -20,6 +19,7 @@ from core.workflow.enums import (
|
|||||||
WorkflowNodeExecutionMetadataKey,
|
WorkflowNodeExecutionMetadataKey,
|
||||||
WorkflowNodeExecutionStatus,
|
WorkflowNodeExecutionStatus,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import File, FileTransferMethod
|
||||||
from core.workflow.node_events import NodeEventBase, NodeRunResult, StreamChunkEvent, StreamCompletedEvent
|
from core.workflow.node_events import NodeEventBase, NodeRunResult, StreamChunkEvent, StreamCompletedEvent
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
from core.workflow.nodes.base.variable_template_parser import VariableTemplateParser
|
from core.workflow.nodes.base.variable_template_parser import VariableTemplateParser
|
||||||
|
|||||||
@ -2,12 +2,12 @@ import logging
|
|||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from core.file import FileTransferMethod
|
|
||||||
from core.variables.types import SegmentType
|
from core.variables.types import SegmentType
|
||||||
from core.variables.variables import FileVariable
|
from core.variables.variables import FileVariable
|
||||||
from core.workflow.constants import SYSTEM_VARIABLE_NODE_ID
|
from core.workflow.constants import SYSTEM_VARIABLE_NODE_ID
|
||||||
from core.workflow.entities.workflow_node_execution import WorkflowNodeExecutionStatus
|
from core.workflow.entities.workflow_node_execution import WorkflowNodeExecutionStatus
|
||||||
from core.workflow.enums import NodeExecutionType, NodeType
|
from core.workflow.enums import NodeExecutionType, NodeType
|
||||||
|
from core.workflow.file import FileTransferMethod
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
from factories import file_factory
|
from factories import file_factory
|
||||||
|
|||||||
@ -8,7 +8,6 @@ from typing import Annotated, Any, Union, cast
|
|||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from core.file import File, FileAttribute, file_manager
|
|
||||||
from core.variables import Segment, SegmentGroup, VariableBase
|
from core.variables import Segment, SegmentGroup, VariableBase
|
||||||
from core.variables.consts import SELECTORS_LENGTH
|
from core.variables.consts import SELECTORS_LENGTH
|
||||||
from core.variables.segments import FileSegment, ObjectSegment
|
from core.variables.segments import FileSegment, ObjectSegment
|
||||||
@ -19,6 +18,7 @@ from core.workflow.constants import (
|
|||||||
RAG_PIPELINE_VARIABLE_NODE_ID,
|
RAG_PIPELINE_VARIABLE_NODE_ID,
|
||||||
SYSTEM_VARIABLE_NODE_ID,
|
SYSTEM_VARIABLE_NODE_ID,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import File, FileAttribute, file_manager
|
||||||
from core.workflow.system_variable import SystemVariable
|
from core.workflow.system_variable import SystemVariable
|
||||||
from factories import variable_factory
|
from factories import variable_factory
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,8 @@ from uuid import uuid4
|
|||||||
|
|
||||||
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, model_validator
|
from pydantic import AliasChoices, BaseModel, ConfigDict, Field, model_validator
|
||||||
|
|
||||||
from core.file.models import File
|
|
||||||
from core.workflow.enums import SystemVariableKey
|
from core.workflow.enums import SystemVariableKey
|
||||||
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
|
|
||||||
class SystemVariable(BaseModel):
|
class SystemVariable(BaseModel):
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import json
|
|||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from typing import Literal, NamedTuple
|
from typing import Literal, NamedTuple
|
||||||
|
|
||||||
from core.file import FileAttribute, file_manager
|
|
||||||
from core.variables import ArrayFileSegment
|
from core.variables import ArrayFileSegment
|
||||||
from core.variables.segments import ArrayBooleanSegment, BooleanSegment
|
from core.variables.segments import ArrayBooleanSegment, BooleanSegment
|
||||||
|
from core.workflow.file import FileAttribute, file_manager
|
||||||
from core.workflow.runtime import VariablePool
|
from core.workflow.runtime import VariablePool
|
||||||
|
|
||||||
from .entities import Condition, SubCondition, SupportedComparisonOperator
|
from .entities import Condition, SubCondition, SupportedComparisonOperator
|
||||||
|
|||||||
@ -9,10 +9,10 @@ from core.app.apps.exc import GenerateTaskStoppedError
|
|||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.app.workflow.layers.observability import ObservabilityLayer
|
from core.app.workflow.layers.observability import ObservabilityLayer
|
||||||
from core.app.workflow.node_factory import DifyNodeFactory
|
from core.app.workflow.node_factory import DifyNodeFactory
|
||||||
from core.file.models import File
|
|
||||||
from core.workflow.constants import ENVIRONMENT_VARIABLE_NODE_ID
|
from core.workflow.constants import ENVIRONMENT_VARIABLE_NODE_ID
|
||||||
from core.workflow.entities import GraphInitParams
|
from core.workflow.entities import GraphInitParams
|
||||||
from core.workflow.errors import WorkflowNodeRunFailedError
|
from core.workflow.errors import WorkflowNodeRunFailedError
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.graph import Graph
|
from core.workflow.graph import Graph
|
||||||
from core.workflow.graph_engine import GraphEngine, GraphEngineConfig
|
from core.workflow.graph_engine import GraphEngine, GraphEngineConfig
|
||||||
from core.workflow.graph_engine.command_channels import InMemoryChannel
|
from core.workflow.graph_engine.command_channels import InMemoryChannel
|
||||||
|
|||||||
@ -4,8 +4,8 @@ from typing import Any, overload
|
|||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from core.file.models import File
|
|
||||||
from core.variables import Segment
|
from core.variables import Segment
|
||||||
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
|
|
||||||
class WorkflowRuntimeTypeConverter:
|
class WorkflowRuntimeTypeConverter:
|
||||||
|
|||||||
@ -94,6 +94,10 @@ class Storage:
|
|||||||
@overload
|
@overload
|
||||||
def load(self, filename: str, /, *, stream: Literal[True]) -> Generator: ...
|
def load(self, filename: str, /, *, stream: Literal[True]) -> Generator: ...
|
||||||
|
|
||||||
|
# Keep a bool fallback overload for callers that forward a runtime bool flag.
|
||||||
|
@overload
|
||||||
|
def load(self, filename: str, /, *, stream: bool = False) -> Union[bytes, Generator]: ...
|
||||||
|
|
||||||
def load(self, filename: str, /, *, stream: bool = False) -> Union[bytes, Generator]:
|
def load(self, filename: str, /, *, stream: bool = False) -> Union[bytes, Generator]:
|
||||||
if stream:
|
if stream:
|
||||||
return self.load_stream(filename)
|
return self.load_stream(filename)
|
||||||
@ -124,3 +128,6 @@ storage = Storage()
|
|||||||
|
|
||||||
def init_app(app: DifyApp):
|
def init_app(app: DifyApp):
|
||||||
storage.init_app(app)
|
storage.init_app(app)
|
||||||
|
from core.app.workflow.file_runtime import bind_dify_workflow_file_runtime
|
||||||
|
|
||||||
|
bind_dify_workflow_file_runtime()
|
||||||
|
|||||||
@ -9,9 +9,9 @@ from opentelemetry.trace import Span
|
|||||||
from opentelemetry.trace.status import Status, StatusCode
|
from opentelemetry.trace.status import Status, StatusCode
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from core.file.models import File
|
|
||||||
from core.variables import Segment
|
from core.variables import Segment
|
||||||
from core.workflow.enums import NodeType
|
from core.workflow.enums import NodeType
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.graph_events import GraphNodeEventBase
|
from core.workflow.graph_events import GraphNodeEventBase
|
||||||
from core.workflow.nodes.base.node import Node
|
from core.workflow.nodes.base.node import Node
|
||||||
from extensions.otel.semconv.gen_ai import ChainAttributes, GenAIAttributes
|
from extensions.otel.semconv.gen_ai import ChainAttributes, GenAIAttributes
|
||||||
|
|||||||
@ -13,8 +13,8 @@ from sqlalchemy.orm import Session
|
|||||||
from werkzeug.http import parse_options_header
|
from werkzeug.http import parse_options_header
|
||||||
|
|
||||||
from constants import AUDIO_EXTENSIONS, DOCUMENT_EXTENSIONS, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
from constants import AUDIO_EXTENSIONS, DOCUMENT_EXTENSIONS, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS
|
||||||
from core.file import File, FileBelongsTo, FileTransferMethod, FileType, FileUploadConfig, helpers
|
|
||||||
from core.helper import ssrf_proxy
|
from core.helper import ssrf_proxy
|
||||||
|
from core.workflow.file import File, FileBelongsTo, FileTransferMethod, FileType, FileUploadConfig, helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models import MessageFile, ToolFile, UploadFile
|
from models import MessageFile, ToolFile, UploadFile
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ from typing import Any, cast
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file import File
|
|
||||||
from core.variables.exc import VariableError
|
from core.variables.exc import VariableError
|
||||||
from core.variables.segments import (
|
from core.variables.segments import (
|
||||||
ArrayAnySegment,
|
ArrayAnySegment,
|
||||||
@ -44,6 +43,7 @@ from core.workflow.constants import (
|
|||||||
CONVERSATION_VARIABLE_NODE_ID,
|
CONVERSATION_VARIABLE_NODE_ID,
|
||||||
ENVIRONMENT_VARIABLE_NODE_ID,
|
ENVIRONMENT_VARIABLE_NODE_ID,
|
||||||
)
|
)
|
||||||
|
from core.workflow.file import File
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedSegmentTypeError(Exception):
|
class UnsupportedSegmentTypeError(Exception):
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from typing import Any, TypeAlias
|
|||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
|
|
||||||
JSONValue: TypeAlias = Any
|
JSONValue: TypeAlias = Any
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from datetime import datetime
|
|||||||
from flask_restx import fields
|
from flask_restx import fields
|
||||||
from pydantic import BaseModel, ConfigDict, computed_field, field_validator
|
from pydantic import BaseModel, ConfigDict, computed_field, field_validator
|
||||||
|
|
||||||
from core.file import helpers as file_helpers
|
from core.workflow.file import helpers as file_helpers
|
||||||
|
|
||||||
simple_account_fields = {
|
simple_account_fields = {
|
||||||
"id": fields.String,
|
"id": fields.String,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from uuid import uuid4
|
|||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
from core.entities.execution_extra_content import ExecutionExtraContentDomainModel
|
from core.entities.execution_extra_content import ExecutionExtraContentDomainModel
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
from fields.conversation_fields import AgentThought, JSONValue, MessageFile
|
from fields.conversation_fields import AgentThought, JSONValue, MessageFile
|
||||||
|
|
||||||
JSONValueType: TypeAlias = JSONValue
|
JSONValueType: TypeAlias = JSONValue
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from flask_restx import fields
|
from flask_restx import fields
|
||||||
|
|
||||||
from core.file import File
|
from core.workflow.file import File
|
||||||
|
|
||||||
|
|
||||||
class FilesContainedField(fields.Raw):
|
class FilesContainedField(fields.Raw):
|
||||||
|
|||||||
@ -21,8 +21,8 @@ from pydantic.functional_validators import AfterValidator
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.app.features.rate_limiting.rate_limit import RateLimitGenerator
|
from core.app.features.rate_limiting.rate_limit import RateLimitGenerator
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_redis import redis_client
|
from extensions.ext_redis import redis_client
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -18,10 +18,10 @@ from sqlalchemy.orm import Mapped, Session, mapped_column
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from constants import DEFAULT_FILE_NUMBER_LIMITS
|
from constants import DEFAULT_FILE_NUMBER_LIMITS
|
||||||
from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod
|
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.tools.signature import sign_tool_file
|
from core.tools.signature import sign_tool_file
|
||||||
from core.workflow.enums import WorkflowExecutionStatus
|
from core.workflow.enums import WorkflowExecutionStatus
|
||||||
|
from core.workflow.file import FILE_MODEL_IDENTITY, File, FileTransferMethod
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from libs.helper import generate_string # type: ignore[import-not-found]
|
from libs.helper import generate_string # type: ignore[import-not-found]
|
||||||
from libs.uuid_utils import uuidv7
|
from libs.uuid_utils import uuidv7
|
||||||
|
|
||||||
|
|||||||
@ -22,8 +22,6 @@ from sqlalchemy import (
|
|||||||
from sqlalchemy.orm import Mapped, declared_attr, mapped_column
|
from sqlalchemy.orm import Mapped, declared_attr, mapped_column
|
||||||
from typing_extensions import deprecated
|
from typing_extensions import deprecated
|
||||||
|
|
||||||
from core.file.constants import maybe_file_object
|
|
||||||
from core.file.models import File
|
|
||||||
from core.variables import utils as variable_utils
|
from core.variables import utils as variable_utils
|
||||||
from core.variables.variables import FloatVariable, IntegerVariable, StringVariable
|
from core.variables.variables import FloatVariable, IntegerVariable, StringVariable
|
||||||
from core.workflow.constants import (
|
from core.workflow.constants import (
|
||||||
@ -33,6 +31,8 @@ from core.workflow.constants import (
|
|||||||
from core.workflow.entities.graph_config import NodeConfigDict, NodeConfigDictAdapter
|
from core.workflow.entities.graph_config import NodeConfigDict, NodeConfigDictAdapter
|
||||||
from core.workflow.entities.pause_reason import HumanInputRequired, PauseReason, PauseReasonType, SchedulingPause
|
from core.workflow.entities.pause_reason import HumanInputRequired, PauseReason, PauseReasonType, SchedulingPause
|
||||||
from core.workflow.enums import NodeType, WorkflowExecutionStatus
|
from core.workflow.enums import NodeType, WorkflowExecutionStatus
|
||||||
|
from core.workflow.file.constants import maybe_file_object
|
||||||
|
from core.workflow.file.models import File
|
||||||
from extensions.ext_storage import Storage
|
from extensions.ext_storage import Storage
|
||||||
from factories.variable_factory import TypeMismatchError, build_segment_with_type
|
from factories.variable_factory import TypeMismatchError, build_segment_with_type
|
||||||
from libs.datetime_utils import naive_utc_now
|
from libs.datetime_utils import naive_utc_now
|
||||||
|
|||||||
@ -18,7 +18,6 @@ from werkzeug.exceptions import Forbidden, NotFound
|
|||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.db.session_factory import session_factory
|
from core.db.session_factory import session_factory
|
||||||
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
|
from core.errors.error import LLMBadRequestError, ProviderTokenNotInitError
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.helper.name_generator import generate_incremental_name
|
from core.helper.name_generator import generate_incremental_name
|
||||||
from core.model_manager import ModelManager
|
from core.model_manager import ModelManager
|
||||||
from core.model_runtime.entities.model_entities import ModelFeature, ModelType
|
from core.model_runtime.entities.model_entities import ModelFeature, ModelType
|
||||||
@ -26,6 +25,7 @@ from core.model_runtime.model_providers.__base.text_embedding_model import TextE
|
|||||||
from core.rag.index_processor.constant.built_in_field import BuiltInField
|
from core.rag.index_processor.constant.built_in_field import BuiltInField
|
||||||
from core.rag.index_processor.constant.index_type import IndexStructureType
|
from core.rag.index_processor.constant.index_type import IndexStructureType
|
||||||
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
from core.rag.retrieval.retrieval_methods import RetrievalMethod
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from enums.cloud_plan import CloudPlan
|
from enums.cloud_plan import CloudPlan
|
||||||
from events.dataset_event import dataset_was_deleted
|
from events.dataset_event import dataset_was_deleted
|
||||||
from events.document_event import document_was_deleted
|
from events.document_event import document_was_deleted
|
||||||
|
|||||||
@ -19,8 +19,8 @@ from constants import (
|
|||||||
IMAGE_EXTENSIONS,
|
IMAGE_EXTENSIONS,
|
||||||
VIDEO_EXTENSIONS,
|
VIDEO_EXTENSIONS,
|
||||||
)
|
)
|
||||||
from core.file import helpers as file_helpers
|
|
||||||
from core.rag.extractor.extract_processor import ExtractProcessor
|
from core.rag.extractor.extract_processor import ExtractProcessor
|
||||||
|
from core.workflow.file import helpers as file_helpers
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from extensions.ext_storage import storage
|
from extensions.ext_storage import storage
|
||||||
from libs.datetime_utils import naive_utc_now
|
from libs.datetime_utils import naive_utc_now
|
||||||
|
|||||||
@ -15,10 +15,10 @@ from werkzeug.exceptions import RequestEntityTooLarge
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.file.models import FileTransferMethod
|
|
||||||
from core.tools.tool_file_manager import ToolFileManager
|
from core.tools.tool_file_manager import ToolFileManager
|
||||||
from core.variables.types import SegmentType
|
from core.variables.types import SegmentType
|
||||||
from core.workflow.enums import NodeType
|
from core.workflow.enums import NodeType
|
||||||
|
from core.workflow.file.models import FileTransferMethod
|
||||||
from enums.quota_type import QuotaType
|
from enums.quota_type import QuotaType
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from extensions.ext_redis import redis_client
|
from extensions.ext_redis import redis_client
|
||||||
|
|||||||
@ -6,7 +6,6 @@ from collections.abc import Mapping
|
|||||||
from typing import Any, Generic, TypeAlias, TypeVar, overload
|
from typing import Any, Generic, TypeAlias, TypeVar, overload
|
||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.file.models import File
|
|
||||||
from core.variables.segments import (
|
from core.variables.segments import (
|
||||||
ArrayFileSegment,
|
ArrayFileSegment,
|
||||||
ArraySegment,
|
ArraySegment,
|
||||||
@ -20,6 +19,7 @@ from core.variables.segments import (
|
|||||||
StringSegment,
|
StringSegment,
|
||||||
)
|
)
|
||||||
from core.variables.utils import dumps_with_segments
|
from core.variables.utils import dumps_with_segments
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.nodes.variable_assigner.common.helpers import UpdatedVariable
|
from core.workflow.nodes.variable_assigner.common.helpers import UpdatedVariable
|
||||||
|
|
||||||
_MAX_DEPTH = 100
|
_MAX_DEPTH = 100
|
||||||
|
|||||||
@ -13,12 +13,12 @@ from core.app.app_config.entities import (
|
|||||||
from core.app.apps.agent_chat.app_config_manager import AgentChatAppConfigManager
|
from core.app.apps.agent_chat.app_config_manager import AgentChatAppConfigManager
|
||||||
from core.app.apps.chat.app_config_manager import ChatAppConfigManager
|
from core.app.apps.chat.app_config_manager import ChatAppConfigManager
|
||||||
from core.app.apps.completion.app_config_manager import CompletionAppConfigManager
|
from core.app.apps.completion.app_config_manager import CompletionAppConfigManager
|
||||||
from core.file.models import FileUploadConfig
|
|
||||||
from core.helper import encrypter
|
from core.helper import encrypter
|
||||||
from core.model_runtime.entities.llm_entities import LLMMode
|
from core.model_runtime.entities.llm_entities import LLMMode
|
||||||
from core.model_runtime.utils.encoders import jsonable_encoder
|
from core.model_runtime.utils.encoders import jsonable_encoder
|
||||||
from core.prompt.simple_prompt_transform import SimplePromptTransform
|
from core.prompt.simple_prompt_transform import SimplePromptTransform
|
||||||
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
from core.prompt.utils.prompt_template_parser import PromptTemplateParser
|
||||||
|
from core.workflow.file.models import FileUploadConfig
|
||||||
from core.workflow.nodes import NodeType
|
from core.workflow.nodes import NodeType
|
||||||
from events.app_event import app_was_created
|
from events.app_event import app_was_created
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
|
|||||||
@ -14,7 +14,6 @@ from sqlalchemy.sql.expression import and_, or_
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.file.models import File
|
|
||||||
from core.variables import Segment, StringSegment, VariableBase
|
from core.variables import Segment, StringSegment, VariableBase
|
||||||
from core.variables.consts import SELECTORS_LENGTH
|
from core.variables.consts import SELECTORS_LENGTH
|
||||||
from core.variables.segments import (
|
from core.variables.segments import (
|
||||||
@ -25,6 +24,7 @@ from core.variables.types import SegmentType
|
|||||||
from core.variables.utils import dumps_with_segments
|
from core.variables.utils import dumps_with_segments
|
||||||
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, ENVIRONMENT_VARIABLE_NODE_ID, SYSTEM_VARIABLE_NODE_ID
|
from core.workflow.constants import CONVERSATION_VARIABLE_NODE_ID, ENVIRONMENT_VARIABLE_NODE_ID, SYSTEM_VARIABLE_NODE_ID
|
||||||
from core.workflow.enums import SystemVariableKey
|
from core.workflow.enums import SystemVariableKey
|
||||||
|
from core.workflow.file.models import File
|
||||||
from core.workflow.nodes import NodeType
|
from core.workflow.nodes import NodeType
|
||||||
from core.workflow.nodes.variable_assigner.common.helpers import get_updated_variables
|
from core.workflow.nodes.variable_assigner.common.helpers import get_updated_variables
|
||||||
from core.workflow.variable_loader import VariableLoader
|
from core.workflow.variable_loader import VariableLoader
|
||||||
|
|||||||
@ -13,7 +13,6 @@ from core.app.app_config.entities import VariableEntityType
|
|||||||
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfigManager
|
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfigManager
|
||||||
from core.app.apps.workflow.app_config_manager import WorkflowAppConfigManager
|
from core.app.apps.workflow.app_config_manager import WorkflowAppConfigManager
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.file import File
|
|
||||||
from core.repositories import DifyCoreRepositoryFactory
|
from core.repositories import DifyCoreRepositoryFactory
|
||||||
from core.repositories.human_input_repository import HumanInputFormRepositoryImpl
|
from core.repositories.human_input_repository import HumanInputFormRepositoryImpl
|
||||||
from core.variables import VariableBase
|
from core.variables import VariableBase
|
||||||
@ -22,6 +21,7 @@ from core.workflow.entities import GraphInitParams, WorkflowNodeExecution
|
|||||||
from core.workflow.entities.pause_reason import HumanInputRequired
|
from core.workflow.entities.pause_reason import HumanInputRequired
|
||||||
from core.workflow.enums import ErrorStrategy, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
|
from core.workflow.enums import ErrorStrategy, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
|
||||||
from core.workflow.errors import WorkflowNodeRunFailedError
|
from core.workflow.errors import WorkflowNodeRunFailedError
|
||||||
|
from core.workflow.file import File
|
||||||
from core.workflow.graph_events import GraphNodeEventBase, NodeRunFailedEvent, NodeRunSucceededEvent
|
from core.workflow.graph_events import GraphNodeEventBase, NodeRunFailedEvent, NodeRunSucceededEvent
|
||||||
from core.workflow.node_events import NodeRunResult
|
from core.workflow.node_events import NodeRunResult
|
||||||
from core.workflow.nodes import NodeType
|
from core.workflow.nodes import NodeType
|
||||||
|
|||||||
8
api/tests/conftest.py
Normal file
8
api/tests/conftest.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from core.app.workflow.file_runtime import bind_dify_workflow_file_runtime
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def _bind_workflow_file_runtime() -> None:
|
||||||
|
bind_dify_workflow_file_runtime()
|
||||||
@ -6,7 +6,7 @@ from uuid import uuid4
|
|||||||
import pytest
|
import pytest
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from core.file import File, FileTransferMethod, FileType
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories.file_factory import StorageKeyLoader
|
from factories.file_factory import StorageKeyLoader
|
||||||
from models import ToolFile, UploadFile
|
from models import ToolFile, UploadFile
|
||||||
|
|||||||
@ -6,7 +6,7 @@ from uuid import uuid4
|
|||||||
import pytest
|
import pytest
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from core.file import File, FileTransferMethod, FileType
|
from core.workflow.file import File, FileTransferMethod, FileType
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from factories.file_factory import StorageKeyLoader
|
from factories.file_factory import StorageKeyLoader
|
||||||
from models import ToolFile, UploadFile
|
from models import ToolFile, UploadFile
|
||||||
|
|||||||
@ -841,7 +841,7 @@ class TestAgentService:
|
|||||||
app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
|
app, account = self._create_test_app_and_account(db_session_with_containers, mock_external_service_dependencies)
|
||||||
conversation, message = self._create_test_conversation_and_message(db_session_with_containers, app, account)
|
conversation, message = self._create_test_conversation_and_message(db_session_with_containers, app, account)
|
||||||
|
|
||||||
from core.file import FileTransferMethod, FileType
|
from core.workflow.file import FileTransferMethod, FileType
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
from models.enums import CreatorUserRole
|
from models.enums import CreatorUserRole
|
||||||
|
|
||||||
|
|||||||
@ -310,8 +310,8 @@ def test_workflow_node_variables_fields():
|
|||||||
|
|
||||||
def test_workflow_file_variable_with_signed_url():
|
def test_workflow_file_variable_with_signed_url():
|
||||||
"""Test that File type variables include signed URLs in API responses."""
|
"""Test that File type variables include signed URLs in API responses."""
|
||||||
from core.file.enums import FileTransferMethod, FileType
|
from core.workflow.file.enums import FileTransferMethod, FileType
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
# Create a File object with LOCAL_FILE transfer method (which generates signed URLs)
|
# Create a File object with LOCAL_FILE transfer method (which generates signed URLs)
|
||||||
test_file = File(
|
test_file = File(
|
||||||
@ -368,8 +368,8 @@ def test_workflow_file_variable_with_signed_url():
|
|||||||
|
|
||||||
def test_workflow_file_variable_remote_url():
|
def test_workflow_file_variable_remote_url():
|
||||||
"""Test that File type variables with REMOTE_URL transfer method return the remote URL."""
|
"""Test that File type variables with REMOTE_URL transfer method return the remote URL."""
|
||||||
from core.file.enums import FileTransferMethod, FileType
|
from core.workflow.file.enums import FileTransferMethod, FileType
|
||||||
from core.file.models import File
|
from core.workflow.file.models import File
|
||||||
|
|
||||||
# Create a File object with REMOTE_URL transfer method
|
# Create a File object with REMOTE_URL transfer method
|
||||||
test_file = File(
|
test_file = File(
|
||||||
|
|||||||
@ -49,8 +49,8 @@ def datasets_document_module(monkeypatch: pytest.MonkeyPatch):
|
|||||||
monkeypatch.setattr(wraps, "account_initialization_required", _noop)
|
monkeypatch.setattr(wraps, "account_initialization_required", _noop)
|
||||||
|
|
||||||
# Bypass billing-related decorators used by other endpoints in this module.
|
# Bypass billing-related decorators used by other endpoints in this module.
|
||||||
monkeypatch.setattr(wraps, "cloud_edition_billing_resource_check", lambda *_args, **_kwargs: (lambda f: f))
|
monkeypatch.setattr(wraps, "cloud_edition_billing_resource_check", lambda *_args, **_kwargs: lambda f: f)
|
||||||
monkeypatch.setattr(wraps, "cloud_edition_billing_rate_limit_check", lambda *_args, **_kwargs: (lambda f: f))
|
monkeypatch.setattr(wraps, "cloud_edition_billing_rate_limit_check", lambda *_args, **_kwargs: lambda f: f)
|
||||||
|
|
||||||
# Avoid Flask-RESTX route registration side effects during import.
|
# Avoid Flask-RESTX route registration side effects during import.
|
||||||
def _noop_route(*_args, **_kwargs): # type: ignore[override]
|
def _noop_route(*_args, **_kwargs): # type: ignore[override]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
|
from core.app.app_config.features.file_upload.manager import FileUploadConfigManager
|
||||||
from core.file.models import FileTransferMethod, FileUploadConfig, ImageConfig
|
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
||||||
|
from core.workflow.file.models import FileTransferMethod, FileUploadConfig, ImageConfig
|
||||||
|
|
||||||
|
|
||||||
def test_convert_with_vision():
|
def test_convert_with_vision():
|
||||||
|
|||||||
@ -9,8 +9,8 @@ from core.app.apps.base_app_queue_manager import PublishFrom
|
|||||||
from core.app.apps.base_app_runner import AppRunner
|
from core.app.apps.base_app_runner import AppRunner
|
||||||
from core.app.entities.app_invoke_entities import InvokeFrom
|
from core.app.entities.app_invoke_entities import InvokeFrom
|
||||||
from core.app.entities.queue_entities import QueueMessageFileEvent
|
from core.app.entities.queue_entities import QueueMessageFileEvent
|
||||||
from core.file.enums import FileTransferMethod, FileType
|
|
||||||
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
from core.model_runtime.entities.message_entities import ImagePromptMessageContent
|
||||||
|
from core.workflow.file.enums import FileTransferMethod, FileType
|
||||||
from models.enums import CreatorUserRole
|
from models.enums import CreatorUserRole
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
from collections.abc import Mapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
|
|
||||||
from core.app.apps.common.workflow_response_converter import WorkflowResponseConverter
|
from core.app.apps.common.workflow_response_converter import WorkflowResponseConverter
|
||||||
from core.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType
|
|
||||||
from core.variables.segments import ArrayFileSegment, FileSegment
|
from core.variables.segments import ArrayFileSegment, FileSegment
|
||||||
|
from core.workflow.file import FILE_MODEL_IDENTITY, File, FileTransferMethod, FileType
|
||||||
|
|
||||||
|
|
||||||
class TestWorkflowResponseConverterFetchFilesFromVariableValue:
|
class TestWorkflowResponseConverterFetchFilesFromVariableValue:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user