Skip to content

Judge a stream's speed on what it generates visibly - #133

Merged
fylorn merged 1 commit into
devfrom
fix/min-speed-judgment
Oct 30, 2026
Merged

fylorn merged 1 commit into
devfrom
fix/min-speed-judgment

Conversation

@fylorn

@fylorn fylorn commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes to how a stream's speed is judged against its provider's minimum (follow-up to #131).

  • Upstream-reported counts are no longer used. Gemini's running output count includes the thoughts it does not show. Once that count got ahead of the text, the text that followed counted for nothing, and a fast stream could be cut. Speed is now judged on visible text only.
  • Summarised reasoning is left out. Responses reasoning summaries, Anthropic thinking blocks, Gemini thought parts and Bedrock reasoning content arrive in bursts while the model reasons at full speed.
    • No second is judged while such a phase is open.
    • After the phase ends, its time and its text are left out of the window.
    • Reasoning streamed as it is generated (Chat reasoning_content, Responses response.reasoning_text.delta) still counts.
  • Short pauses.
    • A long pause is now a quarter of the window, at most 5 s.
    • No second is judged if the last content arrived more than 1 s ago, so the burst an upstream sends after holding tokens back is waited for.
  • End of answer. The end is now also detected from each format's last frame (Anthropic message_stop, Chat [DONE], Responses response.completed), not only from a stop reason. Gemini and Bedrock end with their stop reason.
  • Upstream connection. It is dropped at the cut, before the error frame goes to the client.
  • Affinity and log row. The affinity is dropped, and the speed is written to the log row, only when the stream's outcome is the cut.
  • The CHANGELOG entry, schema comment and console hint are updated to match.

Tests

New unit tests in proxy::min_speed. Run against the previous implementation, these fail:

  • hidden reasoning in Gemini's count
  • a summarised Responses reasoning phase
  • an open Anthropic thinking block
  • the quarter-window pause
  • waiting for the burst after a short pause
  • end detection in every format

reasoning_streamed_as_generated_is_judged guards that raw reasoning still counts.

Also run:

  • make precommit and pnpm lint pass.
  • The gateway_min_speed, gateway_retry and streaming_and_cache integration tests pass locally, except one streaming_and_cache test that needs ClickHouse, which was not running; CI runs it.

The connection drop and the outcome guard come without a failing test: the pump returns right after the cut, so locally there is no ordering that tells the old code from the new.

🤖 Generated with Claude Code

Fixes to how a stream's speed is judged against its provider's minimum:

- Counts the upstream reports are no longer used. Gemini's running
  output count includes the thoughts it does not show; once it leaped
  ahead of the text, the text counted for nothing and a fast stream
  could be cut.
- Summarised reasoning is left out: Responses reasoning summaries,
  Anthropic thinking blocks, Gemini thought parts and Bedrock reasoning
  content arrive in bursts while the model reasons at full speed. No
  second is judged while such a phase is open, and its time and text are
  left out of the window after. Reasoning streamed as generated (Chat
  reasoning_content, Responses reasoning_text) still counts.
- A long pause is a quarter of the window, at most 5 s, and no second is
  judged whose last content is more than a second old: the burst an
  upstream sends after holding tokens back is waited for.
- The answer's end is also seen by the format's last frame (Anthropic
  message_stop, Chat [DONE], Responses response.completed), not only by
  a stop reason.
- The upstream's connection is dropped at the cut, before the error
  frame goes to the client.
- The affinity is dropped and the speed written to the log row only when
  the stream's outcome is the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn merged commit b569e40 into dev Oct 30, 2026
7 checks passed
@fylorn
fylorn deleted the fix/min-speed-judgment branch October 30, 2026 15:39
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant