fix(bedrock/converse): forward first delta when contentBlockStart is absent

When Bedrock's converse-stream API omits contentBlockStart events (observed
with marketplace models such as minimax.minimax-m2.5), the first delta for
each new content block arrives without a prior start event.

AnthropicStreamWrapper detects the block boundary from the delta itself and
correctly emits content_block_stop + content_block_start, but then returns
without queuing the triggering processed_chunk. This silently drops the
first characters of every new block.

Fix: after emitting content_block_start, also queue the processed chunk if
it is a content_block_delta. Applied to both __next__ (sync) and __anext__
(async) paths.
This commit is contained in:
adelnobel 2026-03-30 03:02:27 +00:00
parent 58120537af
commit f8ab7279a8

View file

@ -129,8 +129,6 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
if should_start_new_block and not self.sent_content_block_finish:
# Queue the sequence: content_block_stop -> content_block_start
# The trigger chunk itself is not emitted as a delta since the
# content_block_start already carries the relevant information.
self.chunk_queue.append(
{
"type": "content_block_stop",
@ -145,6 +143,13 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
}
)
self.sent_content_block_finish = False
# Also forward the triggering delta if it has content.
# When Bedrock omits contentBlockStart events (e.g. for marketplace
# models), the first delta for a new block arrives without a prior
# start event. Dropping it causes the first characters of each block
# to be silently lost.
if processed_chunk.get("type") == "content_block_delta":
self.chunk_queue.append(processed_chunk)
return self.chunk_queue.popleft()
if (
@ -305,8 +310,6 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
if not self.queued_usage_chunk:
if should_start_new_block and not self.sent_content_block_finish:
# Queue the sequence: content_block_stop -> content_block_start
# The trigger chunk itself is not emitted as a delta since the
# content_block_start already carries the relevant information.
# 1. Stop current content block
self.chunk_queue.append(
@ -328,6 +331,14 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
# Reset state for new block
self.sent_content_block_finish = False
# Also forward the triggering delta if it has content.
# When Bedrock omits contentBlockStart events (e.g. for marketplace
# models), the first delta for a new block arrives without a prior
# start event. Dropping it causes the first characters of each block
# to be silently lost.
if processed_chunk.get("type") == "content_block_delta":
self.chunk_queue.append(processed_chunk)
# Return the first queued item
return self.chunk_queue.popleft()