diff --git a/agent/native_compaction.py b/agent/native_compaction.py index 67236ecca1..44c721d397 100644 --- a/agent/native_compaction.py +++ b/agent/native_compaction.py @@ -336,7 +336,7 @@ def prune_pre_checkpoint_items( retained_reversed.append(item) user_remaining -= cost else: - content = item["content"] + content = item.get("content") if isinstance(content, str): head = content[: user_remaining * 4] keep = bool(head.strip()) diff --git a/tests/agent/test_native_compaction_typed_user_retention.py b/tests/agent/test_native_compaction_typed_user_retention.py index 82071af960..cf300eadfe 100644 --- a/tests/agent/test_native_compaction_typed_user_retention.py +++ b/tests/agent/test_native_compaction_typed_user_retention.py @@ -58,13 +58,16 @@ _IMAGE = {"type": "input_image", "image_url": "data:image/png;base64,AAAA"} {"type": "input_text", "text": "trailing"}], 2, ("abcd", "efgh")), ([{"type": "input_text", "text": "你好世界"}], 2, ("你好",)), ([{"type": "input_text", "text": "CURRENT" * 20}, _IMAGE], 2, None), + (None, 2, None), ], - ids=["multipart-boundary", "cjk-estimator-budget", "oversized-mixed-image"], + ids=["multipart-boundary", "cjk-estimator-budget", "oversized-mixed-image", "oversized-output-text-only"], ) def test_typed_boundary_is_budgeted_and_never_substitutes_older_ask(content, budget, expected): older = {"role": "user", "content": "old"} current = {"type": "message", "role": "user", "id": "current-user", "content": deepcopy(content)} - for index, part in enumerate(current["content"]): + if content is None: # Content-less item measured only via output_text. + current = {"type": "message", "role": "user", "output_text": "CURRENT" * 20} + for index, part in enumerate(current.get("content") or []): part["metadata"] = {"index": index} items = [older, current, _CHECKPOINT] original = deepcopy(items)