diff --git a/api/controllers/openapi/app_run.py b/api/controllers/openapi/app_run.py index 0a1b08ae60..6d9144c70b 100644 --- a/api/controllers/openapi/app_run.py +++ b/api/controllers/openapi/app_run.py @@ -139,6 +139,7 @@ def _run_chat(app: App, caller: Any, payload: AppRunRequest, streaming: bool): def _run_completion(app: App, caller: Any, payload: AppRunRequest, streaming: bool): args = payload.model_dump(exclude_none=True) + # Completion mode disables auto-naming + tolerates absent query (legacy parity). args["auto_generate_name"] = False args.setdefault("query", "") try: @@ -191,7 +192,7 @@ def _run_workflow(app: App, caller: Any, payload: AppRunRequest, streaming: bool return None, WorkflowRunResponse.model_validate(body).model_dump(mode="json") -_DISPATCH: dict[AppMode, Callable[[App, Any, AppRunRequest, bool], tuple[Any, Any]]] = { +_DISPATCH: dict[AppMode, Callable[[App, Any, AppRunRequest, bool], tuple[Any, dict[str, Any] | None]]] = { AppMode.CHAT: _run_chat, AppMode.AGENT_CHAT: _run_chat, AppMode.ADVANCED_CHAT: _run_chat, diff --git a/api/tests/unit_tests/controllers/openapi/test_app_run_dispatch.py b/api/tests/unit_tests/controllers/openapi/test_app_run_dispatch.py index 27e402e4c9..92ddf89573 100644 --- a/api/tests/unit_tests/controllers/openapi/test_app_run_dispatch.py +++ b/api/tests/unit_tests/controllers/openapi/test_app_run_dispatch.py @@ -1,11 +1,12 @@ import pytest -from werkzeug.exceptions import UnprocessableEntity +from werkzeug.exceptions import InternalServerError, UnprocessableEntity from controllers.openapi.app_run import ( _DISPATCH, AppRunRequest, _enforce_chat_constraint, _enforce_workflow_constraint, + _unpack_blocking, ) from models.model import AppMode @@ -23,3 +24,34 @@ def test_chat_constraint_requires_query(): def test_workflow_constraint_rejects_query(): with pytest.raises(UnprocessableEntity, match="query_not_supported_for_workflow"): _enforce_workflow_constraint(AppRunRequest(inputs={}, query="hi")) + + +def test_unpack_blocking_passes_through_mapping(): + assert _unpack_blocking({"a": 1}) == {"a": 1} + + +def test_unpack_blocking_unwraps_tuple(): + assert _unpack_blocking(({"a": 1}, 200)) == {"a": 1} + + +def test_unpack_blocking_rejects_non_mapping(): + with pytest.raises(InternalServerError): + _unpack_blocking("not a mapping") + + +def test_app_run_request_strips_blank_conversation_id(): + payload = AppRunRequest(inputs={}, conversation_id=" ") + assert payload.conversation_id is None + + +def test_app_run_request_rejects_invalid_uuid_conversation_id(): + from pydantic import ValidationError + with pytest.raises(ValidationError, match="conversation_id must be a valid UUID"): + AppRunRequest(inputs={}, conversation_id="not-a-uuid") + + +def test_app_run_request_accepts_valid_uuid_conversation_id(): + import uuid as _uuid + cid = str(_uuid.uuid4()) + payload = AppRunRequest(inputs={}, conversation_id=cid) + assert payload.conversation_id == cid