async def test_no_duplicate_file_embedding_during_continuation(
        self, mock_resolve_path, mock_add_turn, mock_get_thread
    ):
        """Test that files already embedded in conversation history are not re-embedded"""

        # Mock file resolution to allow our test files
        def mock_resolve(path_str):
            from pathlib import Path

            return Path(path_str)  # Just return as-is for test files

        mock_resolve_path.side_effect = mock_resolve

        # Create a thread context with previous turns including files
        _thread_context = ThreadContext(
            thread_id="test-duplicate-files-id",
            created_at="2023-01-01T00:00:00Z",
            last_updated_at="2023-01-01T00:02:00Z",
            tool_name="analyze",
            turns=[
                ConversationTurn(
                    role="assistant",
                    content="I've analyzed the authentication module.",
                    timestamp="2023-01-01T00:01:00Z",
                    tool_name="analyze",
                    files=["/src/auth.py", "/src/security.py"],  # These files were already analyzed
                ),
                ConversationTurn(
                    role="assistant",
                    content="Found security issues in the auth system.",
                    timestamp="2023-01-01T00:02:00Z",
                    tool_name="codereview",
                    files=["/src/auth.py", "/tests/test_auth.py"],  # auth.py referenced again + new file
                ),
            ],
            initial_context={"question": "Analyze authentication security"},
        )

        # Mock get_thread to return our test context
        mock_get_thread.return_value = _thread_context
        mock_add_turn.return_value = True

        # Mock the model to capture what prompt it receives
        captured_prompt = None

        with patch.object(self.tool, "create_model") as mock_create_model:
            mock_model = Mock()
            mock_response = Mock()
            mock_response.candidates = [
                Mock(
                    content=Mock(parts=[Mock(text="Analysis of new files complete")]),
                    finish_reason="STOP",
                )
            ]

            def capture_prompt(prompt):
                nonlocal captured_prompt
                captured_prompt = prompt
                return mock_response

            mock_model.generate_content.side_effect = capture_prompt
            mock_create_model.return_value = mock_model

            # Mock read_files to simulate file existence and capture its calls
            with patch("tools.base.read_files") as mock_read_files:
                # When the tool processes the new files, it should only read '/src/utils.py'
                mock_read_files.return_value = "--- /src/utils.py ---\ncontent of utils"

                # Execute tool with continuation_id and mix of already-referenced and new files
                arguments = {
                    "prompt": "Now check the utility functions too",
                    "continuation_id": "test-duplicate-files-id",
                    "files": ["/src/auth.py", "/src/utils.py"],  # auth.py already in history, utils.py is new
                }
                response = await self.tool.execute(arguments)

                # Verify response succeeded
                response_data = json.loads(response[0].text)
                assert response_data["status"] == "success"

                # Verify the prompt structure
                assert captured_prompt is not None

                # After fixing the duplication bug, conversation history (including file embedding)
                # is no longer added by tools/base.py - it's handled by server.py
                # This test verifies the file filtering logic still works correctly

                # The current request should still be processed normally
                assert "Now check the utility functions too" in captured_prompt
                assert "Files in current request: /src/auth.py, /src/utils.py" in captured_prompt

                # Most importantly, verify that the file filtering logic works correctly
                # even though conversation history isn't built by tools/base.py anymore
                with patch.object(self.tool, "get_conversation_embedded_files") as mock_get_embedded:
                    # Mock that certain files are already embedded
                    mock_get_embedded.return_value = ["/src/auth.py", "/src/security.py", "/tests/test_auth.py"]

                    # Test the filtering logic directly
                    new_files = self.tool.filter_new_files(["/src/auth.py", "/src/utils.py"], "test-duplicate-files-id")
                    assert new_files == ["/src/utils.py"]  # Only the new file should remain

                    # Verify get_conversation_embedded_files was called correctly
                    mock_get_embedded.assert_called_with("test-duplicate-files-id")
Test that files already embedded in conversation history are not re-embedded
tests/test_conversation_history_bug.py