You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Copilot backend in skillopt_sleep crashes when an assistant.message event has non-dict data #231
CopilotCliBackend._parse_jsonl_response in skillopt_sleep/backend.py assumes the data field of an assistant.message event is an object:
content= (obj.get("data") or {}).get("content")
If data is a string, a number, or a non-empty list, this raises AttributeError. The exception escapes the per-line try, which only wraps json.loads, so one bad line kills the whole parse and the backend returns nothing for that call.
Repro
fromskillopt_sleep.backendimportCopilotCliBackendasBB._parse_jsonl_response('{"type":"assistant.message","data":"hi"}')
# AttributeError: 'str' object has no attribute 'get'
data: [] happens to survive, because [] or {} falls back to {}. Only truthy non-dict values trip it.
Expected
The malformed line is skipped and the rest of the stream still parses.
An existing test already fails because of this
tests/test_sleep_engine.py::TestCopilotBackend::test_parse_jsonl_ignores_excessively_nested_json expects "" and instead errors out. It builds a 2000 deep nested array expecting RecursionError from json.loads, but on Python 3.14 that parses fine, so it reaches the field access and hits the AttributeError instead.
Why this looks like drift rather than an intended contract
skillopt/model/copilot_backend.py::parse_copilot_jsonl parses the same event format and guards it:
That guard arrived in 5497a31 ("harden and deduplicate JSONL parsing"), which deleted the exact (obj.get("data") or {}).get("content") line from both copilot_backend.py and codex_harness.py and merged the three copies into one helper. tests/test_copilot_exec_backend.py locks the behavior in with a "data": "invalid" line mid stream, asserting the surrounding messages still concatenate.
skillopt_sleep/backend.py predates that commit and was not part of the consolidation, most likely because the sleep package intentionally keeps zero dependency on the research package.
Activity