test_invalid_context_length_warning.py
1 """Tests that invalid context_length values in config produce visible warnings.""" 2 3 from unittest.mock import patch, MagicMock, call 4 5 6 def _build_agent(model_cfg, custom_providers=None, model="anthropic/claude-opus-4.6"): 7 """Build an AIAgent with the given model config.""" 8 cfg = {"model": model_cfg} 9 if custom_providers is not None: 10 cfg["custom_providers"] = custom_providers 11 12 base_url = model_cfg.get("base_url", "") 13 14 with ( 15 patch("hermes_cli.config.load_config", return_value=cfg), 16 patch("agent.model_metadata.get_model_context_length", return_value=128_000), 17 patch("run_agent.get_tool_definitions", return_value=[]), 18 patch("run_agent.check_toolset_requirements", return_value={}), 19 patch("run_agent.OpenAI"), 20 ): 21 from run_agent import AIAgent 22 23 agent = AIAgent( 24 model=model, 25 api_key="test-key-1234567890", 26 base_url=base_url, 27 quiet_mode=True, 28 skip_context_files=True, 29 skip_memory=True, 30 ) 31 return agent 32 33 34 def test_valid_integer_context_length_no_warning(): 35 """Plain integer context_length should work silently.""" 36 with patch("run_agent.logger") as mock_logger: 37 agent = _build_agent({"default": "gpt5.4", "provider": "custom", 38 "base_url": "http://localhost:4000/v1", 39 "context_length": 256000}) 40 assert agent._config_context_length == 256000 41 # No warning about invalid context_length 42 for c in mock_logger.warning.call_args_list: 43 assert "Invalid" not in str(c) 44 45 46 def test_string_k_suffix_context_length_warns(): 47 """context_length: '256K' should warn the user clearly.""" 48 with patch("run_agent.logger") as mock_logger: 49 agent = _build_agent({"default": "gpt5.4", "provider": "custom", 50 "base_url": "http://localhost:4000/v1", 51 "context_length": "256K"}) 52 assert agent._config_context_length is None 53 # Should have warned 54 warning_calls = [c for c in mock_logger.warning.call_args_list 55 if "Invalid" in str(c) and "256K" in str(c)] 56 assert len(warning_calls) == 1 57 assert "plain integer" in str(warning_calls[0]) 58 59 60 def test_string_numeric_context_length_works(): 61 """context_length: '256000' (string) should parse fine via int().""" 62 with patch("run_agent.logger") as mock_logger: 63 agent = _build_agent({"default": "gpt5.4", "provider": "custom", 64 "base_url": "http://localhost:4000/v1", 65 "context_length": "256000"}) 66 assert agent._config_context_length == 256000 67 for c in mock_logger.warning.call_args_list: 68 assert "Invalid" not in str(c) 69 70 71 def test_custom_providers_invalid_context_length_warns(): 72 """Invalid context_length in custom_providers should warn.""" 73 custom_providers = [ 74 { 75 "name": "LiteLLM", 76 "base_url": "http://localhost:4000/v1", 77 "models": { 78 "gpt5.4": {"context_length": "256K"} 79 }, 80 } 81 ] 82 with patch("run_agent.logger") as mock_logger: 83 agent = _build_agent( 84 {"default": "gpt5.4", "provider": "custom", 85 "base_url": "http://localhost:4000/v1"}, 86 custom_providers=custom_providers, 87 model="gpt5.4", 88 ) 89 warning_calls = [c for c in mock_logger.warning.call_args_list 90 if "Invalid" in str(c) and "256K" in str(c)] 91 assert len(warning_calls) == 1 92 assert "custom_providers" in str(warning_calls[0]) 93 94 95 def test_custom_providers_valid_context_length(): 96 """Valid integer in custom_providers should work silently.""" 97 custom_providers = [ 98 { 99 "name": "LiteLLM", 100 "base_url": "http://localhost:4000/v1", 101 "models": { 102 "gpt5.4": {"context_length": 256000} 103 }, 104 } 105 ] 106 with patch("run_agent.logger") as mock_logger: 107 agent = _build_agent( 108 {"default": "gpt5.4", "provider": "custom", 109 "base_url": "http://localhost:4000/v1"}, 110 custom_providers=custom_providers, 111 model="gpt5.4", 112 ) 113 for c in mock_logger.warning.call_args_list: 114 assert "Invalid" not in str(c)