@@ -939,6 +939,88 @@ def test_create_local_tool_knowledge_base_with_display_name_map(nexent_agent_ins
939939 assert result .rerank_model == "mock_rerank_model"
940940
941941
942+ def test_create_local_tool_knowledge_base_with_document_paths_from_metadata (nexent_agent_instance ):
943+ """KnowledgeBaseSearchTool should receive document_paths from metadata via set_document_paths.
944+
945+ The `document_paths` parameter is declared with `exclude=True` so it must not
946+ be passed to __init__. Instead it must be forwarded to `set_document_paths`
947+ on the instance, sourced from `tool_config.metadata`. This guards against
948+ the FieldInfo-iteration regression reported when document_paths is unset.
949+ """
950+ mock_kb_tool_class = MagicMock ()
951+ mock_kb_tool_instance = MagicMock ()
952+ mock_kb_tool_class .return_value = mock_kb_tool_instance
953+
954+ document_paths = ["s3://bucket/doc1.txt" , "s3://bucket/doc2.txt" ]
955+
956+ tool_config = ToolConfig (
957+ class_name = "KnowledgeBaseSearchTool" ,
958+ name = "knowledge_base_search" ,
959+ description = "desc" ,
960+ inputs = "{}" ,
961+ output_type = "string" ,
962+ params = {"top_k" : 5 , "index_names" : ["kb1" ]},
963+ source = "local" ,
964+ metadata = {
965+ "vdb_core" : "mock_vdb_core" ,
966+ "embedding_model" : "mock_embedding_model" ,
967+ "document_paths" : document_paths ,
968+ },
969+ )
970+
971+ original_value = nexent_agent .__dict__ .get ("KnowledgeBaseSearchTool" )
972+ nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ] = mock_kb_tool_class
973+
974+ try :
975+ nexent_agent_instance .create_local_tool (tool_config )
976+ finally :
977+ if original_value is not None :
978+ nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ] = original_value
979+ elif "KnowledgeBaseSearchTool" in nexent_agent .__dict__ :
980+ del nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ]
981+
982+ # document_paths is excluded and must not be forwarded to __init__.
983+ init_kwargs = mock_kb_tool_class .call_args .kwargs
984+ assert "document_paths" not in init_kwargs
985+ # It must instead be applied via set_document_paths on the instance.
986+ mock_kb_tool_instance .set_document_paths .assert_called_once_with (document_paths )
987+
988+
989+ def test_create_local_tool_knowledge_base_without_metadata_calls_set_document_paths_none (nexent_agent_instance ):
990+ """When metadata lacks document_paths, set_document_paths(None) must still be invoked.
991+
992+ Ensures the tool's internal filter is explicitly reset to None rather than
993+ left as a stale FieldInfo default from the smolagents wrapper.
994+ """
995+ mock_kb_tool_class = MagicMock ()
996+ mock_kb_tool_instance = MagicMock ()
997+ mock_kb_tool_class .return_value = mock_kb_tool_instance
998+
999+ tool_config = ToolConfig (
1000+ class_name = "KnowledgeBaseSearchTool" ,
1001+ name = "knowledge_base_search" ,
1002+ description = "desc" ,
1003+ inputs = "{}" ,
1004+ output_type = "string" ,
1005+ params = {"top_k" : 5 , "index_names" : ["kb1" ]},
1006+ source = "local" ,
1007+ metadata = None ,
1008+ )
1009+
1010+ original_value = nexent_agent .__dict__ .get ("KnowledgeBaseSearchTool" )
1011+ nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ] = mock_kb_tool_class
1012+
1013+ try :
1014+ nexent_agent_instance .create_local_tool (tool_config )
1015+ finally :
1016+ if original_value is not None :
1017+ nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ] = original_value
1018+ elif "KnowledgeBaseSearchTool" in nexent_agent .__dict__ :
1019+ del nexent_agent .__dict__ ["KnowledgeBaseSearchTool" ]
1020+
1021+ mock_kb_tool_instance .set_document_paths .assert_called_once_with (None )
1022+
1023+
9421024def test_create_local_tool_knowledge_base_with_empty_display_name_map (nexent_agent_instance ):
9431025 """Test KnowledgeBaseSearchTool creation handles empty display_name_to_index_map."""
9441026 mock_kb_tool_class = MagicMock ()
0 commit comments