From db8c0b3dac5c9f1919209f8a6d198845eb446bdc Mon Sep 17 00:00:00 2001 From: red person Date: Wed, 3 Jun 2026 08:11:45 +0300 Subject: [PATCH] Ignore non-string background stream deltas (#1549) --- src/bg_monitor.py | 4 +++- tests/test_bg_monitor_stream.py | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/test_bg_monitor_stream.py diff --git a/src/bg_monitor.py b/src/bg_monitor.py index fbee84e..d732771 100644 --- a/src/bg_monitor.py +++ b/src/bg_monitor.py @@ -53,7 +53,9 @@ async def _drain_agent(sess, messages): if not isinstance(d, dict): continue if "delta" in d: - full += d["delta"] + delta = d.get("delta") + if isinstance(delta, str): + full += delta elif d.get("type") == "agent_step": round_num = d.get("round", round_num) elif d.get("type") == "tool_output": diff --git a/tests/test_bg_monitor_stream.py b/tests/test_bg_monitor_stream.py new file mode 100644 index 0000000..f7ff8f2 --- /dev/null +++ b/tests/test_bg_monitor_stream.py @@ -0,0 +1,39 @@ +import asyncio +import sys +import types +from types import SimpleNamespace + +from src import bg_monitor + + +def test_drain_agent_ignores_non_string_deltas(monkeypatch): + async def fake_stream_agent_loop(*args, **kwargs): + yield 'data: {"delta": null}' + yield 'data: {"delta": ["bad"]}' + yield 'data: {"delta": "ok"}' + yield 'data: {"type": "agent_step", "round": 2}' + yield 'data: {"type": "tool_output", "tool": "shell", "output": "done"}' + yield "data: [DONE]" + + agent_loop = types.ModuleType("src.agent_loop") + agent_loop.stream_agent_loop = fake_stream_agent_loop + monkeypatch.setitem(sys.modules, "src.agent_loop", agent_loop) + + sess = SimpleNamespace( + endpoint_url="http://example.test", + model="model", + headers=None, + context_length=0, + id="s1", + ) + + full, events = asyncio.run(bg_monitor._drain_agent(sess, [])) + + assert full == "ok" + assert events == [{ + "round": 2, + "tool": "shell", + "command": None, + "output": "done", + "exit_code": None, + }]