fix(agent): handle string context compression messages

This commit is contained in:
Vladimir Smirnov 2026-04-25 23:14:24 +03:00 committed by Teknium
parent c080a530ae
commit 9dc6dc062f
2 changed files with 27 additions and 1 deletions

View file

@ -1768,7 +1768,15 @@ This compaction should PRIORITISE preserving all information related to the focu
# retry (_generate_summary recursion) re-enters harmlessly.
with aux_interrupt_protection():
response = call_llm(**call_kwargs)
content = response.choices[0].message.content
# ``_validate_llm_response`` only guarantees ``choices[0].message``
# exists, not that it's an object with ``.content``. Some
# OpenAI-compatible proxies / local backends return a dict- or
# str-shaped message; coerce defensively instead of crashing.
message = response.choices[0].message
if isinstance(message, dict):
content = message.get("content")
else:
content = getattr(message, "content", message)
# Handle cases where content is not a string (e.g., dict from llama.cpp)
if not isinstance(content, str):
content = str(content) if content else ""

View file

@ -510,6 +510,24 @@ class TestNonStringContent:
assert summary is None
assert c._summary_failure_cooldown_until > 0
def test_string_message_coerced_to_summary_content(self):
mock_response = MagicMock()
mock_response.choices = [MagicMock()]
mock_response.choices[0].message = "plain summary text"
with patch("agent.context_compressor.get_model_context_length", return_value=100000):
c = ContextCompressor(model="test", quiet_mode=True)
messages = [
{"role": "user", "content": "do something"},
{"role": "assistant", "content": "ok"},
]
with patch("agent.context_compressor.call_llm", return_value=mock_response):
summary = c._generate_summary(messages)
assert summary == f"{SUMMARY_PREFIX}\nplain summary text"
def test_summary_call_does_not_force_temperature(self):
mock_response = MagicMock()
mock_response.choices = [MagicMock()]