Two ways the VLM parsers crashed on adversarial model output instead of
degrading gracefully (the contract they already honor for invalid JSON):
1. Gemini 2.5: a mask value that is not a 'data:image/png;base64,' string
appended an empty mask and then 'continue'd, skipping the confidence
handler at the bottom of the loop. The item's box was recorded but its
confidence was not, so the confidence array ended up shorter than xyxy
and Detections.from_vlm raised a shape ValueError. Replaced the
'continue' with an if/else so the confidence handler always runs.
2. Gemini 2.0 / Gemini 2.5 / Qwen 2.5: valid JSON whose top level is not a
list, or whose elements are not dicts (e.g. '[1, 2, 3]'), raised
TypeError from the 'key not in item' membership test. Added a top-level
list guard (Gemini 2.0/2.5; Qwen already had one) and a per-element
dict guard so wrong-shaped JSON degrades to empty Detections.
Add regression tests for the mask/confidence alignment and for graceful
degradation across all three parsers.
---------
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>