@@ -644,6 +644,56 @@ def test_get_response_tool_file_search_attributes(self):
644644 assert "max_num_results" in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
645645 assert "ranking_options" in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
646646
647+ def test_get_response_tool_web_search_attributes_with_none_user_location (self ):
648+ """Test extraction of attributes from web search tool when user_location is None"""
649+ # Create a mock web search tool with user_location=None (optional field default)
650+ web_search_tool = MockWebSearchTool (
651+ {"type" : "web_search_preview" , "search_context_size" : "medium" , "user_location" : None }
652+ )
653+
654+ # Call the function directly - should NOT raise AttributeError
655+ with patch ("agentops.instrumentation.providers.openai.attributes.response.WebSearchTool" , MockWebSearchTool ):
656+ result = get_response_tool_web_search_attributes (web_search_tool , 0 )
657+
658+ # Verify attributes - should still work without user_location
659+ assert isinstance (result , dict )
660+ assert MessageAttributes .TOOL_CALL_NAME .format (i = 0 ) in result
661+ assert result [MessageAttributes .TOOL_CALL_NAME .format (i = 0 )] == "web_search_preview"
662+ assert MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 ) in result
663+ # user_location should NOT be in parameters since it was None
664+ assert "user_location" not in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
665+ # search_context_size should still be present
666+ assert "search_context_size" in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
667+
668+ def test_get_response_tool_file_search_attributes_with_none_filters_and_ranking (self ):
669+ """Test extraction of attributes from file search tool when filters and ranking_options are None"""
670+ # Create a mock file search tool with filters=None and ranking_options=None (optional defaults)
671+ file_search_tool = MockFileSearchTool (
672+ {
673+ "type" : "file_search" ,
674+ "vector_store_ids" : ["store_123" ],
675+ "filters" : None ,
676+ "max_num_results" : 10 ,
677+ "ranking_options" : None ,
678+ }
679+ )
680+
681+ # Call the function directly - should NOT raise AttributeError
682+ with patch ("agentops.instrumentation.providers.openai.attributes.response.FileSearchTool" , MockFileSearchTool ):
683+ result = get_response_tool_file_search_attributes (file_search_tool , 0 )
684+
685+ # Verify attributes - should still work without filters/ranking_options
686+ assert isinstance (result , dict )
687+ assert MessageAttributes .TOOL_CALL_TYPE .format (i = 0 ) in result
688+ assert result [MessageAttributes .TOOL_CALL_TYPE .format (i = 0 )] == "file_search"
689+ assert MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 ) in result
690+ # filters and ranking_options should NOT be in parameters since they were None
691+ assert "filters" not in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
692+ assert "ranking_options" not in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
693+ # vector_store_ids and max_num_results should still be present
694+ assert "vector_store_ids" in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
695+ assert "max_num_results" in result [MessageAttributes .TOOL_CALL_ARGUMENTS .format (i = 0 )]
696+
647697 def test_get_response_tool_computer_attributes (self ):
648698 """Test extraction of attributes from computer tool"""
649699 # Create a mock computer tool
0 commit comments