Skip to content

fix(llm): tolerate list-shaped streaming delta content - #2188

Merged
chenghao-mou merged 1 commit into
mainfrom
awoken-tunnel-inverted
Jul 31, 2026
Merged

fix(llm): tolerate list-shaped streaming delta content#2188
chenghao-mou merged 1 commit into
mainfrom
awoken-tunnel-inverted

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Ports livekit/agents#6625.

Summary

  • Flatten list-shaped streaming delta content before filtering thinking tokens.
  • Preserve text from string, record, and typed object parts while ignoring non-text parts.
  • Preserve the distinction between no textual content and an explicitly empty text part.

Source diff coverage

Source diff coverage
  • livekit-agents/livekit/agents/llm/utils.py: Adapted to agents/src/llm/utils.ts. The Python flattening behavior is translated to TypeScript, including string parts, record/object .text parts, empty-list semantics, and warning/drop behavior through the target logger.
  • tests/test_llm_utils.py: Adapted to agents/src/llm/utils.test.ts. All seven source test cases are ported to the existing Vitest suite with only language- and framework-specific assertion changes.
  • Not applicable: None. Every source diff file has a target counterpart, and no supporting infrastructure is missing.

Testing

  • pnpm exec vitest run agents (111 files, 1,523 passed, 5 skipped)
  • pnpm --filter @livekit/agents build
  • pnpm --filter @livekit/agents lint

Ported from livekit/agents#6625

Original PR description

Fixes livekit/agents#6323

Problem

strip_thinking_tokens assumes delta.content is str | None. The OpenAI-compatible ecosystem allows it to be a list of typed content parts ([{"type": "text", "text": ...}]) — Mistral emits this shape on some streamed chunks — and the openai SDK constructs stream models without validation (construct()), so when openai.LLM points at such a provider via base_url, the raw list reaches the filter and crashes the session. Wrapped as a retryable APIConnectionError mid-stream, a FallbackAdapter then silently fails the whole session over to its fallback leg — a hard-to-diagnose degradation.

Re: the open question on the issue about the source of the claim ("the OpenAI streaming spec only documents string"): correct for OpenAI's own service — the authority here is Mistral's chat-completions API, whose assistant/delta message content is typed string | ContentChunk[] in their reference and SDK. Since the plugin explicitly supports OpenAI-compatible providers through base_url, and the SDK's unvalidated stream models pass whatever the provider sends, the list shape is reachable in practice (that's how the original reporter hit it in production). Answered in more detail on the issue thread.

Change

Flatten list-shaped content to its concatenated text parts before the tag scan — dict parts ({"text": ...}), plain strings, and typed objects with a .text attribute. Unknown content types are dropped with a warning instead of crashing. String/None behavior is byte-identical.

Tests

Five new cases in tests/test_llm_utils.py: the issue's exact repro ([{"type": "text", "text": "Hallo"}]), mixed part lists, thinking-tag stripping across list-shaped chunks, non-text parts ignored, and typed objects with .text.

Relationship to #6324

This supersedes the stalled #6324 (same diagnosis, by @KSerProject — credit where due): that PR has had merge conflicts and an unsigned CLA for four weeks. Happy to close this one if the original author returns.

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner July 31, 2026 14:09
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 35cacea

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 39 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-azure Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-krisp Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-protoface Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugins-test Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@chenghao-mou
chenghao-mou merged commit 238a58c into main Jul 31, 2026
6 checks passed
@chenghao-mou
chenghao-mou deleted the awoken-tunnel-inverted branch July 31, 2026 17:32
@github-actions github-actions Bot mentioned this pull request Jul 31, 2026
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.

strip_thinking_tokens crashes on list-shaped streaming delta content (AttributeError: 'list' object has no attribute 'find')

1 participant