From 2cc4ef2a97de95952abfaa368856e7e7a00e22bb Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 28 May 2026 04:31:29 +0000 Subject: [PATCH] fix: address two low-severity context_management edge cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - streaming_iterator: keep `sent_content_block_finish` in sync with the compaction block's emitted start/delta/stop lifecycle and reset it when the next text block's start is queued. - bedrock _map_context_management_param: match dispatcher `_normalize_spec` behavior — only run the OpenAI→Anthropic mapper on list inputs; pass dict inputs through unchanged so already-Anthropic-format values aren't silently dropped. Co-authored-by: Yassin Kortam --- .../adapters/streaming_iterator.py | 14 ++++++++++++++ .../llms/bedrock/chat/converse_transformation.py | 14 +++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py index 5ee42eed698..4e3d47c885c 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -287,10 +287,17 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): ): self.sent_compaction_block = True self._queue_compaction_block_events() + # The compaction block emitted a complete start/delta/stop + # lifecycle. Reflect that in the state machine so any + # downstream check sees a consistent view; the flag is + # reset to ``False`` when the next (text) block's + # ``content_block_start`` is emitted below. + self.sent_content_block_finish = True return self.chunk_queue.popleft() if self.sent_content_block_start is False: self.sent_content_block_start = True + self.sent_content_block_finish = False self.chunk_queue.append( { "type": "content_block_start", @@ -502,10 +509,17 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): ): self.sent_compaction_block = True self._queue_compaction_block_events() + # The compaction block emitted a complete start/delta/stop + # lifecycle. Reflect that in the state machine so any + # downstream check sees a consistent view; the flag is + # reset to ``False`` when the next (text) block's + # ``content_block_start`` is emitted below. + self.sent_content_block_finish = True return self.chunk_queue.popleft() if self.sent_content_block_start is False: self.sent_content_block_start = True + self.sent_content_block_finish = False self.chunk_queue.append( { "type": "content_block_start", diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 370d75780d7..31d2d74cba4 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -979,9 +979,17 @@ class AmazonConverseConfig(BaseConfig): def _map_context_management_param( self, value: Union[dict, list], optional_params: dict ) -> None: - mapped = AnthropicConfig.map_openai_context_management_to_anthropic( - cast(Union[dict, list], value) - ) + # Match the dispatcher's ``_normalize_spec`` behavior: only run the + # OpenAI→Anthropic mapper for list inputs. Dict inputs are already in + # Anthropic-native shape (``{"edits": [...]}``) and should pass + # through unchanged so an Anthropic-format ``context_management`` + # value isn't silently dropped when the mapper can't classify it. + if isinstance(value, list): + mapped = AnthropicConfig.map_openai_context_management_to_anthropic( + cast(Union[dict, list], value) + ) + else: + mapped = value # Skip when the mapper returned None for malformed input — leaving the # key out is safer than passing `context_management: null` downstream, # which Bedrock would reject and which can confuse intermediate checks