diff --git a/src/copilot.py b/src/copilot.py index 62d2b8ca2..92c9c0a21 100644 --- a/src/copilot.py +++ b/src/copilot.py @@ -230,7 +230,10 @@ def request_flags(messages) -> tuple: """ msgs = messages or [] last = msgs[-1] if msgs else None - agent = bool(last) and last.get("role") != "user" + # A message element can be a non-dict (clients send `"messages": ["hi"]`); + # the vision loop below already guards each element with isinstance, so do + # the same here rather than call .get() on a bare string. + agent = isinstance(last, dict) and last.get("role") != "user" vision = False for m in msgs: content = m.get("content") if isinstance(m, dict) else None diff --git a/tests/test_copilot.py b/tests/test_copilot.py index 52d530af6..facf9a98f 100644 --- a/tests/test_copilot.py +++ b/tests/test_copilot.py @@ -89,6 +89,18 @@ def test_request_flags_vision(): assert vision is True +def test_request_flags_non_dict_last_message_does_not_crash(): + # A client can send a bare-string (non-dict) last element; before the + # isinstance guard this raised AttributeError on last.get("role"). + assert copilot.request_flags(["hi"]) == (False, False) + assert copilot.request_flags([{"role": "user"}, "trailing"]) == (False, False) + + +def test_request_flags_empty_and_none(): + assert copilot.request_flags([]) == (False, False) + assert copilot.request_flags(None) == (False, False) + + def test_apply_request_headers_mutates(): h = {"X-GitHub-Api-Version": "v"} copilot.apply_request_headers(h, [{"role": "tool", "content": "x"}])