test_copilot_native_vision_headers.py
1 from unittest.mock import MagicMock, patch 2 3 from run_agent import AIAgent 4 5 6 def _make_copilot_agent(): 7 with patch("run_agent.OpenAI") as mock_openai: 8 mock_openai.return_value = MagicMock() 9 agent = AIAgent( 10 api_key="gh-token", 11 base_url="https://api.githubcopilot.com", 12 provider="copilot", 13 model="gpt-5.4", 14 quiet_mode=True, 15 skip_context_files=True, 16 skip_memory=True, 17 ) 18 return agent 19 20 21 def test_request_client_adds_copilot_vision_header_for_native_image_payload(): 22 agent = _make_copilot_agent() 23 built_kwargs = [] 24 25 def fake_create(kwargs, *, reason, shared): 26 built_kwargs.append(dict(kwargs)) 27 return MagicMock() 28 29 api_kwargs = { 30 "model": "gpt-5.4", 31 "messages": [ 32 { 33 "role": "user", 34 "content": [ 35 {"type": "text", "text": "What is in this image?"}, 36 {"type": "image_url", "image_url": {"url": "data:image/png;base64,abc"}}, 37 ], 38 } 39 ], 40 } 41 42 agent.client = object() 43 with patch.object(agent, "_is_openai_client_closed", return_value=False), patch.object( 44 agent, "_create_openai_client", side_effect=fake_create 45 ): 46 agent._create_request_openai_client(reason="test", api_kwargs=api_kwargs) 47 48 headers = built_kwargs[-1]["default_headers"] 49 assert headers["Copilot-Vision-Request"] == "true" 50 51 52 def test_request_client_leaves_copilot_text_requests_without_vision_header(): 53 agent = _make_copilot_agent() 54 built_kwargs = [] 55 56 def fake_create(kwargs, *, reason, shared): 57 built_kwargs.append(dict(kwargs)) 58 return MagicMock() 59 60 api_kwargs = {"model": "gpt-5.4", "messages": [{"role": "user", "content": "hello"}]} 61 62 agent.client = object() 63 with patch.object(agent, "_is_openai_client_closed", return_value=False), patch.object( 64 agent, "_create_openai_client", side_effect=fake_create 65 ): 66 agent._create_request_openai_client(reason="test", api_kwargs=api_kwargs) 67 68 headers = built_kwargs[-1]["default_headers"] 69 assert "Copilot-Vision-Request" not in headers 70 71 72 def test_request_client_does_not_add_vision_header_after_non_vision_fallback(): 73 agent = _make_copilot_agent() 74 built_kwargs = [] 75 76 def fake_create(kwargs, *, reason, shared): 77 built_kwargs.append(dict(kwargs)) 78 return MagicMock() 79 80 # This is the shape after _prepare_messages_for_non_vision_model has 81 # replaced image parts with text, so Copilot should not get the vision route. 82 api_kwargs = { 83 "model": "gpt-5.4", 84 "messages": [ 85 {"role": "user", "content": "[user image: a dog]\n\nWhat is in this image?"} 86 ], 87 } 88 89 agent.client = object() 90 with patch.object(agent, "_is_openai_client_closed", return_value=False), patch.object( 91 agent, "_create_openai_client", side_effect=fake_create 92 ): 93 agent._create_request_openai_client(reason="test", api_kwargs=api_kwargs) 94 95 headers = built_kwargs[-1]["default_headers"] 96 assert "Copilot-Vision-Request" not in headers