v1.5.9
Changelog
This release rebases Bifrost Enterprise on OSS transportsv1.6.9. It brings opt-in HTTP/2 PING keepalives for Bedrock streams, tenant-aware OTEL metric attributes (team, customer, business unit, service instance), and a large batch of streaming and provider-fidelity fixes, including two SSE heartbeat regressions that could corrupt or abort raw passthrough streams. There are no enterprise-only feature changes in this release.🌎 Open Source Features
- Bedrock HTTP/2 PING Keepalives - The Bedrock provider can now send HTTP/2 PING frames on idle connections through the new
http2_ping_interval_in_secondsconfig key (0 disables it), so quiet streams survive intermediaries that cut idle connections. Docs - Tenant Attributes on OTEL Metrics - Exported metrics now carry a service instance id plus team, customer, and business-unit ids and names, so series can be sliced per tenant without post-processing. Attribute values are also normalized and whitespace-trimmed on export. Docs
- Adaptive Thinking on Raw Passthrough - For adaptive-only Anthropic models (Opus 4.7+, Opus 4.8, Opus 5, Sonnet 5, Fable 5, Mythos 5), a legacy
thinking.type: "enabled"block is now rewritten to the adaptive form on the raw passthrough body, not just on the typed request path.
🐞 Fixed
- SSE Heartbeat Mid-Line Corruption - The stream reader now tracks line boundaries under a mutex and will not emit a heartbeat mid-line, fixing corrupted
data:payloads on raw passthrough streams. - SSE Heartbeat Frame Compatibility - The heartbeat comment frame no longer carries a trailing blank line, so non-conforming SSE decoders (openai-go ssestream before v3.43.0) stop dispatching an empty event and aborting mid-stream.
- Lost Log Rows on Shared Trace IDs - Concurrent requests that inherit the same W3C trace id no longer overwrite each other’s pending log entry; the join now uses the per-request internal trace id.
- Budget Counters Reset on Force-Sync -
config.jsonforce-sync no longer overwrites livecurrent_usage,last_reset, and the token/request rate-limit counters with file values. - Transcription Filename Dropped - The client’s multipart filename is carried through transcription ingress, so non-WAV containers are no longer relabelled
audio.mp3and rejected upstream. - Anthropic Mid-Conversation System Messages - A
role:"system"turn that cannot be forwarded natively is inlined as a user turn instead of being dropped, and Bedrock’s system-reminder converter keeps itscache_controlmarker. - Bedrock Streaming Correctness -
ConverseStreamnow reportsstopReason: tool_usefor tool-use turns,message_startcarries an all-zerousageobject when figures are unknown so@ai-sdk/anthropicaccepts the frame, and encrypted reasoning is preserved as a replay signature when translating Responses history. - Encrypted Reasoning Fail-Soft - An upstream 400 caused by unverifiable replayed
encrypted_contentnow strips the reasoning content and retries once instead of failing the request. - Server-Side Tool Search -
tool_search_tool_*types are normalized on the Responses path, andinclude_server_side_tool_invocationsnow reaches the Gemini declaration-drop gate. - DeepSeek Thinking on Multi-Turn - Thinking is no longer silently disabled for ordinary multi-turn conversations through the OpenAI-compatible surface. Docs
- Vertex and Gemini Response Fidelity -
generateContentkeepscandidates[0].safetyRatingsandavgLogprobs, and Vertex cached-content methods honour API-key or context-header auth instead of overwritingAuthorization. - Custom Provider Base Resolution - OpenAI models served through a custom provider now resolve to their built-in base provider before deciding reasoning item-id embedding.
- MCP Tool Errors Replayed as Success - Failed MCP tool executions are marked as errors instead of being replayed to the model as successful results, covering agent-loop failures, the MCP
isErrorflag, and CodeMode lookup/sandbox failures. - Tool-Result Document Blocks -
documentblocks in tool results survive the Anthropic to Responses conversion with a synthesized filename, andFileURL/FileTypepropagate through all three chat/responses conversion paths. - Stream Termination Edge Cases - A nil delta paired with a non-nil finish reason no longer aborts the stream, and GPT-5-series detection tolerates prefixed model names when resolving reasoning-effort support.
🗄️ Database Migrations
No new database migrations in this release, in either the OSS transports layer or the enterprise repo.🐙 Closed OSS Issues
- #5206 - Bedrock ConverseStream egress reports stopReason=end_turn for tool-use turns (should be tool_use)
- #5211 - Bedrock streaming can drop with “unexpected EOF” when an intermediary idle timeout severs a quiet stream
- #5256 - Concurrent HTTP requests sharing a W3C trace ID lose LLM log rows
- #5279 - OpenAI /v1/responses to Anthropic drops the tool_search_tool_regex type, so server-side tool_search never runs
- #5670 - Transcription drops the client’s multipart filename, so non-WAV containers are relabelled audio.mp3 and rejected
- #5679 - Anthropic Messages does not propagate Gemini mixed server/client tool opt-in
- #5843 - generateContent (Gemini format) drops
candidates[0].safetyRatingsandavgLogprobson Vertex AI responses - #5874 - SSE heartbeat frame aborts streams for openai-go ssestream consumers (< v3.43.0) with “unexpected end of JSON input”
- #5885 - v1.6.8 omits message_start.message.usage on Bedrock-backed providers, breaking @ai-sdk/anthropic streaming
- #5887 - DeepSeek thinking silently lost on ALL multi-turn requests via OpenAI-compat inbound
- #5890 - chat completions surface drops tool_result
is_error, so failed tool calls replay to the model as successful - #5902 - service_tier silently dropped for gpt-5.4 family, priority/fast requests downgrade to default
- #5905 - v1.6.8 raw passthrough heartbeat can split SSE data lines and corrupt JSON
- #5925 - config.json force-sync overwrites budget current_usage and last_reset on startup
📀 Base OSS version
transports/v1.6.9
