fix(compaction): tolerate content-less user item at over-budget boundary

BN01 fold2 finding (2c Low): collapsing the over-budget branch in
d24e5875b7 read `item["content"]` unguarded. A user message whose text
is measured only via `output_text` (no `content` key) reaches that
branch when it exceeds the budget and raised KeyError, aborting the
prune. Use `item.get("content")` so it falls through to the
non-truncatable path (keep nothing, budget reset) as before the
refactor. The typed-boundary parametrize gains a row for it.
This commit is contained in:
kshitijk4poor
2026-10-03 15:45:41 +05:30
committed by kshitij
parent df3d72e8ac
commit 4d1b2dcf65
2 changed files with 6 additions and 3 deletions

View File

@@ -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())

View File

@@ -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)