mirror of
https://github.com/langgenius/dify.git
synced 2026-05-10 22:28:55 +08:00
feat: snippets has no envirment variables. Snippet diable start, human_input, knowledge node.
This commit is contained in:
parent
48d4c54762
commit
3865483d95
@ -71,7 +71,6 @@ class SnippetDraftSyncPayload(BaseModel):
|
||||
|
||||
graph: dict[str, Any]
|
||||
hash: str | None = None
|
||||
environment_variables: list[dict[str, Any]] | None = None
|
||||
conversation_variables: list[dict[str, Any]] | None = None
|
||||
input_fields: list[dict[str, Any]] | None = None
|
||||
|
||||
|
||||
@ -135,10 +135,6 @@ class SnippetDraftWorkflowApi(Resource):
|
||||
payload = SnippetDraftSyncPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
try:
|
||||
environment_variables_list = payload.environment_variables or []
|
||||
environment_variables = [
|
||||
variable_factory.build_environment_variable_from_mapping(obj) for obj in environment_variables_list
|
||||
]
|
||||
conversation_variables_list = payload.conversation_variables or []
|
||||
conversation_variables = [
|
||||
variable_factory.build_conversation_variable_from_mapping(obj) for obj in conversation_variables_list
|
||||
@ -149,12 +145,13 @@ class SnippetDraftWorkflowApi(Resource):
|
||||
graph=payload.graph,
|
||||
unique_hash=payload.hash,
|
||||
account=current_user,
|
||||
environment_variables=environment_variables,
|
||||
conversation_variables=conversation_variables,
|
||||
input_fields=payload.input_fields,
|
||||
)
|
||||
except WorkflowHashNotEqualError:
|
||||
raise DraftWorkflowNotSync()
|
||||
except ValueError as e:
|
||||
return {"message": str(e)}, 400
|
||||
|
||||
return {
|
||||
"result": "success",
|
||||
|
||||
@ -22,7 +22,7 @@ from models import Account
|
||||
from models.snippet import CustomizedSnippet, SnippetType
|
||||
from models.workflow import Workflow
|
||||
from services.plugin.dependencies_analysis import DependenciesAnalysisService
|
||||
from services.snippet_service import SnippetService
|
||||
from services.snippet_service import SNIPPET_FORBIDDEN_NODE_TYPES, SnippetService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -32,13 +32,6 @@ IMPORT_INFO_REDIS_EXPIRY = 10 * 60 # 10 minutes
|
||||
DSL_MAX_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
CURRENT_DSL_VERSION = "0.1.0"
|
||||
|
||||
# List of node types that are not allowed in snippets
|
||||
FORBIDDEN_NODE_TYPES = [
|
||||
BuiltinNodeTypes.START,
|
||||
BuiltinNodeTypes.HUMAN_INPUT,
|
||||
]
|
||||
|
||||
|
||||
class ImportMode(StrEnum):
|
||||
YAML_CONTENT = "yaml-content"
|
||||
YAML_URL = "yaml-url"
|
||||
@ -230,7 +223,7 @@ class SnippetDslService:
|
||||
if not node_data:
|
||||
continue
|
||||
node_type = node_data.get("type", "")
|
||||
if node_type in FORBIDDEN_NODE_TYPES:
|
||||
if node_type in SNIPPET_FORBIDDEN_NODE_TYPES:
|
||||
forbidden_nodes_found.append(node_type)
|
||||
|
||||
if forbidden_nodes_found:
|
||||
@ -427,12 +420,8 @@ class SnippetDslService:
|
||||
# Create or update draft workflow
|
||||
if workflow_data:
|
||||
graph = workflow_data.get("graph", {})
|
||||
environment_variables_list = workflow_data.get("environment_variables", [])
|
||||
conversation_variables_list = workflow_data.get("conversation_variables", [])
|
||||
|
||||
environment_variables = [
|
||||
variable_factory.build_environment_variable_from_mapping(obj) for obj in environment_variables_list
|
||||
]
|
||||
conversation_variables = [
|
||||
variable_factory.build_conversation_variable_from_mapping(obj) for obj in conversation_variables_list
|
||||
]
|
||||
@ -447,7 +436,6 @@ class SnippetDslService:
|
||||
graph=graph,
|
||||
unique_hash=unique_hash,
|
||||
account=account,
|
||||
environment_variables=environment_variables,
|
||||
conversation_variables=conversation_variables,
|
||||
input_fields=input_fields,
|
||||
)
|
||||
@ -494,6 +482,8 @@ class SnippetDslService:
|
||||
"""
|
||||
workflow_dict = workflow.to_dict(include_secret=include_secret)
|
||||
# Filter workspace related data from nodes
|
||||
workflow_dict["environment_variables"] = []
|
||||
|
||||
for node in workflow_dict.get("graph", {}).get("nodes", []):
|
||||
node_data = node.get("data", {})
|
||||
if not node_data:
|
||||
|
||||
@ -9,7 +9,7 @@ from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from core.workflow.node_factory import LATEST_VERSION, NODE_TYPE_CLASSES_MAPPING
|
||||
from extensions.ext_database import db
|
||||
from graphon.enums import NodeType
|
||||
from graphon.enums import BuiltinNodeTypes, NodeType
|
||||
from graphon.variables.variables import VariableBase
|
||||
from libs.infinite_scroll_pagination import InfiniteScrollPagination
|
||||
from models import Account
|
||||
@ -26,6 +26,15 @@ from services.errors.app import WorkflowHashNotEqualError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Node types not allowed in snippet workflows (sync, publish, DSL import).
|
||||
SNIPPET_FORBIDDEN_NODE_TYPES: frozenset[str] = frozenset(
|
||||
{
|
||||
BuiltinNodeTypes.START,
|
||||
BuiltinNodeTypes.HUMAN_INPUT,
|
||||
BuiltinNodeTypes.KNOWLEDGE_RETRIEVAL,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class SnippetService:
|
||||
"""Service for managing customized snippets."""
|
||||
@ -39,6 +48,29 @@ class SnippetService:
|
||||
)
|
||||
self._workflow_run_repo = DifyAPIRepositoryFactory.create_api_workflow_run_repository(session_maker)
|
||||
|
||||
@staticmethod
|
||||
def validate_snippet_graph_forbidden_nodes(graph: Mapping[str, Any]) -> None:
|
||||
"""Reject graphs that contain node types not allowed in snippets."""
|
||||
nodes = graph.get("nodes") or []
|
||||
disallowed: list[tuple[str, str]] = []
|
||||
for node in nodes:
|
||||
if not isinstance(node, dict):
|
||||
continue
|
||||
node_data = node.get("data") or {}
|
||||
node_type = node_data.get("type")
|
||||
if not isinstance(node_type, str):
|
||||
continue
|
||||
if node_type in SNIPPET_FORBIDDEN_NODE_TYPES:
|
||||
node_id = node.get("id")
|
||||
disallowed.append((str(node_id) if node_id is not None else "?", node_type))
|
||||
if not disallowed:
|
||||
return
|
||||
detail = ", ".join(f"{nid}:{t}" for nid, t in disallowed)
|
||||
raise ValueError(
|
||||
"Snippet workflow cannot contain start, human-input, or knowledge-retrieval nodes. "
|
||||
f"Found: {detail}"
|
||||
)
|
||||
|
||||
# --- CRUD Operations ---
|
||||
|
||||
@staticmethod
|
||||
@ -276,23 +308,25 @@ class SnippetService:
|
||||
graph: dict,
|
||||
unique_hash: str | None,
|
||||
account: Account,
|
||||
environment_variables: Sequence[VariableBase],
|
||||
conversation_variables: Sequence[VariableBase],
|
||||
input_fields: list[dict] | None = None,
|
||||
) -> Workflow:
|
||||
"""
|
||||
Sync draft workflow for snippet.
|
||||
|
||||
Snippet workflows do not persist environment variables (always empty).
|
||||
|
||||
:param snippet: CustomizedSnippet instance
|
||||
:param graph: Workflow graph configuration
|
||||
:param unique_hash: Hash for conflict detection
|
||||
:param account: Account making the change
|
||||
:param environment_variables: Environment variables
|
||||
:param conversation_variables: Conversation variables
|
||||
:param input_fields: Input fields for snippet
|
||||
:return: Synced Workflow
|
||||
:raises WorkflowHashNotEqualError: If hash mismatch
|
||||
"""
|
||||
SnippetService.validate_snippet_graph_forbidden_nodes(graph)
|
||||
|
||||
workflow = self.get_draft_workflow(snippet=snippet)
|
||||
|
||||
if workflow and workflow.unique_hash != unique_hash:
|
||||
@ -308,7 +342,7 @@ class SnippetService:
|
||||
version="draft",
|
||||
graph=json.dumps(graph),
|
||||
created_by=account.id,
|
||||
environment_variables=environment_variables,
|
||||
environment_variables=[],
|
||||
conversation_variables=conversation_variables,
|
||||
)
|
||||
db.session.add(workflow)
|
||||
@ -318,7 +352,7 @@ class SnippetService:
|
||||
workflow.graph = json.dumps(graph)
|
||||
workflow.updated_by = account.id
|
||||
workflow.updated_at = datetime.now(UTC).replace(tzinfo=None)
|
||||
workflow.environment_variables = environment_variables
|
||||
workflow.environment_variables = []
|
||||
workflow.conversation_variables = conversation_variables
|
||||
|
||||
# Update snippet's input_fields if provided
|
||||
@ -356,6 +390,8 @@ class SnippetService:
|
||||
if not draft_workflow:
|
||||
raise ValueError("No valid workflow found.")
|
||||
|
||||
SnippetService.validate_snippet_graph_forbidden_nodes(draft_workflow.graph_dict)
|
||||
|
||||
# Create new published workflow
|
||||
workflow = Workflow.new(
|
||||
tenant_id=snippet.tenant_id,
|
||||
@ -365,8 +401,9 @@ class SnippetService:
|
||||
graph=draft_workflow.graph,
|
||||
features=draft_workflow.features,
|
||||
created_by=account.id,
|
||||
environment_variables=draft_workflow.environment_variables,
|
||||
environment_variables=[],
|
||||
conversation_variables=draft_workflow.conversation_variables,
|
||||
rag_pipeline_variables=draft_workflow.rag_pipeline_variables,
|
||||
marked_name="",
|
||||
marked_comment="",
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user