diff --git a/api/core/agent/base_agent_runner.py b/api/core/agent/base_agent_runner.py index e9bb82d147..cba4659483 100644 --- a/api/core/agent/base_agent_runner.py +++ b/api/core/agent/base_agent_runner.py @@ -529,11 +529,9 @@ class BaseAgentRunner(AppRunner): image_detail_config = file_extra_config.image_config.detail if file_extra_config.image_config else None image_detail_config = image_detail_config or ImagePromptMessageContent.DETAIL.LOW - # History files were validated on upload; replaying does not re-validate. file_objs = file_factory.build_from_message_files( message_files=files, tenant_id=self.tenant_id, - config=None, access_controller=_file_access_controller, ) if not file_objs: diff --git a/api/core/memory/token_buffer_memory.py b/api/core/memory/token_buffer_memory.py index 4786b00630..c41c175cca 100644 --- a/api/core/memory/token_buffer_memory.py +++ b/api/core/memory/token_buffer_memory.py @@ -86,13 +86,10 @@ class TokenBufferMemory: detail = ImagePromptMessageContent.DETAIL.HIGH if file_extra_config and app_record: - # History files were validated on upload; replaying does not re-validate. - # See models/utils/file_input_compat.py for the same pattern. file_objs = [ file_factory.build_from_message_file( message_file=message_file, tenant_id=app_record.tenant_id, - config=None, access_controller=_file_access_controller, ) for message_file in message_files diff --git a/api/factories/file_factory/message_files.py b/api/factories/file_factory/message_files.py index 4b3d514238..27441bdcc1 100644 --- a/api/factories/file_factory/message_files.py +++ b/api/factories/file_factory/message_files.py @@ -1,11 +1,18 @@ -"""Adapters from persisted message files to graph-layer file values.""" +"""Adapters from persisted message files to graph-layer file values. + +Replay paths only: files in conversation history were validated at upload time, +so these helpers deliberately do not accept (or forward) a ``FileUploadConfig`` — +re-validation here would break replays whenever workflow ``file_upload`` config +drifts between rounds. Mirrors ``build_file_from_stored_mapping`` in +``models/utils/file_input_compat.py``. +""" from __future__ import annotations from collections.abc import Sequence from core.app.file_access import FileAccessControllerProtocol -from graphon.file import File, FileBelongsTo, FileTransferMethod, FileUploadConfig +from graphon.file import File, FileBelongsTo, FileTransferMethod from models import MessageFile from .builders import build_from_mapping @@ -15,14 +22,12 @@ def build_from_message_files( *, message_files: Sequence[MessageFile], tenant_id: str, - config: FileUploadConfig | None = None, access_controller: FileAccessControllerProtocol, ) -> Sequence[File]: return [ build_from_message_file( message_file=message_file, tenant_id=tenant_id, - config=config, access_controller=access_controller, ) for message_file in message_files @@ -34,7 +39,6 @@ def build_from_message_file( *, message_file: MessageFile, tenant_id: str, - config: FileUploadConfig | None, access_controller: FileAccessControllerProtocol, ) -> File: mapping = { @@ -54,6 +58,5 @@ def build_from_message_file( return build_from_mapping( mapping=mapping, tenant_id=tenant_id, - config=config, access_controller=access_controller, ) diff --git a/api/tests/unit_tests/core/memory/test_token_buffer_memory.py b/api/tests/unit_tests/core/memory/test_token_buffer_memory.py index 611ca54bce..72c24bda96 100644 --- a/api/tests/unit_tests/core/memory/test_token_buffer_memory.py +++ b/api/tests/unit_tests/core/memory/test_token_buffer_memory.py @@ -198,10 +198,11 @@ class TestBuildPromptMessageWithFiles: assert isinstance(result.content[-1], TextPromptMessageContent) assert result.content[-1].data == "user text" - def test_replay_skips_revalidation_by_passing_config_none(self): + def test_replay_does_not_pass_config_to_file_factory(self): """Replay contract: history files were validated on upload, so this - path must call build_from_message_file with config=None. Reverting - this would re-trigger ENG-244 whenever workflow config drifts.""" + path must not forward a FileUploadConfig. The factory's signature + no longer accepts ``config``; this test guards against a future + regression that re-introduces it.""" conv = _make_conversation(AppMode.CHAT) mem = TokenBufferMemory(conversation=conv, model_instance=_make_model_instance()) @@ -237,7 +238,7 @@ class TestBuildPromptMessageWithFiles: ) mock_build.assert_called_once() - assert mock_build.call_args.kwargs["config"] is None + assert "config" not in mock_build.call_args.kwargs @pytest.mark.parametrize("mode", [AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.COMPLETION]) def test_chat_mode_with_files_assistant_message(self, mode):