Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-langchain-aws for
openSUSE:Factory checked in at 2026-10-08 11:59:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langchain-aws (Old)
and /work/SRC/openSUSE:Factory/.python-langchain-aws.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-langchain-aws"
Thu Oct 8 11:59:32 2026 rev:15 rq:1383222 version:1.8.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-langchain-aws/python-langchain-aws.changes
2026-10-01 22:21:50.456443833 +0200
+++
/work/SRC/openSUSE:Factory/.python-langchain-aws.new.3698736/python-langchain-aws.changes
2026-10-08 12:00:24.232515376 +0200
@@ -1,0 +2,10 @@
+Thu Oct 8 06:27:11 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 1.8.1:
+ * Raise ContextOverflowError from ChatBedrockConverse on context
+ window overflow, and from ChatOpenAIMantle Chat Completions models
+ * Filter out foreign reasoning items for reasoning models
+ * Refreshed the bundled Bedrock model profile data
+ * Raise the langchain-core floor to >= 1.6.7
+
+-------------------------------------------------------------------
Old:
----
langchain_aws-1.8.0.tar.gz
New:
----
langchain_aws-1.8.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-langchain-aws.spec ++++++
--- /var/tmp/diff_new_pack.gazdNH/_old 2026-10-08 12:00:25.258558353 +0200
+++ /var/tmp/diff_new_pack.gazdNH/_new 2026-10-08 12:00:25.263558563 +0200
@@ -17,7 +17,7 @@
Name: python-langchain-aws
-Version: 1.8.0
+Version: 1.8.1
Release: 0
Summary: LangChain integrations for AWS
License: MIT
@@ -28,14 +28,14 @@
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-boto3 >= 1.43.64
-Requires: python-langchain-core >= 1.6.3
+Requires: python-langchain-core >= 1.6.7
Requires: python-numpy >= 1.0.0
Requires: python-pydantic >= 2.10.6
BuildArch: noarch
# SECTION test requirements
BuildRequires: %{python_module boto3 >= 1.43.64}
BuildRequires: %{python_module langchain-anthropic}
-BuildRequires: %{python_module langchain-core >= 1.6.3}
+BuildRequires: %{python_module langchain-core >= 1.6.7}
BuildRequires: %{python_module langgraph}
BuildRequires: %{python_module numpy >= 1.0.0}
BuildRequires: %{python_module pydantic >= 2.10.6}
++++++ langchain_aws-1.8.0.tar.gz -> langchain_aws-1.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_aws-1.8.0/PKG-INFO
new/langchain_aws-1.8.1/PKG-INFO
--- old/langchain_aws-1.8.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.5
Name: langchain-aws
-Version: 1.8.0
+Version: 1.8.1
Summary: An integration package connecting AWS and LangChain
Project-URL: Source Code,
https://github.com/langchain-ai/langchain-aws/tree/main/libs/aws
Project-URL: Repository, https://github.com/langchain-ai/langchain-aws
@@ -8,7 +8,7 @@
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: boto3>=1.43.64
-Requires-Dist: langchain-core>=1.6.3
+Requires-Dist: langchain-core>=1.6.7
Requires-Dist: numpy<3,>=1.0.0
Requires-Dist: pydantic<3,>=2.10.6
Provides-Extra: anthropic
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_aws-1.8.0/langchain_aws/chat_models/_compat.py
new/langchain_aws-1.8.1/langchain_aws/chat_models/_compat.py
--- old/langchain_aws-1.8.0/langchain_aws/chat_models/_compat.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/langchain_aws/chat_models/_compat.py
2020-02-02 01:00:00.000000000 +0100
@@ -82,6 +82,10 @@
if "reasoning_content" not in new_block:
new_block["reasoning_content"] = {}
new_block["reasoning_content"]["signature"] = signature
+ if redacted := block.get("extras", {}).get("redacted_content"):
+ if "reasoning_content" not in new_block:
+ new_block["reasoning_content"] = {}
+ new_block["reasoning_content"]["redacted_content"] = redacted
new_content.append(new_block)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_aws-1.8.0/langchain_aws/chat_models/bedrock_converse.py
new/langchain_aws-1.8.1/langchain_aws/chat_models/bedrock_converse.py
--- old/langchain_aws-1.8.0/langchain_aws/chat_models/bedrock_converse.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/langchain_aws/chat_models/bedrock_converse.py
2020-02-02 01:00:00.000000000 +0100
@@ -26,7 +26,7 @@
from botocore.exceptions import ClientError
from langchain_core.callbacks import CallbackManagerForLLMRun
-from langchain_core.exceptions import OutputParserException
+from langchain_core.exceptions import ContextOverflowError,
OutputParserException
from langchain_core.language_models import (
BaseChatModel,
LanguageModelInput,
@@ -1544,6 +1544,10 @@
generation_chunk.text, chunk=generation_chunk
)
yield generation_chunk
+ except ClientError as e:
+ # Bedrock can also report the overflow as an event after the
stream opens.
+ _raise_if_context_overflow(e)
+ raise
finally:
if hasattr(stream, "close"):
stream.close()
@@ -2317,6 +2321,79 @@
return [SystemMessage(content=new_content), *messages[1:]]
+class BedrockContextOverflowError(ClientError, ContextOverflowError):
+ """ClientError raised when input exceeds the Bedrock model's context
window."""
+
+ def __reduce__(self) -> Tuple[Any, ...]:
+ # ClientError.__reduce__ rebuilds a plain ClientError, losing the
overflow type.
+ return BedrockContextOverflowError, (self.response,
self.operation_name)
+
+
+# Lowercased fragments of the ValidationException messages Bedrock returns when
+# the prompt exceeds the model's context window.
+_CONTEXT_OVERFLOW_MARKERS = (
+ # Claude Sonnet 4.5, DeepSeek R1
+ "input is too long",
+ # Claude Haiku 4.5 and newer Claude models; also matched by
langchain-anthropic
+ "prompt is too long",
+ # Amazon Nova
+ "input tokens exceeded",
+ # Meta Llama, Mistral, and other open-weight models (gpt-oss, Qwen,
DeepSeek V3)
+ "maximum context length",
+ # OpenAI GPT; also matched by langchain-openai
+ "context_length_exceeded",
+ "exceeds the context window",
+ "input tokens exceed the configured limit",
+ # Kimi K3
+ "exceed model maximum",
+ # matched by LiteLLM (Bedrock, vLLM/SGLang)
+ "too many input tokens",
+ "is longer than the model's context length",
+)
+
+
+_CONTEXT_OVERFLOW_ERROR_TYPES: Dict[
+ Type[ClientError], Type[BedrockContextOverflowError]
+] = {}
+
+
+def _context_overflow_error_type(
+ error_type: Type[ClientError],
+) -> Type[BedrockContextOverflowError]:
+ """Return a subclass of both `error_type` and
`BedrockContextOverflowError`.
+
+ Subclassing the original type keeps handlers that catch boto3's modeled
+ exceptions, such as `client.exceptions.ValidationException`, working.
+ """
+ if issubclass(BedrockContextOverflowError, error_type):
+ return BedrockContextOverflowError
+ if error_type not in _CONTEXT_OVERFLOW_ERROR_TYPES:
+ _CONTEXT_OVERFLOW_ERROR_TYPES[error_type] = cast(
+ Type[BedrockContextOverflowError],
+ type(error_type.__name__, (error_type,
BedrockContextOverflowError), {}),
+ )
+ return _CONTEXT_OVERFLOW_ERROR_TYPES[error_type]
+
+
+def _raise_if_context_overflow(error: ClientError) -> None:
+ """Re-raise `error` as a `ContextOverflowError` if it reports a context
overflow.
+
+ Args:
+ error: The ClientError from boto3.
+
+ Raises:
+ BedrockContextOverflowError: If the error is a context window overflow.
+ """
+ error_info = error.response.get("Error", {})
+ # Event stream errors use a lowercase code, e.g. "validationException".
+ if error_info.get("Code", "").lower() != "validationexception":
+ return
+ error_message = str(error_info.get("Message", "")).lower()
+ if any(marker in error_message for marker in _CONTEXT_OVERFLOW_MARKERS):
+ overflow_type = _context_overflow_error_type(type(error))
+ raise overflow_type(error.response, error.operation_name) from error
+
+
def _handle_bedrock_error(error: ClientError) -> None:
"""Handle Bedrock API errors and provide enhanced error messages.
@@ -2324,9 +2401,12 @@
error: The ClientError from boto3
Raises:
+ BedrockContextOverflowError: If the input exceeds the model's context
window
ValueError: Enhanced error with helpful message for IAM permission
issues
ClientError: Re-raises the original error if not a known case
"""
+ _raise_if_context_overflow(error)
+
error_code = error.response.get("Error", {}).get("Code", "")
error_message = str(error)
@@ -2348,6 +2428,79 @@
raise error
+_REASONING_BLOCK_TYPES = frozenset(
+ {"reasoning", "reasoning_content", "thinking", "redacted_thinking"}
+)
+
+
+def _known_model_provider(model_id: Optional[str]) -> Optional[str]:
+ """Return the provider encoded in a Bedrock model ID, or `None` if
unknowable.
+
+ ARNs for custom, provisioned, and application inference profile models do
+ not encode the provider.
+ """
+ if not model_id or model_id.startswith("arn:"):
+ return None
+ return parse_model_provider(model_id).lower()
+
+
+def _drop_foreign_reasoning(
+ message: AIMessage,
+ *,
+ model_id: Optional[str],
+ provider: Optional[str],
+) -> AIMessage:
+ """Drop reasoning blocks that a different model provider produced.
+
+ Reasoning carries provider-specific state (signatures, encrypted payloads)
+ that other providers reject outright, so replaying it after switching
+ models mid-thread fails the request. When either side's provider is
+ unknown, the message is returned unchanged.
+
+ Args:
+ message: Assistant message in Converse content format.
+ model_id: Model ID of the model the request is being sent to.
+ provider: Provider of the model the request is being sent to, which
+ takes precedence over the one parsed from `model_id`.
+
+ Returns:
+ The message, or a copy of it without reasoning blocks.
+ """
+ if isinstance(message.content, str):
+ return message
+ if message.response_metadata.get("model_provider") not in (
+ None,
+ "bedrock_converse",
+ "bedrock",
+ ):
+ return message
+ model_name = message.response_metadata.get("model_name")
+ source_provider = (
+ _known_model_provider(model_name) if isinstance(model_name, str) else
None
+ )
+ target_provider = (provider or "").lower() or
_known_model_provider(model_id)
+ if (
+ source_provider is None
+ or target_provider is None
+ or source_provider == target_provider
+ ):
+ return message
+
+ content = [
+ block
+ for block in message.content
+ if not (isinstance(block, dict) and block.get("type") in
_REASONING_BLOCK_TYPES)
+ ]
+ if len(content) == len(message.content):
+ return message
+ logger.debug(
+ "Dropping reasoning blocks produced by provider %s; %s rejects them",
+ source_provider,
+ target_provider,
+ )
+ return message.model_copy(update={"content": content})
+
+
def _messages_to_bedrock(
messages: List[BaseMessage],
system: Optional[List[Union[str, Dict[str, Any]]]] = None,
@@ -2384,6 +2537,9 @@
messages[idx] = message.model_copy(
update={"content": cast(list, normalized)}
)
+ messages[idx] = _drop_foreign_reasoning(
+ cast(AIMessage, messages[idx]), model_id=model_id,
provider=provider
+ )
bedrock_messages: List[Dict[str, Any]] = []
bedrock_system: List[Dict[str, Any]] = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_aws-1.8.0/langchain_aws/chat_models/openai.py
new/langchain_aws-1.8.1/langchain_aws/chat_models/openai.py
--- old/langchain_aws-1.8.0/langchain_aws/chat_models/openai.py 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/langchain_aws/chat_models/openai.py 2020-02-02
01:00:00.000000000 +0100
@@ -10,15 +10,22 @@
import os
from collections.abc import AsyncIterator, Iterator
-from typing import Any, Literal, cast
+from typing import Any, Literal, NoReturn, cast
+import openai
+from langchain_core.callbacks import (
+ AsyncCallbackManagerForLLMRun,
+ CallbackManagerForLLMRun,
+)
+from langchain_core.exceptions import ContextOverflowError
from langchain_core.language_models import (
LanguageModelInput,
ModelProfile,
ModelProfileRegistry,
)
from langchain_core.language_models.chat_models import LangSmithParams
-from langchain_core.outputs import ChatGenerationChunk
+from langchain_core.messages import BaseMessage
+from langchain_core.outputs import ChatGenerationChunk, ChatResult
from langchain_core.runnables import Runnable
from langchain_core.utils import secret_from_env
from langchain_openai.chat_models.base import (
@@ -44,6 +51,8 @@
_MODEL_PROFILES = cast("ModelProfileRegistry", _PROFILES)
+_MANTLE_CONTEXT_OVERFLOW_MARKER = "maximum context length"
+
def _get_default_model_profile(model_name: str) -> ModelProfile:
"""Return the static capability profile for a Mantle model, or an empty
one."""
@@ -51,6 +60,31 @@
return default.copy()
+class MantleContextOverflowError(openai.BadRequestError, ContextOverflowError):
+ """BadRequestError raised when input exceeds the Mantle model's context
window."""
+
+
+class MantleAPIContextOverflowError(openai.APIError, ContextOverflowError):
+ """APIError raised when input exceeds the Mantle model's context window."""
+
+
+def _handle_mantle_error(error: openai.APIError) -> NoReturn:
+ """Handle Mantle API errors not covered by base langchain-openai."""
+ is_overflow = not isinstance(error, ContextOverflowError) and (
+ _MANTLE_CONTEXT_OVERFLOW_MARKER in str(error).lower()
+ )
+ if is_overflow and isinstance(error, openai.BadRequestError):
+ raise MantleContextOverflowError(
+ message=error.message, response=error.response, body=error.body
+ ) from error
+ if is_overflow:
+ raise MantleAPIContextOverflowError(
+ message=error.message, request=error.request, body=error.body
+ ) from error
+
+ raise error
+
+
def _plain_secret(value: Any) -> str | None:
"""Return the plain string for a ``SecretStr``/``str``/``None`` value."""
if value is None:
@@ -320,22 +354,53 @@
params["ls_provider"] = "openai-mantle"
return params
+ def _generate(
+ self,
+ messages: list[BaseMessage],
+ stop: list[str] | None = None,
+ run_manager: CallbackManagerForLLMRun | None = None,
+ **kwargs: Any,
+ ) -> ChatResult:
+ try:
+ return super()._generate(messages, stop, run_manager, **kwargs)
+ except openai.APIError as e:
+ _handle_mantle_error(e)
+
+ async def _agenerate(
+ self,
+ messages: list[BaseMessage],
+ stop: list[str] | None = None,
+ run_manager: AsyncCallbackManagerForLLMRun | None = None,
+ **kwargs: Any,
+ ) -> ChatResult:
+ try:
+ return await super()._agenerate(messages, stop, run_manager,
**kwargs)
+ except openai.APIError as e:
+ _handle_mantle_error(e)
+
def _stream(self, *args: Any, **kwargs: Any) ->
Iterator[ChatGenerationChunk]:
"""Route to the Chat Completions or Responses API."""
- if self._use_responses_api({**kwargs, **self.model_kwargs}):
- return super()._stream_responses(*args, **kwargs)
- return super()._stream(*args, **kwargs)
+ try:
+ if self._use_responses_api({**kwargs, **self.model_kwargs}):
+ yield from super()._stream_responses(*args, **kwargs)
+ else:
+ yield from super()._stream(*args, **kwargs)
+ except openai.APIError as e:
+ _handle_mantle_error(e)
async def _astream(
self, *args: Any, **kwargs: Any
) -> AsyncIterator[ChatGenerationChunk]:
"""Route to the Chat Completions or Responses API."""
- if self._use_responses_api({**kwargs, **self.model_kwargs}):
- async for chunk in super()._astream_responses(*args, **kwargs):
- yield chunk
- else:
- async for chunk in super()._astream(*args, **kwargs):
- yield chunk
+ try:
+ if self._use_responses_api({**kwargs, **self.model_kwargs}):
+ async for chunk in super()._astream_responses(*args, **kwargs):
+ yield chunk
+ else:
+ async for chunk in super()._astream(*args, **kwargs):
+ yield chunk
+ except openai.APIError as e:
+ _handle_mantle_error(e)
def with_structured_output(
self,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_aws-1.8.0/langchain_aws/data/_profiles.py
new/langchain_aws-1.8.1/langchain_aws/data/_profiles.py
--- old/langchain_aws-1.8.0/langchain_aws/data/_profiles.py 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/langchain_aws/data/_profiles.py 2020-02-02
01:00:00.000000000 +0100
@@ -1338,6 +1338,31 @@
"max",
],
},
+ "eu.anthropic.claude-sonnet-5-5": {
+ "name": "Claude Sonnet 5.5 (EU)",
+ "release_date": "2026-09-28",
+ "last_updated": "2026-09-28",
+ "open_weights": False,
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": False,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
"eu.mistral.pixtral-large-2502-v1:0": {
"name": "Pixtral Large (25.02) (EU)",
"release_date": "2025-04-08",
@@ -1933,6 +1958,31 @@
"pdf_tool_message": True,
"image_tool_message": True,
},
+ "global.openai.gpt-6.1-sol": {
+ "name": "GPT-6.1 Sol (Global)",
+ "release_date": "2026-09-29",
+ "last_updated": "2026-09-29",
+ "open_weights": False,
+ "max_input_tokens": 1050000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": True,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
"global.xai.grok-4.6": {
"name": "Grok 4.6 (Global)",
"release_date": "2026-08-12",
@@ -2132,6 +2182,80 @@
"pdf_tool_message": True,
"image_tool_message": True,
},
+ "in.anthropic.claude-haiku-4-5-20251001-v1:0": {
+ "name": "Claude Haiku 4.5 (India)",
+ "release_date": "2025-10-15",
+ "last_updated": "2025-10-15",
+ "open_weights": False,
+ "max_input_tokens": 200000,
+ "max_output_tokens": 64000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": False,
+ "attachment": True,
+ "temperature": True,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
+ "in.anthropic.claude-opus-5": {
+ "name": "Claude Opus 5 (India)",
+ "release_date": "2026-07-24",
+ "last_updated": "2026-07-24",
+ "open_weights": False,
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
+ "in.anthropic.claude-sonnet-5": {
+ "name": "Claude Sonnet 5 (India)",
+ "release_date": "2026-06-30",
+ "last_updated": "2026-06-30",
+ "open_weights": False,
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": False,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
"in.openai.gpt-5.6-luna": {
"name": "GPT-5.6 Luna (India)",
"release_date": "2026-07-09",
@@ -3249,6 +3373,31 @@
"max",
],
},
+ "openai.gpt-6.1-sol": {
+ "name": "GPT-6.1 Sol",
+ "release_date": "2026-09-29",
+ "last_updated": "2026-09-29",
+ "open_weights": False,
+ "max_input_tokens": 1050000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": True,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
"openai.gpt-oss-120b": {
"name": "gpt-oss-120b",
"release_date": "2025-08-05",
@@ -4131,6 +4280,31 @@
"max",
],
},
+ "us.anthropic.claude-sonnet-5-5": {
+ "name": "Claude Sonnet 5.5 (US)",
+ "release_date": "2026-09-28",
+ "last_updated": "2026-09-28",
+ "open_weights": False,
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "pdf_inputs": True,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": False,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
"us.deepseek.r1-v1:0": {
"name": "DeepSeek-R1 (US)",
"release_date": "2025-01-20",
@@ -4456,6 +4630,31 @@
"open_weights": False,
"max_input_tokens": 1050000,
"max_output_tokens": 128000,
+ "text_inputs": True,
+ "image_inputs": True,
+ "audio_inputs": False,
+ "video_inputs": False,
+ "text_outputs": True,
+ "image_outputs": False,
+ "audio_outputs": False,
+ "video_outputs": False,
+ "reasoning_output": True,
+ "tool_calling": True,
+ "structured_output": True,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ },
+ "us.openai.gpt-6.1-sol": {
+ "name": "GPT-6.1 Sol (US)",
+ "release_date": "2026-09-29",
+ "last_updated": "2026-09-29",
+ "open_weights": False,
+ "max_input_tokens": 1050000,
+ "max_output_tokens": 128000,
"text_inputs": True,
"image_inputs": True,
"audio_inputs": False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_aws-1.8.0/pyproject.toml
new/langchain_aws-1.8.1/pyproject.toml
--- old/langchain_aws-1.8.0/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_aws-1.8.1/pyproject.toml 2020-02-02 01:00:00.000000000
+0100
@@ -9,10 +9,10 @@
readme = "README.md"
authors = []
-version = "1.8.0"
+version = "1.8.1"
requires-python = ">=3.10"
dependencies = [
- "langchain-core>=1.6.3",
+ "langchain-core>=1.6.7",
"boto3>=1.43.64",
"pydantic>=2.10.6,<3",
"numpy>=1.0.0,<3",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_aws-1.8.0/tests/unit_tests/chat_models/test_bedrock_converse.py
new/langchain_aws-1.8.1/tests/unit_tests/chat_models/test_bedrock_converse.py
---
old/langchain_aws-1.8.0/tests/unit_tests/chat_models/test_bedrock_converse.py
2020-02-02 01:00:00.000000000 +0100
+++
new/langchain_aws-1.8.1/tests/unit_tests/chat_models/test_bedrock_converse.py
2020-02-02 01:00:00.000000000 +0100
@@ -811,6 +811,218 @@
]
+def test__messages_to_bedrock_v1_preserves_redacted_reasoning() -> None:
+ """Encrypted reasoning survives v1 replay so the model can reuse it."""
+ messages = [
+ HumanMessage(content="What is 2 + 2?"),
+ AIMessage(
+ content=[
+ {"type": "reasoning", "extras": {"redacted_content":
b"rsn_opaque"}},
+ {"type": "text", "text": "4"},
+ ],
+ response_metadata={
+ "output_version": "v1",
+ "model_provider": "bedrock_converse",
+ },
+ ),
+ ]
+
+ actual_messages, _ = _messages_to_bedrock(messages,
model_id="openai.gpt-6-luna")
+
+ assert actual_messages == [
+ {"role": "user", "content": [{"text": "What is 2 + 2?"}]},
+ {
+ "role": "assistant",
+ "content": [
+ {"reasoningContent": {"redactedContent": b"rsn_opaque"}},
+ {"text": "4"},
+ ],
+ },
+ ]
+
+
+_CLAUDE = "us.anthropic.claude-sonnet-5-5"
+_LUNA = "us.openai.gpt-6-luna"
+_CLAUDE_REASONING = {
+ "type": "reasoning_content",
+ "reasoning_content": {"text": "", "signature": "claude_signature"},
+}
+_CLAUDE_REASONING_V1 = {
+ "type": "reasoning",
+ "extras": {"signature": "claude_signature"},
+}
+_LUNA_REASONING = {
+ "type": "reasoning_content",
+ "reasoning_content": {"redacted_content": b"rsn_opaque"},
+}
+_LUNA_REASONING_V1 = {
+ "type": "reasoning",
+ "extras": {"redacted_content": b"rsn_opaque"},
+}
+_CLAUDE_REASONING_BEDROCK = {
+ "reasoningContent": {"reasoningText": {"text": "", "signature":
"claude_signature"}}
+}
+_LUNA_REASONING_BEDROCK = {"reasoningContent": {"redactedContent":
b"rsn_opaque"}}
+
+
+def _assistant_turn(
+ reasoning: dict, text: str, *, model_name: Optional[str], v1: bool = False
+) -> AIMessage:
+ response_metadata: dict = {"model_provider": "bedrock_converse"}
+ if model_name is not None:
+ response_metadata["model_name"] = model_name
+ if v1:
+ response_metadata["output_version"] = "v1"
+ return AIMessage(
+ content=[reasoning, {"type": "text", "text": text}],
+ response_metadata=response_metadata,
+ )
+
+
+def _replayed_assistant_content(
+ message: AIMessage, *, model_id: str, provider: Optional[str] = None
+) -> list:
+ actual_messages, _ = _messages_to_bedrock(
+ [HumanMessage(content="What is 2 + 2?"), message],
+ model_id=model_id,
+ provider=provider,
+ )
+ return actual_messages[1]["content"]
+
+
[email protected](
+ ("reasoning", "source", "target", "v1"),
+ [
+ (_CLAUDE_REASONING, _CLAUDE, "openai.gpt-6-luna", False),
+ (_CLAUDE_REASONING_V1, _CLAUDE, "openai.gpt-6-luna", True),
+ (_LUNA_REASONING, _LUNA, "anthropic.claude-sonnet-5-5", False),
+ (_LUNA_REASONING_V1, _LUNA, "anthropic.claude-sonnet-5-5", True),
+ ],
+)
+def test__messages_to_bedrock_drops_reasoning_from_other_provider(
+ reasoning: dict, source: str, target: str, v1: bool
+) -> None:
+ message = _assistant_turn(reasoning, "4", model_name=source, v1=v1)
+ original_content = list(message.content)
+
+ assert _replayed_assistant_content(message, model_id=target) == [{"text":
"4"}]
+ assert message.content == original_content
+
+
[email protected](
+ ("reasoning", "source", "target", "v1", "expected"),
+ [
+ (
+ _CLAUDE_REASONING,
+ _CLAUDE,
+ "anthropic.claude-sonnet-5",
+ False,
+ _CLAUDE_REASONING_BEDROCK,
+ ),
+ (
+ _CLAUDE_REASONING_V1,
+ _CLAUDE,
+ "anthropic.claude-sonnet-5",
+ True,
+ _CLAUDE_REASONING_BEDROCK,
+ ),
+ (
+ _LUNA_REASONING,
+ _LUNA,
+ "openai.gpt-5.6-luna",
+ False,
+ _LUNA_REASONING_BEDROCK,
+ ),
+ (
+ _LUNA_REASONING_V1,
+ _LUNA,
+ "openai.gpt-5.6-luna",
+ True,
+ _LUNA_REASONING_BEDROCK,
+ ),
+ ],
+)
+def test__messages_to_bedrock_keeps_reasoning_from_same_provider(
+ reasoning: dict, source: str, target: str, v1: bool, expected: dict
+) -> None:
+ message = _assistant_turn(reasoning, "4", model_name=source, v1=v1)
+
+ assert _replayed_assistant_content(message, model_id=target) == [
+ expected,
+ {"text": "4"},
+ ]
+
+
[email protected](
+ "model_name",
+ [None, "arn:aws:bedrock:us-east-1:123456789012:custom-model/abc"],
+)
+def test__messages_to_bedrock_keeps_reasoning_from_unknown_provider(
+ model_name: Optional[str],
+) -> None:
+ message = _assistant_turn(_CLAUDE_REASONING, "4", model_name=model_name)
+
+ assert _replayed_assistant_content(message, model_id="openai.gpt-6-luna")
== [
+ _CLAUDE_REASONING_BEDROCK,
+ {"text": "4"},
+ ]
+
+
+def test__messages_to_bedrock_keeps_reasoning_for_unknown_target() -> None:
+ message = _assistant_turn(_CLAUDE_REASONING, "4", model_name=_CLAUDE)
+ arn = "arn:aws:bedrock:us-east-1:123456789012:custom-model/abc"
+
+ assert _replayed_assistant_content(message, model_id=arn) == [
+ _CLAUDE_REASONING_BEDROCK,
+ {"text": "4"},
+ ]
+
+
+def test__messages_to_bedrock_explicit_provider_identifies_target() -> None:
+ message = _assistant_turn(_CLAUDE_REASONING, "4", model_name=_CLAUDE)
+ arn = "arn:aws:bedrock:us-east-1:123456789012:custom-model/abc"
+
+ assert _replayed_assistant_content(message, model_id=arn,
provider="openai") == [
+ {"text": "4"}
+ ]
+
+
+def test__messages_to_bedrock_drops_foreign_reasoning_before_merging_turns()
-> None:
+ """Consecutive turns from different models are judged separately."""
+ messages = [
+ HumanMessage(content="What is 2 + 2?"),
+ _assistant_turn(_CLAUDE_REASONING, "4", model_name=_CLAUDE),
+ _assistant_turn(_LUNA_REASONING, "Still 4.", model_name=_LUNA),
+ ]
+
+ actual_messages, _ = _messages_to_bedrock(messages,
model_id="openai.gpt-6-luna")
+
+ assert actual_messages[1] == {
+ "role": "assistant",
+ "content": [{"text": "4"}, _LUNA_REASONING_BEDROCK, {"text": "Still
4."}],
+ }
+
+
+def test__messages_to_bedrock_keeps_tool_calls_when_dropping_reasoning() ->
None:
+ message = AIMessage(
+ content=[_CLAUDE_REASONING],
+ tool_calls=[
+ {"id": "call_abc", "name": "get_weather", "args": {"city":
"Paris"}}
+ ],
+ response_metadata={"model_provider": "bedrock_converse", "model_name":
_CLAUDE},
+ )
+
+ assert _replayed_assistant_content(message, model_id="openai.gpt-6-luna")
== [
+ {
+ "toolUse": {
+ "toolUseId": "call_abc",
+ "input": {"city": "Paris"},
+ "name": "get_weather",
+ }
+ }
+ ]
+
+
def test__messages_to_bedrock_preserves_ai_cache_point() -> None:
"""Preserve cache points when replaying normalized assistant history."""
messages = [
@@ -5181,6 +5393,263 @@
assert "Example policy statement" in error_message
+_INPUT_TOO_LONG = "Input is too long for requested model."
+
+
+def _validation_error_response(message: str, code: str =
"ValidationException") -> Any:
+ return {
+ "Error": {"Code": code, "Message": message},
+ "ResponseMetadata": {"RequestId": "test-request-id"},
+ }
+
+
+def _bedrock_runtime_client() -> Any:
+ # boto3.client is mocked in conftest; botocore gives a real client for
Stubber.
+ return botocore.session.get_session().create_client(
+ "bedrock-runtime",
+ region_name="us-east-1",
+ aws_access_key_id="test",
+ aws_secret_access_key="test",
+ )
+
+
[email protected](
+ "message",
+ [
+ _INPUT_TOO_LONG,
+ "The model returned the following errors: Input is too long for
requested "
+ "model.",
+ "The model returned the following errors: Input Tokens Exceeded:
Number of "
+ "input tokens exceeds maximum length. Please update the input to try
again.",
+ "The model returned the following errors: This model's maximum context
"
+ "length is 131072 tokens. Please reduce the length of the prompt",
+ "The model returned the following errors: Mantle streaming error for "
+ 'requestId 0: ErrorEvent { error: APIError { type: "BadRequestError", '
+ "code: Some(400), message: \"Input length (450236) exceeds model's "
+ 'maximum context length (131072).", param: None } }',
+ "prompt is too long: 1052304 tokens > 1000000 maximum",
+ "The model returned the following errors: context_length_exceeded:
Your "
+ "input exceeds the context window of this model. Please adjust your
input "
+ "and try again.",
+ "Your input exceeds the context window of this model.",
+ "Input tokens exceed the configured limit of 272000 tokens. Your
messages "
+ "resulted in 450236 tokens.",
+ "prompt tokens (450236) exceed model maximum (262144)",
+ "Too many input tokens.",
+ "The input (450236 tokens) is longer than the model's context length "
+ "(131072 tokens).",
+ ],
+)
+def test_context_overflow_error_detection(message: str) -> None:
+ from botocore.exceptions import ClientError
+ from langchain_core.exceptions import ContextOverflowError
+
+ from langchain_aws.chat_models.bedrock_converse import (
+ BedrockContextOverflowError,
+ _handle_bedrock_error,
+ )
+
+ error = ClientError(_validation_error_response(message), "Converse")
+
+ with pytest.raises(ContextOverflowError) as exc_info:
+ _handle_bedrock_error(error)
+
+ assert isinstance(exc_info.value, BedrockContextOverflowError)
+ assert isinstance(exc_info.value, ClientError)
+ assert exc_info.value.response == error.response
+ assert exc_info.value.operation_name == "Converse"
+ assert str(exc_info.value) == str(error)
+ assert exc_info.value.__cause__ is error
+
+
[email protected](
+ "message",
+ [
+ "The maximum tokens you requested exceeds the model limit of 64000.
Try "
+ "again with a maximum tokens value that is lower than 64000.",
+ "Malformed input request: #: extraneous key [foo] is not permitted",
+ ],
+)
+def test_context_overflow_ignores_other_validation_errors(message: str) ->
None:
+ from botocore.exceptions import ClientError
+
+ from langchain_aws.chat_models.bedrock_converse import
_handle_bedrock_error
+
+ error = ClientError(_validation_error_response(message), "Converse")
+
+ with pytest.raises(ClientError) as exc_info:
+ _handle_bedrock_error(error)
+
+ assert exc_info.value is error
+
+
+def test_context_overflow_requires_validation_exception() -> None:
+ from botocore.exceptions import ClientError
+
+ from langchain_aws.chat_models.bedrock_converse import
_handle_bedrock_error
+
+ error = ClientError(
+ _validation_error_response(_INPUT_TOO_LONG,
code="ThrottlingException"),
+ "Converse",
+ )
+
+ with pytest.raises(ClientError) as exc_info:
+ _handle_bedrock_error(error)
+
+ assert exc_info.value is error
+
+
+def test_context_overflow_preserves_modeled_exception_type() -> None:
+ from langchain_core.exceptions import ContextOverflowError
+
+ from langchain_aws.chat_models.bedrock_converse import
_handle_bedrock_error
+
+ client = _bedrock_runtime_client()
+ error = client.exceptions.ValidationException(
+ _validation_error_response(_INPUT_TOO_LONG), "Converse"
+ )
+
+ with pytest.raises(client.exceptions.ValidationException) as exc_info:
+ _handle_bedrock_error(error)
+
+ assert isinstance(exc_info.value, ContextOverflowError)
+ assert type(exc_info.value).__name__ == "ValidationException"
+
+
+def test_context_overflow_error_survives_pickling() -> None:
+ import pickle
+
+ from botocore.exceptions import ClientError, EventStreamError
+ from langchain_core.exceptions import ContextOverflowError
+
+ from langchain_aws.chat_models.bedrock_converse import (
+ BedrockContextOverflowError,
+ _raise_if_context_overflow,
+ )
+
+ client = _bedrock_runtime_client()
+ errors = [
+ ClientError(_validation_error_response(_INPUT_TOO_LONG), "Converse"),
+ client.exceptions.ValidationException(
+ _validation_error_response(_INPUT_TOO_LONG), "Converse"
+ ),
+ EventStreamError(
+ _validation_error_response(_INPUT_TOO_LONG,
code="validationException"),
+ "ConverseStream",
+ ),
+ ]
+ for error in errors:
+ with pytest.raises(ContextOverflowError) as exc_info:
+ _raise_if_context_overflow(error)
+
+ restored = pickle.loads(pickle.dumps(exc_info.value))
+
+ assert isinstance(restored, BedrockContextOverflowError)
+ assert isinstance(restored, ClientError)
+ assert restored.response == error.response
+ assert restored.operation_name == error.operation_name
+
+
+def test_invoke_raises_context_overflow_error() -> None:
+ from botocore.stub import Stubber
+ from langchain_core.exceptions import ContextOverflowError
+
+ client = _bedrock_runtime_client()
+ llm = ChatBedrockConverse(
+ model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
+ region_name="us-east-1",
+ client=client,
+ )
+ stubber = Stubber(client)
+ stubber.add_client_error(
+ "converse",
+ service_error_code="ValidationException",
+ service_message=_INPUT_TOO_LONG,
+ http_status_code=400,
+ )
+
+ with stubber, pytest.raises(ContextOverflowError) as exc_info:
+ llm.invoke("hello")
+
+ assert isinstance(exc_info.value, client.exceptions.ValidationException)
+
+
+def test_stream_raises_context_overflow_error() -> None:
+ from botocore.stub import Stubber
+ from langchain_core.exceptions import ContextOverflowError
+
+ client = _bedrock_runtime_client()
+ llm = ChatBedrockConverse(
+ model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
+ region_name="us-east-1",
+ client=client,
+ )
+ stubber = Stubber(client)
+ stubber.add_client_error(
+ "converse_stream",
+ service_error_code="ValidationException",
+ service_message=_INPUT_TOO_LONG,
+ http_status_code=400,
+ )
+
+ with stubber, pytest.raises(ContextOverflowError) as exc_info:
+ list(llm.stream("hello"))
+
+ assert isinstance(exc_info.value, client.exceptions.ValidationException)
+
+
+def test_stream_raises_context_overflow_error_from_event_stream() -> None:
+ from botocore.exceptions import EventStreamError
+ from langchain_core.exceptions import ContextOverflowError
+
+ llm = ChatBedrockConverse(
+ model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
region_name="us-east-1"
+ )
+ error = EventStreamError(
+ _validation_error_response(_INPUT_TOO_LONG,
code="validationException"),
+ "ConverseStream",
+ )
+
+ def _events() -> Iterator[dict]:
+ raise error
+ yield {}
+
+ mock_client = mock.Mock()
+ mock_client.converse_stream.return_value = {"stream": _events()}
+ llm.client = mock_client
+
+ with pytest.raises(ContextOverflowError) as exc_info:
+ list(llm._stream([HumanMessage(content="hello")]))
+
+ assert isinstance(exc_info.value, EventStreamError)
+ assert exc_info.value.__cause__ is error
+
+
+def test_stream_reraises_other_event_stream_errors() -> None:
+ from botocore.exceptions import EventStreamError
+
+ llm = ChatBedrockConverse(
+ model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
region_name="us-east-1"
+ )
+ error = EventStreamError(
+ _validation_error_response("Too many requests",
code="throttlingException"),
+ "ConverseStream",
+ )
+
+ def _events() -> Iterator[dict]:
+ raise error
+ yield {}
+
+ mock_client = mock.Mock()
+ mock_client.converse_stream.return_value = {"stream": _events()}
+ llm.client = mock_client
+
+ with pytest.raises(EventStreamError) as exc_info:
+ list(llm._stream([HumanMessage(content="hello")]))
+
+ assert exc_info.value is error
+
+
def test_reasoning_config_validation_only_applies_to_nova_2() -> None:
"""Test that reasoning config validation only applies to Nova 2 models."""
# Should not raise an error for non-Nova-2 models even with invalid config
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_aws-1.8.0/tests/unit_tests/chat_models/test_openai.py
new/langchain_aws-1.8.1/tests/unit_tests/chat_models/test_openai.py
--- old/langchain_aws-1.8.0/tests/unit_tests/chat_models/test_openai.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/tests/unit_tests/chat_models/test_openai.py
2020-02-02 01:00:00.000000000 +0100
@@ -1,9 +1,12 @@
"""ChatOpenAIMantle unit tests."""
-from typing import Tuple, Type, cast
-from unittest.mock import patch
+from collections.abc import AsyncIterator, Iterator
+from typing import Any, Tuple, Type, cast
+from unittest.mock import MagicMock, patch
+import openai
import pytest
+from langchain_core.exceptions import ContextOverflowError
from langchain_core.language_models import BaseChatModel
from langchain_core.messages import HumanMessage
from langchain_openai.chat_models.base import BaseChatOpenAI
@@ -12,6 +15,10 @@
from pytest import MonkeyPatch
from langchain_aws import ChatOpenAIMantle
+from langchain_aws.chat_models.openai import (
+ MantleAPIContextOverflowError,
+ MantleContextOverflowError,
+)
from langchain_aws.utils import _BedrockApiKeyProvider
MODEL_NAME = "openai.gpt-oss-120b"
@@ -419,3 +426,108 @@
"hello", extra_headers={"X-Another-Header": "ok"}
)
assert payload["extra_headers"] == {"X-Another-Header": "ok"}
+
+
+_MANTLE_OVERFLOW = (
+ 'ErrorEvent { error: APIError { type: "BadRequestError", code: Some(400), '
+ "message: \"Input length (213426) exceeds model's maximum context length "
+ '(131072).", param: None } }'
+)
+
+
+def _response() -> Any:
+ # Stand-in for the SDK's HTTP response; the error classes only read these.
+ return MagicMock(status_code=400, headers={}, request=MagicMock())
+
+
+def _bad_request(message: str) -> openai.BadRequestError:
+ return openai.BadRequestError(message, response=_response(), body=None)
+
+
+def _api_error(message: str) -> openai.APIError:
+ return openai.APIError(message, cast(Any, MagicMock()), body=None)
+
+
+def _raising_stream(error: Exception) -> Iterator[Any]:
+ raise error
+ yield # pragma: no cover
+
+
+async def _raising_astream(error: Exception) -> AsyncIterator[Any]:
+ raise error
+ yield # pragma: no cover
+
+
+def test_invoke_context_overflow_raises_context_overflow_error() -> None:
+ error = _bad_request(_MANTLE_OVERFLOW)
+ with patch.object(BaseChatOpenAI, "_generate", side_effect=error):
+ with pytest.raises(ContextOverflowError) as exc_info:
+ _make_model().invoke("hello")
+
+ assert isinstance(exc_info.value, MantleContextOverflowError)
+ assert isinstance(exc_info.value, openai.BadRequestError)
+ assert exc_info.value.__cause__ is error
+
+
[email protected]("model", [MODEL_NAME, "openai.gpt-5.6-sol"])
+def test_stream_context_overflow_raises_context_overflow_error(model: str) ->
None:
+ # gpt-oss streams over Chat Completions; GPT-5.x over the Responses API.
+ error = _api_error(_MANTLE_OVERFLOW)
+ route = "_stream" if model == MODEL_NAME else "_stream_responses"
+ with patch.object(
+ BaseChatOpenAI, route, side_effect=lambda *a, **k:
_raising_stream(error)
+ ):
+ with pytest.raises(ContextOverflowError) as exc_info:
+ llm = ChatOpenAIMantle(
+ model=model,
+ region_name="us-east-1",
+ bedrock_api_key=SecretStr("test-key"),
+ )
+ list(llm.stream("hello"))
+
+ assert isinstance(exc_info.value, MantleAPIContextOverflowError)
+ assert isinstance(exc_info.value, openai.APIError)
+ assert exc_info.value.__cause__ is error
+
+
+async def test_async_context_overflow_raises_context_overflow_error() -> None:
+ invoke_error = _bad_request(_MANTLE_OVERFLOW)
+ stream_error = _api_error(_MANTLE_OVERFLOW)
+ with (
+ patch.object(BaseChatOpenAI, "_agenerate", side_effect=invoke_error),
+ patch.object(
+ BaseChatOpenAI,
+ "_astream",
+ side_effect=lambda *a, **k: _raising_astream(stream_error),
+ ),
+ ):
+ with pytest.raises(MantleContextOverflowError):
+ await _make_model().ainvoke("hello")
+ with pytest.raises(MantleAPIContextOverflowError):
+ async for _ in _make_model().astream("hello"):
+ pass
+
+
+class _AlreadyOverflow(openai.BadRequestError, ContextOverflowError):
+ pass
+
+
[email protected](
+ "error",
+ [
+ _bad_request("Invalid 'max_output_tokens': integer below minimum
value"),
+ # e.g. GPT-5.x overflows, already classified by langchain-openai
+ _AlreadyOverflow(
+ "context_length_exceeded: maximum context length",
+ response=_response(),
+ body=None,
+ ),
+ ],
+ ids=["other_error", "already_context_overflow"],
+)
+def test_errors_are_reraised_unchanged(error: openai.BadRequestError) -> None:
+ with patch.object(BaseChatOpenAI, "_generate", side_effect=error):
+ with pytest.raises(openai.BadRequestError) as exc_info:
+ _make_model().invoke("hello")
+
+ assert exc_info.value is error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_aws-1.8.0/uv.lock
new/langchain_aws-1.8.1/uv.lock
--- old/langchain_aws-1.8.0/uv.lock 2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_aws-1.8.1/uv.lock 2020-02-02 01:00:00.000000000 +0100
@@ -945,7 +945,7 @@
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "python_full_version < '3.12'" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz",
hash =
"sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size
= 30371, upload-time = "2025-11-21T23:01:54.787Z" }
wheels = [
@@ -1534,7 +1534,7 @@
[[package]]
name = "langchain-aws"
-version = "1.8.0"
+version = "1.8.1"
source = { editable = "." }
dependencies = [
{ name = "boto3" },
@@ -1618,7 +1618,7 @@
{ name = "bedrock-agentcore", marker = "python_full_version >= '3.10' and
extra == 'tools'", specifier = ">=1.23.0" },
{ name = "boto3", specifier = ">=1.43.64" },
{ name = "langchain-anthropic", marker = "extra == 'anthropic'" },
- { name = "langchain-core", specifier = ">=1.6.3" },
+ { name = "langchain-core", specifier = ">=1.6.7" },
{ name = "langchain-openai", marker = "extra == 'openai'", specifier =
">=1.0.0" },
{ name = "numpy", specifier = ">=1.0.0,<3" },
{ name = "openai", marker = "extra == 'openai'", specifier = ">=1.106.0" },
@@ -1690,7 +1690,7 @@
[[package]]
name = "langchain-core"
-version = "1.6.6"
+version = "1.6.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -1704,9 +1704,9 @@
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
-sdist = { url =
"https://files.pythonhosted.org/packages/18/87/9e5d393bbcec068c51becc255a15aacfd8a14ac5826179751c1c320e5258/langchain_core-1.6.6.tar.gz",
hash =
"sha256:67616d984c085009be2c381c2efd330d32429a58aebab295b4f51b6573964511", size
= 1007227, upload-time = "2026-09-29T14:52:54.598Z" }
+sdist = { url =
"https://files.pythonhosted.org/packages/0b/0e/cd8ace920319158f1111ad3e6d6a418254fad7594402a57560ff285d5127/langchain_core-1.6.7.tar.gz",
hash =
"sha256:55842ca61ffb460787c6f62c8bf775275972e9b9a3fd9b2210931eb77d038e2d", size
= 1009564, upload-time = "2026-10-06T15:46:53.498Z" }
wheels = [
- { url =
"https://files.pythonhosted.org/packages/90/10/8c00b4dc094886314c907ec7ead258dfee28948cf44175976cc4fba9aba8/langchain_core-1.6.6-py3-none-any.whl",
hash =
"sha256:d9a71e312ab7443701238750e04a57aefc037c4f1ec82837c8a1609d9a14a9b1", size
= 572080, upload-time = "2026-09-29T14:52:53.213Z" },
+ { url =
"https://files.pythonhosted.org/packages/af/fb/12b08f501fb2fc379b82eb5c391b56c6ecc70d30aedeb4acb44de03a9252/langchain_core-1.6.7-py3-none-any.whl",
hash =
"sha256:e12cb80b2008b0484c33d209c42d6290ef173f7be9d639b372aba0d438676cdd", size
= 572761, upload-time = "2026-10-06T15:46:52.069Z" },
]
[[package]]