@@ -389,3 +389,112 @@ async def track_load_tools(*args, **kwargs):
389389
390390 # Verify add_consumer was called with the registry ID
391391 mock_provider .add_consumer .assert_called_once_with (registry ._registry_id )
392+
393+
394+ def test_tool_registry_replace_existing_tool ():
395+ """Test replacing an existing tool."""
396+ old_tool = MagicMock ()
397+ old_tool .tool_name = "my_tool"
398+ old_tool .is_dynamic = False
399+ old_tool .supports_hot_reload = False
400+
401+ new_tool = MagicMock ()
402+ new_tool .tool_name = "my_tool"
403+ new_tool .is_dynamic = False
404+
405+ registry = ToolRegistry ()
406+ registry .register_tool (old_tool )
407+ registry .replace ("my_tool" , new_tool )
408+
409+ assert registry .registry ["my_tool" ] == new_tool
410+
411+
412+ def test_tool_registry_replace_nonexistent_tool ():
413+ """Test replacing a tool that doesn't exist raises ValueError."""
414+ new_tool = MagicMock ()
415+ new_tool .tool_name = "my_tool"
416+
417+ registry = ToolRegistry ()
418+
419+ with pytest .raises (ValueError , match = "Cannot replace tool 'my_tool' - tool does not exist" ):
420+ registry .replace ("my_tool" , new_tool )
421+
422+
423+ def test_tool_registry_replace_with_different_name ():
424+ """Test replacing with different name raises ValueError."""
425+ old_tool = MagicMock ()
426+ old_tool .tool_name = "old_tool"
427+ old_tool .is_dynamic = False
428+ old_tool .supports_hot_reload = False
429+
430+ new_tool = MagicMock ()
431+ new_tool .tool_name = "new_tool"
432+
433+ registry = ToolRegistry ()
434+ registry .register_tool (old_tool )
435+
436+ with pytest .raises (ValueError , match = "Tool names must match" ):
437+ registry .replace ("old_tool" , new_tool )
438+
439+
440+ def test_tool_registry_replace_dynamic_tool ():
441+ """Test replacing a dynamic tool updates both registries."""
442+ old_tool = MagicMock ()
443+ old_tool .tool_name = "dynamic_tool"
444+ old_tool .is_dynamic = True
445+ old_tool .supports_hot_reload = True
446+
447+ new_tool = MagicMock ()
448+ new_tool .tool_name = "dynamic_tool"
449+ new_tool .is_dynamic = True
450+
451+ registry = ToolRegistry ()
452+ registry .register_tool (old_tool )
453+ registry .replace ("dynamic_tool" , new_tool )
454+
455+ assert registry .registry ["dynamic_tool" ] == new_tool
456+ assert registry .dynamic_tools ["dynamic_tool" ] == new_tool
457+
458+
459+ def test_tool_registry_replace_dynamic_with_non_dynamic ():
460+ """Test replacing a dynamic tool with non-dynamic tool removes from dynamic_tools."""
461+ old_tool = MagicMock ()
462+ old_tool .tool_name = "my_tool"
463+ old_tool .is_dynamic = True
464+ old_tool .supports_hot_reload = True
465+
466+ new_tool = MagicMock ()
467+ new_tool .tool_name = "my_tool"
468+ new_tool .is_dynamic = False
469+
470+ registry = ToolRegistry ()
471+ registry .register_tool (old_tool )
472+
473+ assert "my_tool" in registry .dynamic_tools
474+
475+ registry .replace ("my_tool" , new_tool )
476+
477+ assert registry .registry ["my_tool" ] == new_tool
478+ assert "my_tool" not in registry .dynamic_tools
479+
480+
481+ def test_tool_registry_replace_non_dynamic_with_dynamic ():
482+ """Test replacing a non-dynamic tool with dynamic tool adds to dynamic_tools."""
483+ old_tool = MagicMock ()
484+ old_tool .tool_name = "my_tool"
485+ old_tool .is_dynamic = False
486+ old_tool .supports_hot_reload = False
487+
488+ new_tool = MagicMock ()
489+ new_tool .tool_name = "my_tool"
490+ new_tool .is_dynamic = True
491+
492+ registry = ToolRegistry ()
493+ registry .register_tool (old_tool )
494+
495+ assert "my_tool" not in registry .dynamic_tools
496+
497+ registry .replace ("my_tool" , new_tool )
498+
499+ assert registry .registry ["my_tool" ] == new_tool
500+ assert registry .dynamic_tools ["my_tool" ] == new_tool
0 commit comments