Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-langchain-anthropic for
openSUSE:Factory checked in at 2026-07-26 11:30:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langchain-anthropic (Old)
and /work/SRC/openSUSE:Factory/.python-langchain-anthropic.new.2004 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-langchain-anthropic"
Sun Jul 26 11:30:01 2026 rev:3 rq:1367770 version:1.5.2
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-langchain-anthropic/python-langchain-anthropic.changes
2026-07-22 19:08:38.636330182 +0200
+++
/work/SRC/openSUSE:Factory/.python-langchain-anthropic.new.2004/python-langchain-anthropic.changes
2026-07-26 11:32:38.183316377 +0200
@@ -1,0 +2,11 @@
+Sat Jul 25 19:03:47 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 1.5.2:
+ * Add Claude Opus 5 support
+ * Enable structured output for Claude Opus 4.8
+ * Support the langsmith gateway through an environment
+ variable
+- Raise the anthropic floor to 0.120.0 and the langchain-core
+ floor to 1.5.1, following upstream requires
+
+-------------------------------------------------------------------
Old:
----
langchain_anthropic-1.5.0.tar.gz
New:
----
langchain_anthropic-1.5.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-langchain-anthropic.spec ++++++
--- /var/tmp/diff_new_pack.a39AwW/_old 2026-07-26 11:32:38.707334427 +0200
+++ /var/tmp/diff_new_pack.a39AwW/_new 2026-07-26 11:32:38.711334565 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-langchain-anthropic
-Version: 1.5.0
+Version: 1.5.2
Release: 0
Summary: Integration package connecting Claude (Anthropic) APIs and
LangChain
License: MIT
@@ -28,8 +28,8 @@
BuildRequires: %{python_module pip}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-anthropic >= 0.96.0
-Requires: python-langchain-core >= 1.5.0
+Requires: python-anthropic >= 0.120.0
+Requires: python-langchain-core >= 1.5.1
Requires: python-pydantic >= 2.7.4
BuildArch: noarch
# SECTION test requirements
++++++ langchain_anthropic-1.5.0.tar.gz -> langchain_anthropic-1.5.2.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.5.0/PKG-INFO
new/langchain_anthropic-1.5.2/PKG-INFO
--- old/langchain_anthropic-1.5.0/PKG-INFO 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_anthropic-1.5.2/PKG-INFO 2020-02-02 01:00:00.000000000
+0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: langchain-anthropic
-Version: 1.5.0
+Version: 1.5.2
Summary: Integration package connecting Claude (Anthropic) APIs and LangChain
Project-URL: Homepage,
https://docs.langchain.com/oss/python/integrations/providers/anthropic
Project-URL: Documentation,
https://reference.langchain.com/python/integrations/langchain_anthropic/
@@ -23,8 +23,8 @@
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: <4.0.0,>=3.10.0
-Requires-Dist: anthropic<1.0.0,>=0.96.0
-Requires-Dist: langchain-core<2.0.0,>=1.5.0
+Requires-Dist: anthropic<1.0.0,>=0.120.0
+Requires-Dist: langchain-core<2.0.0,>=1.5.1
Requires-Dist: pydantic<3.0.0,>=2.7.4
Description-Content-Type: text/markdown
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/langchain_anthropic/_version.py
new/langchain_anthropic-1.5.2/langchain_anthropic/_version.py
--- old/langchain_anthropic-1.5.0/langchain_anthropic/_version.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/langchain_anthropic/_version.py
2020-02-02 01:00:00.000000000 +0100
@@ -1,3 +1,3 @@
"""Version information for `langchain-anthropic`."""
-__version__ = "1.5.0"
+__version__ = "1.5.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/langchain_anthropic/chat_models.py
new/langchain_anthropic-1.5.2/langchain_anthropic/chat_models.py
--- old/langchain_anthropic-1.5.0/langchain_anthropic/chat_models.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/langchain_anthropic/chat_models.py
2020-02-02 01:00:00.000000000 +0100
@@ -48,7 +48,8 @@
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk,
ChatResult
from langchain_core.runnables import Runnable, RunnableMap, RunnablePassthrough
from langchain_core.tools import BaseTool
-from langchain_core.utils import from_env, get_pydantic_field_names,
secret_from_env
+from langchain_core.utils import from_env, get_pydantic_field_names
+from langchain_core.utils._gateway import _apply_gateway_config
from langchain_core.utils.function_calling import (
convert_to_json_schema,
convert_to_openai_tool,
@@ -959,24 +960,21 @@
stop_sequences: list[str] | None = Field(None, alias="stop")
"""Default stop sequences."""
- anthropic_api_url: str | None = Field(
- alias="base_url",
- default_factory=from_env(
- ["ANTHROPIC_API_URL", "ANTHROPIC_BASE_URL"],
- default="https://api.anthropic.com",
- ),
- )
+ anthropic_api_url: str | None = Field(default=None, alias="base_url")
"""Base URL for API requests. Only specify if using a proxy or service
emulator.
If a value isn't passed in, will attempt to read the value first from
`ANTHROPIC_API_URL` and if that is not set, `ANTHROPIC_BASE_URL`.
+
+ If `LANGSMITH_GATEWAY` is set, it is used as a fallback after those env
vars.
"""
- anthropic_api_key: SecretStr = Field(
- alias="api_key",
- default_factory=secret_from_env("ANTHROPIC_API_KEY", default=""),
- )
- """Automatically read from env var `ANTHROPIC_API_KEY` if not provided."""
+ anthropic_api_key: SecretStr = Field(default=SecretStr(""),
alias="api_key")
+ """Automatically read from env var `ANTHROPIC_API_KEY` if not provided.
+
+ If `LANGSMITH_GATEWAY` is enabled and the base URL points at the gateway,
+ `LANGSMITH_GATEWAY_API_KEY` is used instead.
+ """
anthropic_proxy: str | None = Field(
default_factory=from_env("ANTHROPIC_PROXY", default=None)
@@ -1021,17 +1019,19 @@
Examples:
- `#!python {"type": "enabled", "budget_tokens": 10_000}` (pre-4.7 models)
- - `#!python {"type": "adaptive"}` (Opus 4.6+, Sonnet 5)
- - `#!python {"type": "adaptive", "display": "summarized"}` (Opus 4.7+,
Sonnet 5)
- - `#!python {"type": "disabled"}` (Sonnet 5, where adaptive thinking is
- on by default)
+ - `#!python {"type": "adaptive"}` (Opus 4.6+, Opus 5, Sonnet 5)
+ - `#!python {"type": "adaptive", "display": "summarized"}` (Opus 4.7+,
+ Opus 5, Sonnet 5)
+ - `#!python {"type": "disabled"}` (Opus 5 and Sonnet 5, where adaptive
+ thinking is on by default)
- !!! note "Claude Opus 4.7+ and Sonnet 5"
+ !!! note "Claude Opus 4.7+, Opus 5, and Sonnet 5"
`budget_tokens` is removed on these models — use `{"type": "adaptive"}`
with `output_config.effort` to control reasoning effort. The default
`display` is `"omitted"`; set it to `"summarized"` to receive
- summarized reasoning in the response.
+ summarized reasoning in the response. On Opus 5, disabled thinking is
+ supported only at `"high"` effort or below.
"""
output_config: dict[str, Any] | None = None
@@ -1208,6 +1208,31 @@
self._add_version("langchain-anthropic", __version__)
return self
+ @model_validator(mode="before")
+ @classmethod
+ def _resolve_gateway(cls, values: Any) -> Any:
+ """Resolve the base URL and API key, applying LangSmith gateway
settings.
+
+ An explicit ``base_url``/``api_key`` always wins. Otherwise the base
URL
+ falls back to ``ANTHROPIC_API_URL``/``ANTHROPIC_BASE_URL``, then the
+ LangSmith gateway, then the Anthropic default. The gateway key is
+ preferred only when the base URL came from the gateway; for any other
+ endpoint the provider key wins, and the gateway key is a candidate only
+ when the gateway is enabled.
+ """
+ if isinstance(values, dict):
+ _apply_gateway_config(
+ values,
+ cls,
+ base_url_field="anthropic_api_url",
+ api_key_field="anthropic_api_key",
+ provider_path="anthropic",
+ base_url_env=["ANTHROPIC_API_URL", "ANTHROPIC_BASE_URL"],
+ api_key_env="ANTHROPIC_API_KEY",
+ default_base_url="https://api.anthropic.com",
+ )
+ return values
+
def _resolve_model_profile(self) -> ModelProfile | None:
profile = _get_default_model_profile(self.model) or None
if profile is not None and self.betas and "context-1m-2025-08-07" in
self.betas:
@@ -1265,6 +1290,51 @@
}
return anthropic.AsyncClient(**params)
+ def _assert_valid_model_configuration(self, kwargs: Mapping[str, Any]) ->
None:
+ """Validate resolved request configuration against model-specific
invariants."""
+ request_config = {**self.model_kwargs, **kwargs}
+ thinking = request_config.get("thinking")
+ if self.thinking is not None:
+ thinking = self.thinking
+
+ output_config = dict(self.output_config or {})
+ if self.reasoning_effort:
+ output_config["effort"] = self.reasoning_effort
+ request_output_config = request_config.get("output_config")
+ if isinstance(request_output_config, dict):
+ output_config.update(request_output_config)
+ effort = request_config.get("effort")
+ if effort is None:
+ effort = request_config.get("reasoning_effort")
+ if effort:
+ output_config["effort"] = effort
+
+ if (
+ self.model.startswith("claude-opus-5")
+ and isinstance(thinking, Mapping)
+ and thinking.get("type") == "enabled"
+ ):
+ msg = (
+ '`thinking={"type": "enabled", "budget_tokens": ...}` is not '
+ f"supported for {self.model}; use adaptive thinking and "
+ "`output_config.effort` instead."
+ )
+ raise ValueError(msg)
+
+ if (
+ self.model.startswith("claude-opus-5")
+ and isinstance(thinking, Mapping)
+ and thinking.get("type") == "disabled"
+ and output_config.get("effort") in {"xhigh", "max"}
+ ):
+ msg = (
+ '`thinking={"type": "disabled"}` is not supported for '
+ f"{self.model} with "
+ f"`output_config.effort={output_config['effort']!r}`; use
adaptive "
+ "thinking, omit `thinking`, or set effort to `high` or below."
+ )
+ raise ValueError(msg)
+
def _get_request_payload(
self,
input_: LanguageModelInput,
@@ -1273,6 +1343,7 @@
**kwargs: Any,
) -> dict:
"""Get the request payload for the Anthropic API."""
+ self._assert_valid_model_configuration(kwargs)
messages = self._convert_input(input_).to_messages()
for idx, message in enumerate(messages):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/langchain_anthropic/data/_profiles.py
new/langchain_anthropic-1.5.2/langchain_anthropic/data/_profiles.py
--- old/langchain_anthropic-1.5.0/langchain_anthropic/data/_profiles.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/langchain_anthropic/data/_profiles.py
2020-02-02 01:00:00.000000000 +0100
@@ -297,7 +297,41 @@
"video_outputs": False,
"reasoning_output": True,
"tool_calling": True,
- "structured_output": False,
+ "structured_output": True,
+ "attachment": True,
+ "temperature": False,
+ "image_url_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ "tool_call_streaming": True,
+ "reasoning_effort_levels": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max",
+ ],
+ "reasoning_effort_default": "high",
+ },
+ "claude-opus-5": {
+ "name": "Claude Opus 5",
+ "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,
+ "structured_output": True,
"attachment": True,
"temperature": False,
"image_url_inputs": True,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/langchain_anthropic/data/profile_augmentations.toml
new/langchain_anthropic-1.5.2/langchain_anthropic/data/profile_augmentations.toml
---
old/langchain_anthropic-1.5.0/langchain_anthropic/data/profile_augmentations.toml
2020-02-02 01:00:00.000000000 +0100
+++
new/langchain_anthropic-1.5.2/langchain_anthropic/data/profile_augmentations.toml
2020-02-02 01:00:00.000000000 +0100
@@ -42,6 +42,12 @@
reasoning_effort_default = "high"
[overrides."claude-opus-4-8"]
+structured_output = true
+reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
+reasoning_effort_default = "high"
+
+[overrides."claude-opus-5"]
+structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.5.0/pyproject.toml
new/langchain_anthropic-1.5.2/pyproject.toml
--- old/langchain_anthropic-1.5.0/pyproject.toml 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/pyproject.toml 2020-02-02
01:00:00.000000000 +0100
@@ -20,11 +20,11 @@
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
-version = "1.5.0"
+version = "1.5.2"
requires-python = ">=3.10.0,<4.0.0"
dependencies = [
- "anthropic>=0.96.0,<1.0.0",
- "langchain-core>=1.5.0,<2.0.0",
+ "anthropic>=0.120.0,<1.0.0",
+ "langchain-core>=1.5.1,<2.0.0",
"pydantic>=2.7.4,<3.0.0",
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/tests/integration_tests/test_chat_models.py
new/langchain_anthropic-1.5.2/tests/integration_tests/test_chat_models.py
--- old/langchain_anthropic-1.5.0/tests/integration_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/tests/integration_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
@@ -1353,13 +1353,13 @@
def test_reasoning_effort_defaults_adaptive_thinking() -> None:
"""`reasoning_effort` defaults `thinking` to adaptive on models that
support it.
- Regression test for a model (Opus 4.7+, Sonnet 5) actually accepting the
+ Regression test for a model (Opus 4.7+, Opus 5, Sonnet 5) actually
accepting the
resulting `{"type": "adaptive", "display": "summarized"}` thinking config,
not just that the payload is well-formed locally.
"""
llm = ChatAnthropic(
- model="claude-opus-4-7",
- reasoning_effort="xhigh",
+ model="claude-opus-5",
+ reasoning_effort="high",
max_tokens=2_000,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.5.0/tests/unit_tests/test_chat_models.py
new/langchain_anthropic-1.5.2/tests/unit_tests/test_chat_models.py
--- old/langchain_anthropic-1.5.0/tests/unit_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.5.2/tests/unit_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
@@ -2826,6 +2826,20 @@
}
+def test_claude_opus_5_profile_supports_structured_output() -> None:
+ model = ChatAnthropic(model="claude-opus-5")
+ assert model.profile
+ assert model.profile["structured_output"] is True
+ assert model.profile["max_input_tokens"] == 1_000_000
+ assert model.profile["reasoning_effort_levels"] == [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max",
+ ]
+
+
def test_profile() -> None:
model = ChatAnthropic(model="claude-sonnet-4-5-20250929")
assert model.profile
@@ -3034,12 +3048,12 @@
reasoning mode to apply it to. Only models whose profile advertises
`xhigh` (Opus 4.7+, Sonnet 5) accept this `thinking` shape.
"""
- model = ChatAnthropic(model="claude-opus-4-7", reasoning_effort="high")
+ model = ChatAnthropic(model="claude-opus-5", reasoning_effort="low")
payload = model._get_request_payload("Test query")
assert payload["thinking"] == {"type": "adaptive", "display": "summarized"}
- assert payload["output_config"]["effort"] == "high"
+ assert payload["output_config"]["effort"] == "low"
def test_reasoning_effort_as_call_time_kwarg_defaults_adaptive_thinking() ->
None:
@@ -3093,6 +3107,63 @@
assert payload["thinking"] == {"type": "disabled"}
[email protected]("effort", ["xhigh", "max"])
+def test_opus_5_rejects_disabled_thinking_at_high_effort(effort: str) -> None:
+ """Opus 5 permits disabled thinking only through `high` effort."""
+ model = ChatAnthropic(
+ model="claude-opus-5",
+ thinking={"type": "disabled"},
+ output_config={"effort": effort},
+ )
+
+ with pytest.raises(
+ ValueError,
+ match=r"not supported for claude-opus-5.*set effort to `high` or
below",
+ ):
+ model._get_request_payload("Test query")
+
+
+def test_opus_5_allows_disabled_thinking_at_high_effort() -> None:
+ """Opus 5 accepts disabled thinking at `high` effort."""
+ model = ChatAnthropic(
+ model="claude-opus-5",
+ thinking={"type": "disabled"},
+ output_config={"effort": "max"},
+ )
+
+ payload = model._get_request_payload("Test query",
output_config={"effort": "high"})
+
+ assert payload["thinking"] == {"type": "disabled"}
+ assert payload["output_config"]["effort"] == "high"
+
+
[email protected]("effort", ["xhigh", "max"])
+def test_opus_5_rejects_call_time_disabled_thinking_at_high_effort(
+ effort: str,
+) -> None:
+ """Preflight validates call-time effort overrides before message
conversion."""
+ model = ChatAnthropic(
+ model="claude-opus-5",
+ thinking={"type": "disabled"},
+ )
+
+ with pytest.raises(ValueError, match=r"not supported for claude-opus-5"):
+ model._get_request_payload("Test query", output_config={"effort":
effort})
+
+
[email protected]("effort", ["low", "medium", "high", "xhigh", "max"])
+def test_opus_5_rejects_manual_thinking_at_all_effort_levels(effort: str) ->
None:
+ """Opus 5 does not support manual extended thinking."""
+ model = ChatAnthropic(
+ model="claude-opus-5",
+ thinking={"type": "enabled", "budget_tokens": 1_024},
+ output_config={"effort": effort},
+ )
+
+ with pytest.raises(ValueError, match=r"use adaptive thinking"):
+ model._get_request_payload("Test query")
+
+
def test_effort_also_defaults_adaptive_thinking() -> None:
"""Test that `effort` composes with the adaptive-thinking default too.
@@ -3780,3 +3851,94 @@
message_finish = cast("dict[str, Any]", stream_events[-1])
assert message_finish["event"] == "message-finish"
assert message_finish["metadata"]["stop_reason"] == "tool_use"
+
+
+def test_langsmith_gateway_true(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME, api_key="test")
+ assert llm.anthropic_api_url ==
"https://gateway.smith.langchain.com/anthropic"
+
+
+def test_langsmith_gateway_false(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "false")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME, api_key="test")
+ assert llm.anthropic_api_url == "https://api.anthropic.com"
+
+
+def test_langsmith_gateway_unset(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.delenv("LANGSMITH_GATEWAY", raising=False)
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME, api_key="test")
+ assert llm.anthropic_api_url == "https://api.anthropic.com"
+
+
+def test_langsmith_gateway_custom_url(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "https://my-gateway.example.com/")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME, api_key="test")
+ assert llm.anthropic_api_url == "https://my-gateway.example.com/anthropic"
+
+
+def test_langsmith_gateway_provider_env_overrides_gateway(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.setenv("ANTHROPIC_BASE_URL", "https://api.anthropic.com")
+ llm = ChatAnthropic(model=MODEL_NAME, api_key="test")
+ assert llm.anthropic_api_url == "https://api.anthropic.com"
+
+
+def test_langsmith_gateway_api_key(monkeypatch: pytest.MonkeyPatch) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME)
+ assert llm.anthropic_api_key.get_secret_value() == "gateway-key"
+
+
+def test_langsmith_gateway_api_key_not_used_without_gateway(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.delenv("LANGSMITH_GATEWAY", raising=False)
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv("ANTHROPIC_API_KEY", "provider-key")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME)
+ assert llm.anthropic_api_key.get_secret_value() == "provider-key"
+
+
+def test_langsmith_gateway_api_key_overrides_provider_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv("ANTHROPIC_API_KEY", "provider-key")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
+ llm = ChatAnthropic(model=MODEL_NAME)
+ assert llm.anthropic_api_key.get_secret_value() == "gateway-key"
+
+
+def test_langsmith_gateway_provider_base_url_uses_provider_key(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ # Base URL overridden away from the gateway -> provider key wins over the
+ # gateway key, even though the gateway is enabled.
+ monkeypatch.setenv("LANGSMITH_GATEWAY", "true")
+ monkeypatch.setenv("LANGSMITH_GATEWAY_API_KEY", "gateway-key")
+ monkeypatch.setenv("ANTHROPIC_API_KEY", "provider-key")
+ monkeypatch.delenv("ANTHROPIC_API_URL", raising=False)
+ monkeypatch.setenv("ANTHROPIC_BASE_URL", "https://api.anthropic.com")
+ llm = ChatAnthropic(model=MODEL_NAME)
+ assert llm.anthropic_api_url == "https://api.anthropic.com"
+ assert llm.anthropic_api_key.get_secret_value() == "provider-key"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.5.0/uv.lock
new/langchain_anthropic-1.5.2/uv.lock
--- old/langchain_anthropic-1.5.0/uv.lock 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_anthropic-1.5.2/uv.lock 2020-02-02 01:00:00.000000000
+0100
@@ -29,7 +29,7 @@
[[package]]
name = "anthropic"
-version = "0.96.0"
+version = "0.120.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -41,9 +41,9 @@
{ name = "sniffio" },
{ name = "typing-extensions" },
]
-sdist = { url =
"https://files.pythonhosted.org/packages/b9/7e/672f533dee813028d2c699bfd2a7f52c9118d7353680d9aa44b9e23f717f/anthropic-0.96.0.tar.gz",
hash =
"sha256:9de947b737f39452f68aa520f1c2239d44119c9b73b0fb6d4e6ca80f00279ee6", size
= 658210, upload-time = "2026-04-16T14:28:02.846Z" }
+sdist = { url =
"https://files.pythonhosted.org/packages/92/5c/3331da4fc009d448008a50c78d86cc929e8c937cd1442245ce3f80561c4e/anthropic-0.120.0.tar.gz",
hash =
"sha256:6ba6007dc9b00365b20f6101a6618f5196ac1ceef81512e4b5cc0e7436d4975d", size
= 1008042, upload-time = "2026-07-24T16:32:52.384Z" }
wheels = [
- { url =
"https://files.pythonhosted.org/packages/48/5a/72f33204064b6e87601a71a6baf8d855769f8a0c1eaae8d06a1094872371/anthropic-0.96.0-py3-none-any.whl",
hash =
"sha256:9a6e335a354602a521cd9e777e92bfd46ba6e115bf9bbfe6135311e8fb2015b2", size
= 635930, upload-time = "2026-04-16T14:28:01.436Z" },
+ { url =
"https://files.pythonhosted.org/packages/1b/8a/8522bdf809e1f95f0d9c936540987a3f6afba01d2921a2bf488dedf836a8/anthropic-0.120.0-py3-none-any.whl",
hash =
"sha256:591bd531563ec7b63a1e138f5c11f14cb94edda99623b349c2ce2ece8e08b8a5", size
= 1022602, upload-time = "2026-07-24T16:32:50.506Z" },
]
[[package]]
@@ -617,7 +617,7 @@
[[package]]
name = "langchain-anthropic"
-version = "1.5.0"
+version = "1.5.2"
source = { editable = "." }
dependencies = [
{ name = "anthropic" },
@@ -657,7 +657,7 @@
[package.metadata]
requires-dist = [
- { name = "anthropic", specifier = ">=0.96.0,<1.0.0" },
+ { name = "anthropic", specifier = ">=0.120.0,<1.0.0" },
{ name = "langchain-core", editable = "../../core" },
{ name = "pydantic", specifier = ">=2.7.4,<3.0.0" },
]
@@ -690,7 +690,7 @@
[[package]]
name = "langchain-core"
-version = "1.4.9"
+version = "1.5.1"
source = { editable = "../../core" }
dependencies = [
{ name = "jsonpatch" },