Skip to content

v1.1.3

Choose a tag to compare

@github-actions github-actions released this 15 Jun 09:09
· 46 commits to main since this release
v1.1.3
d2070c2

[1.1.3] — 2026-06-15

Streaming-correctness release. Brings the streaming routing path (RouteStream) to parity with non-streaming Route: the post-request plugin pipeline, the per-provider circuit breaker, and least-latency / cost-optimized ordering now all apply to stream: true traffic. Also tightens fallback retry semantics and async-context propagation. No public API breaks. Fixes every issue labelled release-1.1.3: #135, #136, #137, and #138, plus enhancement #181.

Fixed

  • Streaming requests skipped the post-request plugin pipeline (issue #135, PR #201): RouteStream ran only before_request plugins, so after_request (response-cache store, request-logger) and on_error plugins never fired for streaming traffic and a cache Skip hit was discarded with the provider called anyway. The full plugin lifecycle now runs for streams: RunAfter fires once the stream drains — with the response reconstructed from streamed chunks so the response-cache can store it — RunOnError fires on resolution / provider / stream / after-plugin failures, and a cache hit short-circuits the provider into a single streamed chunk. @Rachit-Gandhi
  • Circuit breaker was a no-op for streaming-first traffic (issue #136, PR #199): the streaming path never recorded breaker outcomes, so mid-stream provider failures did not count and the breaker never opened. Stream success is now recorded at stream completion and failures (both at startup and mid-stream) count toward the breaker; open-circuit streaming targets are skipped during resolution so fallback advances instead of returning circuit-open. @Rachit-Gandhi
  • Fallback strategy retried cancellations and open circuits (issue #137, PR #198): shouldRetry returned true for any error without a parseable HTTP status code, so context.Canceled / context.DeadlineExceeded and circuitbreaker.ErrCircuitOpen re-attempted already-cancelled requests and burned the whole retry budget against an open circuit. These sentinels are now non-retryable, and the retry loop checks ctx.Err() before each attempt.
  • Streaming ignored least-latency / cost-optimized ordering (issue #138, PR #198): streamingTargetOrderLocked had no case for these modes and silently fell through to declaration order. Streaming now orders targets by observed p50 latency (exploring unsampled targets first) and by catalog model cost, mirroring the non-streaming path, and records successful stream latency samples so least-latency converges for streaming-only traffic.

Changed

  • Circuit-breaker failure accounting (issue #136, PR #199): caller-side cancellation and client deadlines no longer trip the breaker, while provider-side timeouts that surface as context.DeadlineExceeded while the request context is still live are counted as failures. Applies to both Route and RouteStream.
  • Detached background goroutines preserve trace context (issue #181, PR #202): async event hooks and the streaming observability completion event now run under context.WithoutCancel(ctx) instead of the already-cancelled request context / context.Background(), so fire-and-forget work (DB writes, outbound calls) is no longer dead-on-arrival and recorded events stay linked to the originating trace. MCP background initialization parents its 60s timeout on the gateway shutdown context so Close() cancels in-flight handshakes instead of letting them linger.

Notes

  • Under cost-optimized routing with unpriced_strategy: skip, the streaming path keeps unpriced providers as a last-resort fallback (and errors only when no candidate is priced), whereas the non-streaming path never selects an unpriced provider. This is intentional for the streaming fallback chain.
  • All public release-1.1.3 issues — #135, #136, #137, #138 — and enhancement #181 are closed by this release.

Contributors

Thanks to everyone who shipped this release:


Full changelog: https://github.com/ferro-labs/ai-gateway/blob/v1.1.3/CHANGELOG.md