Skip to content

fix(v2): don't mistake a literal '[' inside a preceding string field for the tasks array start#2426

Open
roli-lpci wants to merge 1 commit into
567-labs:mainfrom
roli-lpci:fix/iterable-bracket-in-string
Open

fix(v2): don't mistake a literal '[' inside a preceding string field for the tasks array start#2426
roli-lpci wants to merge 1 commit into
567-labs:mainfrom
roli-lpci:fix/iterable-bracket-in-string

Conversation

@roli-lpci

Copy link
Copy Markdown

Describe your changes

IterableBase.tasks_from_chunks / tasks_from_chunks_async (instructor/v2/dsl/iterable.py), the
streaming path every provider's Iterable[Model] extraction goes through, detects the start of the
streamed tasks array with a naive "[" in chunk check on each individual chunk. If a field
preceding tasks in the response JSON contains a literal [ inside a string value — for example a
free-text note field like "check [priority] items first" — that in-string bracket falsely
triggers array-start detection. The buffer gets sliced from the wrong offset, and every task
streamed after that point is silently dropped: the function returns an empty list, with no
exception anywhere.

chunks = [
    '{"note": "check [priority] items first", ',
    '"tasks": [',
    '{"name": "alpha", "priority": 1}',
    ', {"name": "beta", "priority": 2}',
    "]}",
]
list(IterableModel(Task).tasks_from_chunks(chunks))
# []  <- both tasks vanished, no error

The fix adds _find_unquoted_char, a small string-aware scanner (tracks in_string/escape state,
the same pattern get_object a few lines below already uses for brace-matching) and uses it in
both tasks_from_chunks and tasks_from_chunks_async to find the real, unquoted [ against the
full accumulated buffer instead of a naive per-chunk substring check. 38 lines changed across both
sync/async entry points plus the new helper; no signature changes.

Tests: added test_iterable_tasks_from_chunks_ignores_bracket_inside_preceding_string and its
async counterpart, mirroring the existing test_iterable_tasks_from_chunks_handles_braces_inside_strings
pattern, using the note-field repro above. Before fix: 2 failed — assert [] == [Task(name='alpha', priority=1), Task(name='beta', priority=2)] (both streamed tasks silently dropped). After fix: all
6 tests in tests/v2/test_iterable_streaming.py pass. ruff check is clean on both changed files.

Issue ticket number and link

No existing issue tracks this bug. Distinct from the already-merged PR #2340 (a consolidation
bundle whose iterable.py portion fixed brace-in-string detection in get_object) — this fixes a
different detection bug (array-start bracket, not object-boundary brace) in a different function;
get_object itself is unchanged.

Checklist before requesting a review

  • I have performed a self-review of my code
  • If it is a core feature, I have added thorough tests.
  • If it is a core feature, I have added documentation. (Bug fix to internal streaming
    detection; no documented behavior changed.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant