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-10-15 12:21:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-langchain-anthropic (Old)
and /work/SRC/openSUSE:Factory/.python-langchain-anthropic.new.3698736
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-langchain-anthropic"
Thu Oct 15 12:21:55 2026 rev:16 rq:1384900 version:1.7.6
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-langchain-anthropic/python-langchain-anthropic.changes
2026-10-01 16:45:34.571346830 +0200
+++
/work/SRC/openSUSE:Factory/.python-langchain-anthropic.new.3698736/python-langchain-anthropic.changes
2026-10-15 12:22:00.039738592 +0200
@@ -1,0 +2,9 @@
+Thu Oct 15 04:53:04 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 1.7.6:
+ * Mid-conversation system-message handling follows the model
+ profile (langchain-core 1.6.10) instead of a hardcoded model
+ name list; warning text updated accordingly
+ * Require langchain-core >= 1.6.10 for the new profile fields
+
+-------------------------------------------------------------------
Old:
----
langchain_anthropic-1.7.5.tar.gz
New:
----
langchain_anthropic-1.7.6.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-langchain-anthropic.spec ++++++
--- /var/tmp/diff_new_pack.gI18jH/_old 2026-10-15 12:22:00.688765750 +0200
+++ /var/tmp/diff_new_pack.gI18jH/_new 2026-10-15 12:22:00.690765834 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-langchain-anthropic
-Version: 1.7.5
+Version: 1.7.6
Release: 0
Summary: Integration package connecting Claude (Anthropic) APIs and
LangChain
License: MIT
@@ -29,7 +29,7 @@
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-anthropic >= 0.120.0
-Requires: python-langchain-core >= 1.6.6
+Requires: python-langchain-core >= 1.6.10
Requires: python-pydantic >= 2.7.4
BuildArch: noarch
# SECTION test requirements
@@ -37,7 +37,7 @@
BuildRequires: %{python_module blockbuster}
BuildRequires: %{python_module defusedxml}
BuildRequires: %{python_module freezegun}
-BuildRequires: %{python_module langchain-core >= 1.6.6}
+BuildRequires: %{python_module langchain-core >= 1.6.10}
BuildRequires: %{python_module pydantic >= 2.7.4}
BuildRequires: %{python_module pytest-asyncio}
BuildRequires: %{python_module pytest-mock}
++++++ langchain_anthropic-1.7.5.tar.gz -> langchain_anthropic-1.7.6.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.7.5/PKG-INFO
new/langchain_anthropic-1.7.6/PKG-INFO
--- old/langchain_anthropic-1.7.5/PKG-INFO 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_anthropic-1.7.6/PKG-INFO 2020-02-02 01:00:00.000000000
+0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.5
Name: langchain-anthropic
-Version: 1.7.5
+Version: 1.7.6
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/
@@ -24,7 +24,7 @@
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: <4.0.0,>=3.10.0
Requires-Dist: anthropic<2.0.0,>=0.120.0
-Requires-Dist: langchain-core<2.0.0,>=1.6.6
+Requires-Dist: langchain-core<2.0.0,>=1.6.10
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.7.5/langchain_anthropic/_version.py
new/langchain_anthropic-1.7.6/langchain_anthropic/_version.py
--- old/langchain_anthropic-1.7.5/langchain_anthropic/_version.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/langchain_anthropic/_version.py
2020-02-02 01:00:00.000000000 +0100
@@ -1,3 +1,3 @@
"""Version information for `langchain-anthropic`."""
-__version__ = "1.7.5"
+__version__ = "1.7.6"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.7.5/langchain_anthropic/chat_models.py
new/langchain_anthropic-1.7.6/langchain_anthropic/chat_models.py
--- old/langchain_anthropic-1.7.5/langchain_anthropic/chat_models.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/langchain_anthropic/chat_models.py
2020-02-02 01:00:00.000000000 +0100
@@ -625,10 +625,10 @@
warnings.warn(
f"Tool-change block {block_type!r} was dropped: it is only
"
"valid on a `SystemMessage` sent in place, and this one
was "
- "hoisted into the top-level `system` field. Use a model
that "
- "supports mid-conversation system messages and place the "
- "message after a human or tool message, either last or
before "
- f"an AI message (model: {model!r}).",
+ "hoisted into the top-level `system` field. Use a model
whose "
+ "profile sets `mid_conversation_system_messages` and place
"
+ "the message after a human or tool message, either last or
"
+ f"before an AI message (model: {model!r}).",
UserWarning,
stacklevel=stacklevel,
)
@@ -648,8 +648,9 @@
warnings.warn(
"A non-leading `SystemMessage` was moved to the top-level `system`
field "
"and now applies to the entire conversation. To send it in place, use
a "
- "supported model and place it after a human or tool message, either
last "
- f"or before an AI message (model: {model!r}).",
+ "model whose profile sets `mid_conversation_system_messages` and place
"
+ "it after a human or tool message, either last or before an AI message
"
+ f"(model: {model!r}).",
UserWarning,
stacklevel=3,
)
@@ -716,8 +717,16 @@
messages: Sequence[BaseMessage],
*,
model: str | None,
+ mid_conversation_system_messages: bool = False,
) -> tuple[str | list[dict] | None, list[dict]]:
- """Format messages for Anthropic's API."""
+ """Format messages for Anthropic's API.
+
+ Args:
+ messages: Messages to format.
+ model: The model the request targets, used only in warning text.
+ mid_conversation_system_messages: Whether a non-leading system message
+ may be sent in place. When `False`, it is hoisted into `system`.
+ """
system: str | list[dict] | None = None
formatted_messages: list[dict] = []
toolsets: dict[str, str] = {}
@@ -736,7 +745,7 @@
preserve_tool_changes=True,
)
continue
- if _supports_mid_conversation_system_messages(model) and (
+ if mid_conversation_system_messages and (
pending_system
or _previous_turn_allows_system(
formatted_messages[-1] if formatted_messages else None
@@ -1143,21 +1152,6 @@
return tuple(levels)
-def _supports_mid_conversation_system_messages(model: object) -> bool:
- """Return whether the model supports mid-conversation system messages."""
- if not isinstance(model, str):
- return False
- return model.startswith(
- (
- "claude-fable-5",
- "claude-mythos-5",
- "claude-opus-4-8",
- "claude-opus-5",
- "claude-sonnet-5-5",
- )
- )
-
-
def _supports_forced_tool_choice(model: str) -> bool:
"""Return whether the model accepts `tool_choice` types `any` and
`tool`."""
return not model.startswith(
@@ -1901,7 +1895,13 @@
}
)
- system, formatted_messages = _format_messages(messages,
model=self.model)
+ system, formatted_messages = _format_messages(
+ messages,
+ model=self.model,
+ mid_conversation_system_messages=bool(
+ (self.profile or {}).get("mid_conversation_system_messages")
+ ),
+ )
if isinstance(system, list) and not system:
# Every block was narrowed away (or the message was empty to begin
# with). An empty block array carries no instructions, so drop the
@@ -3095,7 +3095,11 @@
```
""" # noqa: D214
formatted_system, formatted_messages = _format_messages(
- messages, model=self.model
+ messages,
+ model=self.model,
+ mid_conversation_system_messages=bool(
+ (self.profile or {}).get("mid_conversation_system_messages")
+ ),
)
if formatted_system is not None:
kwargs["system"] = formatted_system
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.7.5/langchain_anthropic/data/_profiles.py
new/langchain_anthropic-1.7.6/langchain_anthropic/data/_profiles.py
--- old/langchain_anthropic-1.7.5/langchain_anthropic/data/_profiles.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/langchain_anthropic/data/_profiles.py
2020-02-02 01:00:00.000000000 +0100
@@ -49,6 +49,8 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
"claude-fable-5-1": {
"name": "Claude Fable 5.1",
@@ -83,6 +85,8 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
"claude-haiku-4-5": {
"name": "Claude Haiku 4.5 (latest)",
@@ -136,6 +140,54 @@
"image_tool_message": True,
"tool_call_streaming": True,
},
+ "claude-haiku-5-5": {
+ "name": "Claude Haiku 5.5",
+ "release_date": "2026-10-07",
+ "last_updated": "2026-10-07",
+ "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,
+ "tool_call_streaming": True,
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
+ },
+ "claude-mythos-5": {
+ "image_url_inputs": True,
+ "pdf_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ "structured_output": False,
+ "tool_call_streaming": True,
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
+ },
+ "claude-mythos-5-1": {
+ "image_url_inputs": True,
+ "pdf_inputs": True,
+ "pdf_tool_message": True,
+ "image_tool_message": True,
+ "structured_output": False,
+ "tool_call_streaming": True,
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
+ },
"claude-opus-4-5": {
"name": "Claude Opus 4.5 (latest)",
"release_date": "2025-11-24",
@@ -300,6 +352,8 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
"claude-opus-5": {
"name": "Claude Opus 5",
@@ -334,6 +388,8 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
"claude-opus-5-5": {
"name": "Claude Opus 5.5",
@@ -368,13 +424,15 @@
"max",
],
"reasoning_effort_default": "medium",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
"claude-sonnet-4-5": {
"name": "Claude Sonnet 4.5 (latest)",
"release_date": "2025-09-29",
"last_updated": "2025-09-29",
"open_weights": False,
- "max_input_tokens": 1000000,
+ "max_input_tokens": 200000,
"max_output_tokens": 64000,
"text_inputs": True,
"image_inputs": True,
@@ -400,7 +458,7 @@
"release_date": "2025-09-29",
"last_updated": "2025-09-29",
"open_weights": False,
- "max_input_tokens": 1000000,
+ "max_input_tokens": 200000,
"max_output_tokens": 64000,
"text_inputs": True,
"image_inputs": True,
@@ -487,6 +545,8 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": False,
},
"claude-sonnet-5-5": {
"name": "Claude Sonnet 5.5",
@@ -522,5 +582,7 @@
"max",
],
"reasoning_effort_default": "high",
+ "mid_conversation_system_messages": True,
+ "mid_conversation_tools": True,
},
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.7.5/langchain_anthropic/data/profile_augmentations.toml
new/langchain_anthropic-1.7.6/langchain_anthropic/data/profile_augmentations.toml
---
old/langchain_anthropic-1.7.5/langchain_anthropic/data/profile_augmentations.toml
2020-02-02 01:00:00.000000000 +0100
+++
new/langchain_anthropic-1.7.6/langchain_anthropic/data/profile_augmentations.toml
2020-02-02 01:00:00.000000000 +0100
@@ -42,34 +42,61 @@
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-opus-5"]
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-opus-5-5"]
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "medium"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-sonnet-5-5"]
structured_output = true
tool_choice = false
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-sonnet-5"]
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = false
+
+[overrides."claude-haiku-5-5"]
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-fable-5"]
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
[overrides."claude-fable-5-1"]
structured_output = true
reasoning_effort_levels = ["low", "medium", "high", "xhigh", "max"]
reasoning_effort_default = "high"
+mid_conversation_system_messages = true
+mid_conversation_tools = true
+
+# Not in models.dev (Project Glasswing only), so these entries are the whole
profile.
+[overrides."claude-mythos-5"]
+mid_conversation_system_messages = true
+mid_conversation_tools = true
+
+[overrides."claude-mythos-5-1"]
+mid_conversation_system_messages = true
+mid_conversation_tools = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.7.5/pyproject.toml
new/langchain_anthropic-1.7.6/pyproject.toml
--- old/langchain_anthropic-1.7.5/pyproject.toml 2020-02-02
01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/pyproject.toml 2020-02-02
01:00:00.000000000 +0100
@@ -20,11 +20,11 @@
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
-version = "1.7.5"
+version = "1.7.6"
requires-python = ">=3.10.0,<4.0.0"
dependencies = [
"anthropic>=0.120.0,<2.0.0",
- "langchain-core>=1.6.6,<2.0.0",
+ "langchain-core>=1.6.10,<2.0.0",
"pydantic>=2.7.4,<3.0.0",
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.7.5/tests/unit_tests/test_chat_models.py
new/langchain_anthropic-1.7.6/tests/unit_tests/test_chat_models.py
--- old/langchain_anthropic-1.7.5/tests/unit_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/tests/unit_tests/test_chat_models.py
2020-02-02 01:00:00.000000000 +0100
@@ -1721,7 +1721,9 @@
},
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert expected_messages == actual_messages
@@ -1795,7 +1797,9 @@
HumanMessage("Review foo()"),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "You are a code reviewer."
assert actual_messages == [{"role": "user", "content": "Review foo()"}]
@@ -1811,7 +1815,9 @@
SystemMessage("Every suggestion must include type annotations."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "You are a code reviewer."
assert actual_messages == [
@@ -1832,7 +1838,9 @@
SystemMessage("Be concise."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages == [
@@ -1849,7 +1857,9 @@
AIMessage("Looks fine."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages == [
@@ -1872,7 +1882,9 @@
SystemMessage("Be concise."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert [message["role"] for message in actual_messages] == [
@@ -1909,7 +1921,9 @@
SystemMessage("Be concise."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert [message["role"] for message in actual_messages] == [
@@ -1933,7 +1947,9 @@
]
with pytest.warns(UserWarning, match=_HOIST_WARNING):
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "Be concise."
assert [message["role"] for message in actual_messages] == ["user",
"assistant"]
@@ -1948,7 +1964,9 @@
]
with pytest.warns(UserWarning, match=_HOIST_WARNING):
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "Be concise."
assert actual_messages == [
@@ -1966,7 +1984,9 @@
]
with pytest.warns(UserWarning, match=_HOIST_WARNING):
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "Be concise."
assert actual_messages == [
@@ -1984,7 +2004,9 @@
SystemMessage("Every suggestion must include type annotations."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == [
{"type": "text", "text": "You are a code reviewer."},
@@ -2009,7 +2031,9 @@
SystemMessage("Include type annotations."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages == [
@@ -2032,7 +2056,9 @@
HumanMessage("Review bar()"),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages == [
@@ -2056,11 +2082,15 @@
with pytest.raises(
ValueError, match=r"Received multiple non-consecutive system
messages\."
):
- _format_messages(messages, model=MID_CONVERSATION_SYSTEM_MODEL)
+ _format_messages(
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
+ )
-def test__format_messages_non_leading_system_hoisted_on_unsupported_model() ->
None:
- """Test unsupported models hoist non-leading system messages."""
+def test__format_messages_non_leading_system_hoisted_by_default() -> None:
+ """Without the capability, it is hoisted, and the warning omits its
text."""
messages = [
HumanMessage("Review foo()"),
SystemMessage("Be concise."),
@@ -2074,57 +2104,54 @@
assert actual_messages == [{"role": "user", "content": "Review foo()"}]
-def test__format_messages_non_leading_system_hoisted_on_sonnet_5() -> None:
- """Sonnet 5 is a current model that does not support the feature."""
- messages = [
- HumanMessage("Review foo()"),
- SystemMessage("Be concise."),
- ]
- with pytest.warns(UserWarning, match=_HOIST_WARNING):
- actual_system, actual_messages = _format_messages(
- messages, model="claude-sonnet-5"
- )
- assert actual_system == "Be concise."
- assert actual_messages == [{"role": "user", "content": "Review foo()"}]
+def test_non_leading_system_in_place_when_profile_declares_it() -> None:
+ """The profile decides, so a Bedrock model ID sends it in place too."""
+ model = ChatAnthropic(
+ model="global.anthropic.claude-opus-5-5",
+ profile={"mid_conversation_system_messages": True},
+ )
+ payload = model._get_request_payload(
+ [HumanMessage("Review foo()"), SystemMessage("Be concise.")]
+ )
+ assert "system" not in payload
+ assert payload["messages"][-1] == {"role": "system", "content": "Be
concise."}
-def test__format_messages_non_leading_system_hoisted_on_platform_model_id() ->
None:
- """Test platform-prefixed model identifiers do not match."""
- messages = [
- HumanMessage("Review foo()"),
- SystemMessage("Be concise."),
- ]
[email protected]("profile", [{}, {"mid_conversation_system_messages":
False}])
+def test_non_leading_system_hoisted_when_profile_does_not_declare_it(
+ profile: dict,
+) -> None:
+ """Absent or `False` both hoist, even for a model that supports it."""
+ model = ChatAnthropic(model="claude-opus-5-5", profile=profile)
with pytest.warns(UserWarning, match=_HOIST_WARNING):
- actual_system, _ = _format_messages(
- messages, model="us.anthropic.claude-opus-5-v1:0"
+ payload = model._get_request_payload(
+ [HumanMessage("Review foo()"), SystemMessage("Be concise.")]
)
- assert actual_system == "Be concise."
+ assert payload["system"] == "Be concise."
+ assert payload["messages"] == [{"role": "user", "content": "Review foo()"}]
@pytest.mark.parametrize(
- "model",
- ["claude-opus-5-1", "claude-fable-5-1", "claude-mythos-5-2",
"claude-opus-4-8"],
+ ("model", "system_messages", "tools"),
+ [
+ ("claude-opus-5-5", True, True),
+ ("claude-haiku-5-5", True, True),
+ # Sonnet 5 accepts a mid-conversation system message but rejects tools
in it.
+ ("claude-sonnet-5", True, False),
+ # Mythos isn't in models.dev, so its profile comes from augmentations
alone.
+ ("claude-mythos-5", True, True),
+ ("claude-mythos-5-1", True, True),
+ ("claude-mythos-preview", None, None),
+ ("claude-opus-4-5", None, None),
+ ],
)
-def test__format_messages_supported_model_prefixes_match_forward(model: str)
-> None:
- """A later point release of a supported family needs no edit here."""
- messages = [
- HumanMessage("Review foo()"),
- SystemMessage("Be concise."),
- ]
- _, actual_messages = _format_messages(messages, model=model)
- assert actual_messages[-1] == {"role": "system", "content": "Be concise."}
-
-
[email protected]("model", ["claude-opus-4-5", "claude-mythos-preview"])
-def test__format_messages_unsupported_model_prefixes_hoist(model: str) -> None:
- """Prefixes that must not match: pre-4-8 Opus, and unversioned Mythos."""
- messages = [
- HumanMessage("Review foo()"),
- SystemMessage("Be concise."),
- ]
- with pytest.warns(UserWarning, match=_HOIST_WARNING):
- actual_system, _ = _format_messages(messages, model=model)
- assert actual_system == "Be concise."
+def test_profile_declares_mid_conversation_capabilities(
+ model: str, *, system_messages: bool | None, tools: bool | None
+) -> None:
+ """Profiles carry the capabilities live probes show each model accepts."""
+ profile = ChatAnthropic(model=model).profile or {}
+ assert profile.get("mid_conversation_system_messages") is system_messages
+ assert profile.get("mid_conversation_tools") is tools
def test__format_messages_second_unplaceable_system_run_raises() -> None:
@@ -2138,7 +2165,11 @@
with pytest.raises(
ValueError, match=r"Received multiple non-consecutive system
messages\."
):
- _format_messages(messages, model=MID_CONVERSATION_SYSTEM_MODEL)
+ _format_messages(
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
+ )
def test__format_messages_system_cache_control_preserved_in_both_paths() ->
None:
@@ -2150,7 +2181,9 @@
}
in_place_messages = [HumanMessage("Review foo()"), SystemMessage([block])]
actual_system, actual_messages = _format_messages(
- in_place_messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ in_place_messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages[-1] == {"role": "system", "content": [block]}
@@ -2167,7 +2200,9 @@
SystemMessage(content_blocks=[create_text_block("Be concise.")]),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages[-1] == {
@@ -2185,6 +2220,7 @@
_, actual_messages = _format_messages(
[human, AIMessage("thought "), system],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages[-1]["content"] == "thought"
@@ -2192,6 +2228,7 @@
_, actual_messages = _format_messages(
[human, AIMessage([{"type": "text", "text": "thought "}]), system],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages[-1]["content"][0]["text"] == "thought" # type:
ignore[index]
@@ -2202,6 +2239,7 @@
_, actual_messages = _format_messages(
[HumanMessage("Review foo()"), AIMessage(""), SystemMessage("Be
concise.")],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages == [
{"role": "user", "content": "Review foo()"},
@@ -2218,7 +2256,9 @@
AIMessage("Looks fine."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages == [
@@ -2238,7 +2278,9 @@
]
with pytest.warns(UserWarning, match=_HOIST_WARNING):
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == "Be concise."
assert actual_messages == [
@@ -2272,6 +2314,7 @@
_, actual_messages = _format_messages(
[HumanMessage("Review foo()"), SystemMessage([block])],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages[-1] == {
"role": "system",
@@ -2308,7 +2351,9 @@
AIMessage("Looks fine."),
]
actual_system, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system is None
assert actual_messages[1] == {"role": "system", "content": [block]}
@@ -2329,8 +2374,14 @@
SystemMessage([{"type": "non_standard", "value": block}]),
AIMessage("Looks fine."),
]
- assert _format_messages(bare, model=MID_CONVERSATION_SYSTEM_MODEL) == (
- _format_messages(wrapped, model=MID_CONVERSATION_SYSTEM_MODEL)
+ assert _format_messages(
+ bare, model=MID_CONVERSATION_SYSTEM_MODEL,
mid_conversation_system_messages=True
+ ) == (
+ _format_messages(
+ wrapped,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
+ )
)
@@ -2355,9 +2406,11 @@
assert _format_messages(
[conversation[0], bare, conversation[1]],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
) == _format_messages(
[conversation[0], wrapped, conversation[1]],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
@@ -2368,7 +2421,11 @@
SystemMessage([{"type": "text", "text": "Be concise."},
_TOOL_REMOVAL_BLOCK]),
AIMessage("Looks fine."),
]
- _, actual_messages = _format_messages(messages,
model=MID_CONVERSATION_SYSTEM_MODEL)
+ _, actual_messages = _format_messages(
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
+ )
assert actual_messages[1] == {
"role": "system",
"content": [{"type": "text", "text": "Be concise."},
_TOOL_REMOVAL_BLOCK],
@@ -2389,7 +2446,9 @@
]
with pytest.warns(UserWarning, match=_UNRECOGNIZED_SYSTEM_BLOCK_WARNING):
_, actual_messages = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages[1] == {
"role": "system",
@@ -2410,7 +2469,9 @@
]
with pytest.warns(UserWarning, match=_UNRECOGNIZED_SYSTEM_BLOCK_WARNING):
actual_system, _ = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == [{"type": "text", "text": "Be concise."}]
@@ -2428,6 +2489,7 @@
actual_system, actual_messages = _format_messages(
[SystemMessage(content), HumanMessage("Review foo()")],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_system == [block]
assert actual_messages == [{"role": "user", "content": "Review foo()"}]
@@ -2462,7 +2524,9 @@
]
with pytest.warns(UserWarning, match=_TOOL_CHANGE_UNSUPPORTED_WARNING) as
record:
actual_system, _ = _format_messages(
- messages, model=MID_CONVERSATION_SYSTEM_MODEL
+ messages,
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
messages_warned = [str(warning.message) for warning in record]
assert any(_TOOL_CHANGE_UNSUPPORTED_WARNING in m for m in messages_warned)
@@ -2497,6 +2561,7 @@
AIMessage("Looks fine."),
],
model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert content == before
@@ -2508,7 +2573,9 @@
"source": {"type": "base64", "media_type": "image/png", "data":
"aGk="},
}
_, actual_messages = _format_messages(
- [HumanMessage([block])], model=MID_CONVERSATION_SYSTEM_MODEL
+ [HumanMessage([block])],
+ model=MID_CONVERSATION_SYSTEM_MODEL,
+ mid_conversation_system_messages=True,
)
assert actual_messages == [{"role": "user", "content": [block]}]
@@ -3113,6 +3180,21 @@
assert call_args["system"] == [{"type": "text", "text": "You are a
scientist"}]
+def test_get_num_tokens_from_messages_keeps_mid_conversation_system_in_place()
-> None:
+ """Counting reads the profile like a request does, so the turn stays in
place."""
+ llm = ChatAnthropic(
+ model=MODEL_NAME, profile={"mid_conversation_system_messages": True}
+ )
+ messages = [HumanMessage("Review foo()"), SystemMessage("Be concise.")]
+
+ with patch.object(anthropic, "Client") as _client:
+ llm.get_num_tokens_from_messages(messages)
+
+ call_args = _client.return_value.messages.count_tokens.call_args.kwargs
+ assert "system" not in call_args
+ assert call_args["messages"][-1] == {"role": "system", "content": "Be
concise."}
+
+
def test_usage_metadata_standardization() -> None:
class UsageModel(BaseModel):
input_tokens: int = 10
@@ -4728,7 +4810,7 @@
def test_profile_1m_context_beta() -> None:
model = ChatAnthropic(model="claude-sonnet-4-5")
assert model.profile
- assert model.profile["max_input_tokens"] == 1000000
+ assert model.profile["max_input_tokens"] == 200000
model = ChatAnthropic(model="claude-sonnet-4-5",
betas=["context-1m-2025-08-07"])
assert model.profile
@@ -4739,7 +4821,7 @@
betas=["token-efficient-tools-2025-02-19"],
)
assert model.profile
- assert model.profile["max_input_tokens"] == 1000000
+ assert model.profile["max_input_tokens"] == 200000
async def test_model_profile_not_blocking() -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/langchain_anthropic-1.7.5/tests/unit_tests/test_sonnet55.py
new/langchain_anthropic-1.7.6/tests/unit_tests/test_sonnet55.py
--- old/langchain_anthropic-1.7.5/tests/unit_tests/test_sonnet55.py
2020-02-02 01:00:00.000000000 +0100
+++ new/langchain_anthropic-1.7.6/tests/unit_tests/test_sonnet55.py
2020-02-02 01:00:00.000000000 +0100
@@ -20,7 +20,6 @@
from langchain_core.runnables import RunnableBinding, RunnableSequence
from langchain_anthropic import ChatAnthropic
-from langchain_anthropic.chat_models import _format_messages
MODEL = "claude-sonnet-5-5"
TOOL = {"name": "answer", "input_schema": {"type": "object", "properties": {}}}
@@ -139,7 +138,7 @@
def test_mid_conversation_system() -> None:
- system, messages = _format_messages(
+ payload = model()._get_request_payload(
[
SystemMessage("initial"),
HumanMessage("hello"),
@@ -147,10 +146,14 @@
AIMessage("answer"),
HumanMessage("next"),
],
- model=MODEL,
)
- assert system == "initial"
- assert [m["role"] for m in messages] == ["user", "system", "assistant",
"user"]
+ assert payload["system"] == "initial"
+ assert [m["role"] for m in payload["messages"]] == [
+ "user",
+ "system",
+ "assistant",
+ "user",
+ ]
@pytest.mark.parametrize("standard", [False, True])
@@ -334,11 +337,10 @@
"type": "tool_addition",
"tool": {"type": "tool_reference", "name": "answer"},
}
- _, messages = _format_messages(
+ payload = model()._get_request_payload(
[HumanMessage("hello"), SystemMessage([block]), AIMessage("answer")],
- model=MODEL,
)
- assert messages[1] == {"role": "system", "content": [block]}
+ assert payload["messages"][1] == {"role": "system", "content": [block]}
def test_default_thinking_stream_preserves_signature() -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/langchain_anthropic-1.7.5/uv.lock
new/langchain_anthropic-1.7.6/uv.lock
--- old/langchain_anthropic-1.7.5/uv.lock 2020-02-02 01:00:00.000000000
+0100
+++ new/langchain_anthropic-1.7.6/uv.lock 2020-02-02 01:00:00.000000000
+0100
@@ -334,7 +334,7 @@
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "python_full_version < '3.11'" },
+ { name = "typing-extensions" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz",
hash =
"sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size
= 29749, upload-time = "2025-05-10T17:42:51.123Z" }
wheels = [
@@ -395,8 +395,8 @@
version = "2.12.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "h11", marker = "python_full_version != '3.12.*' or sys_platform
!= 'emscripten'" },
- { name = "truststore", marker = "python_full_version != '3.12.*' or
sys_platform != 'emscripten'" },
+ { name = "h11" },
+ { name = "truststore" },
]
sdist = { url =
"https://files.pythonhosted.org/packages/be/ad/f4f0e57345f1870f3e8cb624e058d7eca6e5a27d33bcc3311d9b618734cd/httpcore2-2.12.0.tar.gz",
hash =
"sha256:9293522bba0aa7c4c8e9e3f040c16575bd8868e155a77fa30c7a9085a5eae648", size
= 67548, upload-time = "2026-08-18T13:22:08.211Z" }
wheels = [
@@ -582,7 +582,7 @@
[[package]]
name = "langchain"
-version = "1.4.3"
+version = "1.4.4"
source = { editable = "../../langchain_v1" }
dependencies = [
{ name = "langchain-core" },
@@ -592,7 +592,7 @@
[package.metadata]
requires-dist = [
- { name = "fastmcp", marker = "extra == 'mcp'", specifier =
">=4.0.1,<5.0.0" },
+ { name = "fastmcp", marker = "extra == 'mcp'", specifier =
">=4.0.11,<5.0.0" },
{ name = "langchain-anthropic", marker = "extra == 'anthropic'", editable
= "." },
{ name = "langchain-aws", marker = "extra == 'aws'" },
{ name = "langchain-azure-ai", marker = "extra == 'azure-ai'" },
@@ -621,7 +621,7 @@
lint = [{ name = "ruff", specifier = ">=0.15.0,<0.17.0" }]
test = [
{ name = "blockbuster", specifier = ">=1.5.26,<1.6.0" },
- { name = "fastmcp", specifier = ">=4.0.1,<5.0.0" },
+ { name = "fastmcp", specifier = ">=4.0.11,<5.0.0" },
{ name = "langchain-openai", editable = "../openai" },
{ name = "langchain-tests", editable = "../../standard-tests" },
{ name = "pytest", specifier = ">=9.0.3,<10.0.0" },
@@ -643,14 +643,14 @@
{ name = "wrapt", specifier = ">=1.15.0,<3.0.0" },
]
typing = [
- { name = "fastmcp", specifier = ">=4.0.1,<5.0.0" },
+ { name = "fastmcp", specifier = ">=4.0.11,<5.0.0" },
{ name = "mypy", specifier = ">=2.1.0,<2.2.0" },
{ name = "types-toml", specifier = ">=0.10.8.20240310,<1.0.0.0" },
]
[[package]]
name = "langchain-anthropic"
-version = "1.7.5"
+version = "1.7.6"
source = { editable = "." }
dependencies = [
{ name = "anthropic" },
@@ -723,7 +723,7 @@
[[package]]
name = "langchain-core"
-version = "1.6.6"
+version = "1.6.10"
source = { editable = "../../core" }
dependencies = [
{ name = "httpx" },
@@ -886,7 +886,7 @@
[[package]]
name = "langgraph-sdk"
-version = "0.4.2"
+version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -895,9 +895,9 @@
{ name = "orjson" },
{ name = "websockets" },
]
-sdist = { url =
"https://files.pythonhosted.org/packages/b4/2b/bd8ac26d4e97f6df88ef05ce5b6a38945a3903e1025d926f4752aa88aa97/langgraph_sdk-0.4.2.tar.gz",
hash =
"sha256:b88f0f5f6328ac0680d6790614a905b2bcfa257f2276dba4e38f0e86db0aa738", size
= 348327, upload-time = "2026-06-01T17:51:19.856Z" }
+sdist = { url =
"https://files.pythonhosted.org/packages/78/85/54edf4902c0378510f09a009f64e3d3f5644aeeb51d13cf67ec380a5245b/langgraph_sdk-0.4.6.tar.gz",
hash =
"sha256:ea5b1749d70987d741c9b9fe2b7e1c5f7da7e4d102f64e390333c1890c9bbd5b", size
= 350632, upload-time = "2026-10-06T14:17:53.641Z" }
wheels = [
- { url =
"https://files.pythonhosted.org/packages/a0/05/aac507337cceae773c2cc9ab91eb6301963af7aeeb55b4217a00e15aff17/langgraph_sdk-0.4.2-py3-none-any.whl",
hash =
"sha256:75fa5096c1177ce39c847096a8fe3745ffd480ddb412995f836e9f5f884c43dd", size
= 160521, upload-time = "2026-06-01T17:51:18.849Z" },
+ { url =
"https://files.pythonhosted.org/packages/6c/c7/69d13026db3577c157877dea47a9dc5fffd3dcde2d1ab8009fa8f7e5f6a6/langgraph_sdk-0.4.6-py3-none-any.whl",
hash =
"sha256:57122b02bda41d37a97a5e09eb018aa8c9b3dc85c433880073779bd9324b7eea", size
= 162390, upload-time = "2026-10-06T14:17:52.134Z" },
]
[[package]]
@@ -2016,11 +2016,11 @@
[[package]]
name = "urllib3"
-version = "2.7.0"
+version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url =
"https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz",
hash =
"sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size
= 433602, upload-time = "2026-05-07T16:13:18.596Z" }
+sdist = { url =
"https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz",
hash =
"sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size
= 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
- { url =
"https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl",
hash =
"sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size
= 131087, upload-time = "2026-05-07T16:13:17.151Z" },
+ { url =
"https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl",
hash =
"sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size
= 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]