diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index 21a73fc2fb..8de456a71d 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -643,7 +643,10 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): if not isinstance(item, dict): return try: - output_index = int(parsed_chunk.get("output_index")) + output_index_raw = parsed_chunk.get("output_index") + if output_index_raw is None: + raise ValueError("missing output_index") + output_index = int(output_index_raw) except (TypeError, ValueError): output_index = len(recovered_output_items) recovered_output_items[output_index] = item @@ -660,7 +663,10 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): return try: - output_index = int(parsed_chunk.get("output_index")) + output_index_raw = parsed_chunk.get("output_index") + if output_index_raw is None: + raise ValueError("missing output_index") + output_index = int(output_index_raw) except (TypeError, ValueError): output_index = len(recovered_text_only_items) @@ -682,7 +688,10 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): return try: - content_index = int(parsed_chunk.get("content_index")) + content_index_raw = parsed_chunk.get("content_index") + if content_index_raw is None: + raise ValueError("missing content_index") + content_index = int(content_index_raw) except (TypeError, ValueError): content_index = len(content) @@ -789,8 +798,8 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): logging_obj ) if recovered_output_items: - output_items = recovered_output_items - raw_response.output = recovered_output_items + output_items = cast(Any, recovered_output_items) + raw_response.output = cast(Any, recovered_output_items) verbose_logger.warning( "Recovered empty Responses API output from raw SSE for model=%s", model, diff --git a/litellm/llms/chatgpt/responses/transformation.py b/litellm/llms/chatgpt/responses/transformation.py index d0e63fbfdf..c2060ceaad 100644 --- a/litellm/llms/chatgpt/responses/transformation.py +++ b/litellm/llms/chatgpt/responses/transformation.py @@ -213,6 +213,8 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): if not isinstance(item, dict): return try: + if output_index is None: + raise ValueError("missing output_index") index = int(output_index) except (TypeError, ValueError): index = len(streamed_output_items) diff --git a/litellm/llms/reducto/common.py b/litellm/llms/reducto/common.py index d9c419700a..1a1abac49a 100644 --- a/litellm/llms/reducto/common.py +++ b/litellm/llms/reducto/common.py @@ -131,11 +131,12 @@ def build_pages_from_reducto(result: Dict[str, Any]) -> List["OCRPage"]: block.get("content", "") for block in blocks if block.get("content") ) page_index = max(page_no - 1, 0) - pages.append( - OCRPage( - index=page_index, - markdown=markdown, - blocks=blocks, - ) + page = OCRPage( + index=page_index, + markdown=markdown, ) + # OCRPage accepts extra keys at runtime; assign blocks after construction + # so static typing does not reject provider-specific metadata. + setattr(page, "blocks", blocks) + pages.append(page) return pages diff --git a/litellm/llms/vertex_ai/vertex_llm_base.py b/litellm/llms/vertex_ai/vertex_llm_base.py index 5087abe48c..787b45df15 100644 --- a/litellm/llms/vertex_ai/vertex_llm_base.py +++ b/litellm/llms/vertex_ai/vertex_llm_base.py @@ -45,7 +45,7 @@ class VertexBase: self._credentials: Optional[GoogleCredentialsObject] = None self._credentials_project_mapping: Dict[ Tuple[Optional[VERTEX_CREDENTIALS_TYPES], Optional[str]], - Tuple[GoogleCredentialsObject, str], + Tuple[GoogleCredentialsObject, Optional[str]], ] = {} self.project_id: Optional[str] = None self.async_handler: Optional[AsyncHTTPHandler] = None