diff --git a/api/app/core/error_codes.py b/api/app/core/error_codes.py index 3feae4f6..41f58734 100644 --- a/api/app/core/error_codes.py +++ b/api/app/core/error_codes.py @@ -19,6 +19,7 @@ class BizCode(IntEnum): TENANT_NOT_FOUND = 3002 WORKSPACE_NO_ACCESS = 3003 WORKSPACE_INVITE_NOT_FOUND = 3004 + WORKSPACE_ACCESS_DENIED = 3005 # API Key 管理(3xxx) API_KEY_NOT_FOUND = 3007 API_KEY_DUPLICATE_NAME = 3008 @@ -113,6 +114,8 @@ HTTP_MAPPING = { BizCode.FORBIDDEN: 403, BizCode.TENANT_NOT_FOUND: 400, BizCode.WORKSPACE_NO_ACCESS: 403, + BizCode.WORKSPACE_INVITE_NOT_FOUND: 400, + BizCode.WORKSPACE_ACCESS_DENIED: 403, BizCode.NOT_FOUND: 400, BizCode.USER_NOT_FOUND: 200, BizCode.WORKSPACE_NOT_FOUND: 400, diff --git a/api/app/core/workflow/adapters/dify/converter.py b/api/app/core/workflow/adapters/dify/converter.py index f0cb32dd..41459d8d 100644 --- a/api/app/core/workflow/adapters/dify/converter.py +++ b/api/app/core/workflow/adapters/dify/converter.py @@ -496,7 +496,23 @@ class DifyConverter(BaseConverter): def convert_assigner_node_config(self, node: dict) -> dict: node_data = node["data"] assignments = [] - for assignment in node_data["items"]: + + # Support both formats: + # 1. New format: node_data["items"] list + # 2. Flat format: assigned_variable_selector + input_variable_selector + write_mode + if "items" in node_data: + raw_items = node_data["items"] + elif "assigned_variable_selector" in node_data and "input_variable_selector" in node_data: + raw_items = [{ + "variable_selector": node_data["assigned_variable_selector"], + "value": node_data["input_variable_selector"], + "input_type": ValueInputType.VARIABLE, + "operation": node_data.get("write_mode", "over-write"), + }] + else: + raw_items = [] + + for assignment in raw_items: if assignment.get("operation") is None or assignment.get("value") is None: continue assignments.append( diff --git a/api/app/core/workflow/nodes/list_operator/config.py b/api/app/core/workflow/nodes/list_operator/config.py index c178ec59..6fde6a57 100644 --- a/api/app/core/workflow/nodes/list_operator/config.py +++ b/api/app/core/workflow/nodes/list_operator/config.py @@ -1,5 +1,5 @@ from typing import Any -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from app.core.workflow.nodes.base_config import BaseNodeConfig from app.core.workflow.nodes.enums import ComparisonOperator @@ -31,6 +31,11 @@ class ExtractConfig(BaseModel): enabled: bool = False serial: str = "1" # 1-based index string, e.g. "1" = first + @field_validator("serial", mode="before") + @classmethod + def coerce_serial(cls, v): + return str(v) + class ListOperatorNodeConfig(BaseNodeConfig): """ diff --git a/api/app/core/workflow/utils/file_processor.py b/api/app/core/workflow/utils/file_processor.py index 9b07d2e9..0bedf9a7 100644 --- a/api/app/core/workflow/utils/file_processor.py +++ b/api/app/core/workflow/utils/file_processor.py @@ -91,7 +91,7 @@ async def fetch_remote_file_meta( """ import httpx - name = size = mime_type = extension = None + name = extension = None try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.head(url, follow_redirects=True) diff --git a/api/app/services/workflow_service.py b/api/app/services/workflow_service.py index 5fccee54..b771c639 100644 --- a/api/app/services/workflow_service.py +++ b/api/app/services/workflow_service.py @@ -25,7 +25,7 @@ from app.repositories.workflow_repository import ( WorkflowExecutionRepository, WorkflowNodeExecutionRepository ) -from app.schemas import DraftRunRequest, FileInput +from app.schemas import DraftRunRequest, FileInput, FileType from app.services.conversation_service import ConversationService from app.services.multi_agent_service import convert_uuids_to_str from app.services.multimodal_service import MultimodalService @@ -466,7 +466,7 @@ class WorkflowService: if not isinstance(item, dict) or item.get("is_file"): return item transfer_method = item.get("transfer_method", "remote_url") - file_type = item.get("type", "document") + file_type = FileType.trans(item.get("type", "document")) origin_file_type = item.get("file_type") or file_type if transfer_method == "remote_url": url = item.get("url", "")