From 014f926e8f2c611031a952a21046f8b2a37a30ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:28:12 +0000 Subject: [PATCH 1/4] Initial plan From c4f59441f82f89b176c3d726daf75c4d2f93fbe4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:36:33 +0000 Subject: [PATCH 2/4] Add graceful error handling for unknown/malformed session events in Python SDK Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com> --- python/copilot/client.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/copilot/client.py b/python/copilot/client.py index 0828e6e..fcab866 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -726,7 +726,11 @@ def handle_notification(method: str, params: dict): session_id = params["sessionId"] event_dict = params["event"] # Convert dict to SessionEvent object - event = session_event_from_dict(event_dict) + try: + event = session_event_from_dict(event_dict) + except Exception: + # Silently ignore unknown/malformed event types for forward compatibility + return with self._sessions_lock: session = self._sessions.get(session_id) if session: @@ -801,7 +805,11 @@ def handle_notification(method: str, params: dict): session_id = params["sessionId"] event_dict = params["event"] # Convert dict to SessionEvent object - event = session_event_from_dict(event_dict) + try: + event = session_event_from_dict(event_dict) + except Exception: + # Silently ignore unknown/malformed event types for forward compatibility + return session = self._sessions.get(session_id) if session: session._dispatch_event(event) From 32d554eadc63eedd58c23f1548d4fb42fd549729 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:38:08 +0000 Subject: [PATCH 3/4] Add unit tests for unknown/malformed session event handling Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com> --- python/test_unknown_events.py | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 python/test_unknown_events.py diff --git a/python/test_unknown_events.py b/python/test_unknown_events.py new file mode 100644 index 0000000..887cc62 --- /dev/null +++ b/python/test_unknown_events.py @@ -0,0 +1,121 @@ +""" +Test that unknown/malformed session events are handled gracefully. +""" + +from datetime import datetime +from uuid import uuid4 + +import pytest + +from copilot import CopilotClient + + +class TestUnknownEventHandling: + """Test graceful handling of unknown and malformed session events.""" + + def test_event_parsing_with_unknown_type(self): + """Verify that unknown event types map to UNKNOWN enum value.""" + from copilot.generated.session_events import SessionEventType, session_event_from_dict + + unknown_event = { + "id": str(uuid4()), + "timestamp": datetime.now().isoformat(), + "parentId": None, + "type": "session.completely_new_event_from_future", + "data": {}, + } + + event = session_event_from_dict(unknown_event) + assert event.type == SessionEventType.UNKNOWN, \ + f"Expected UNKNOWN, got {event.type}" + + def test_malformed_data_raises_exception(self): + """Malformed data should raise exceptions (caught by handler).""" + from copilot.generated.session_events import session_event_from_dict + + # Bad UUID format + malformed_event = { + "id": "not-a-uuid", + "timestamp": datetime.now().isoformat(), + "parentId": None, + "type": "session.start", + "data": {}, + } + + with pytest.raises((ValueError, AssertionError)): + session_event_from_dict(malformed_event) + + # Bad timestamp format + malformed_event2 = { + "id": str(uuid4()), + "timestamp": "invalid-timestamp", + "parentId": None, + "type": "session.start", + "data": {}, + } + + with pytest.raises(Exception): + session_event_from_dict(malformed_event2) + + def test_handler_catches_parsing_exceptions(self): + """The notification handler should catch and ignore parsing exceptions.""" + from copilot.generated.session_events import session_event_from_dict + + events_dispatched = [] + + def mock_dispatch(event): + events_dispatched.append(event) + + # Test 1: Known event should work + known_event = { + "id": str(uuid4()), + "timestamp": datetime.now().isoformat(), + "parentId": None, + "type": "session.start", + "data": {}, + } + + try: + event = session_event_from_dict(known_event) + mock_dispatch(event) + except Exception as e: + pytest.fail(f"Known event should not raise: {e}") + + assert len(events_dispatched) == 1, "Known event should be dispatched" + + # Test 2: Unknown event type should use UNKNOWN enum + unknown_event = { + "id": str(uuid4()), + "timestamp": datetime.now().isoformat(), + "parentId": None, + "type": "session.future_unknown_event", + "data": {}, + } + + try: + event = session_event_from_dict(unknown_event) + mock_dispatch(event) + except Exception as e: + pytest.fail(f"Unknown event should not raise: {e}") + + assert len(events_dispatched) == 2, "Unknown event should be dispatched with UNKNOWN type" + + # Test 3: Malformed event - simulate what the handler does + malformed_event = { + "id": "not-a-valid-uuid", + "timestamp": datetime.now().isoformat(), + "parentId": None, + "type": "session.start", + "data": {}, + } + + # This simulates the try-except in the notification handler + try: + event = session_event_from_dict(malformed_event) + mock_dispatch(event) + except Exception: + # Handler catches and returns, event not dispatched + pass + + assert len(events_dispatched) == 2, "Malformed event should not be dispatched" + From 5b1c1752d5f81ce8d87d7323ecbb66992a231b57 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:40:06 +0000 Subject: [PATCH 4/4] Improve test specificity for exception types Co-authored-by: friggeri <106686+friggeri@users.noreply.github.com> --- python/test_unknown_events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/test_unknown_events.py b/python/test_unknown_events.py index 887cc62..93b20bf 100644 --- a/python/test_unknown_events.py +++ b/python/test_unknown_events.py @@ -54,7 +54,7 @@ def test_malformed_data_raises_exception(self): "data": {}, } - with pytest.raises(Exception): + with pytest.raises((ValueError, TypeError, OSError)): session_event_from_dict(malformed_event2) def test_handler_catches_parsing_exceptions(self):