Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
09d7208
Merge branch 'main' into next
anthropic-sdks-writer[bot] Sep 15, 2026
9e6ce27
chore(internal): add more unnecessary cast comments
anthropic-sdks-writer[bot] Sep 15, 2026
13cfe64
chore(internal): pass strict= to zip() in the MCP tool helpers
claude[bot] Sep 15, 2026
8ec9cc9
fix(bedrock): raise an API error for eventstream exception and error …
claude[bot] Sep 15, 2026
5921735
codegen metadata
anthropic-sdks-writer[bot] Sep 15, 2026
2bdfd41
chore(internal): set ruff's target version to Python 3.10
anthropic-sdks-writer[bot] Sep 15, 2026
30ebd69
fix(client): don't raise TypeError for `X | Y` fields with unknown data
anthropic-sdks-writer[bot] Sep 15, 2026
2c18298
chore(internal): remove an unused noqa comment from the model tests
anthropic-sdks-writer[bot] Sep 15, 2026
b366fa5
fix(client): accept `X | Y` union types when parsing responses
anthropic-sdks-writer[bot] Sep 15, 2026
8b23fb3
feat(tools): add compact_before_next_turn() to the tool runner (#641)
dtmeadows-ant Sep 16, 2026
eacc0ff
chore(docs): clarify the compaction tool_changes and tool change desc…
anthropic-sdks-writer[bot] Sep 16, 2026
1680324
fix(client): join multiple anthropic-beta values with a comma and no …
claude[bot] Sep 16, 2026
351de0c
codegen metadata
anthropic-sdks-writer[bot] Sep 16, 2026
e7dd41e
codegen metadata
anthropic-sdks-writer[bot] Sep 16, 2026
9d2d579
codegen metadata
anthropic-sdks-writer[bot] Sep 17, 2026
d3a9fc8
fix(tools): tidy compact_before_next_turn() state and failure handlin…
dtmeadows-ant Sep 17, 2026
91931e1
chore(deps): require pydantic 1.10 or later
anthropic-sdks-writer[bot] Sep 17, 2026
99184dc
chore(docs): add descriptions for enum values and path parameters
anthropic-sdks-writer[bot] Sep 17, 2026
182a764
codegen metadata
anthropic-sdks-writer[bot] Sep 17, 2026
5b4202a
codegen metadata
anthropic-sdks-writer[bot] Sep 17, 2026
28f0a83
feat(api): add group with display_name to rate limits, deprecate grou…
anthropic-sdks-writer[bot] Sep 18, 2026
a096a48
release: 1.7.0
stainless-app[bot] Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.6.0"
".": "1.7.0"
}
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Changelog

## 1.7.0 (2026-09-18)

Full Changelog: [v1.6.0...v1.7.0](https://github.com/anthropics/anthropic-sdk-python/compare/v1.6.0...v1.7.0)

### Features

* **api:** add group with display_name to rate limits, deprecate group_type ([28f0a83](https://github.com/anthropics/anthropic-sdk-python/commit/28f0a831355fa3d539fd3e1db1c63f92a39bb252))
* **tools:** add compact_before_next_turn() to the tool runner ([#641](https://github.com/anthropics/anthropic-sdk-python/issues/641)) ([8b23fb3](https://github.com/anthropics/anthropic-sdk-python/commit/8b23fb33f326c7ffa52e8d925902af0fd94501ce))


### Bug Fixes

* **bedrock:** raise an API error for eventstream exception and error frames ([#769](https://github.com/anthropics/anthropic-sdk-python/issues/769)) ([8ec9cc9](https://github.com/anthropics/anthropic-sdk-python/commit/8ec9cc9bdf7278ce7a1557dc7d6e455c7808946e))
* **client:** accept `X | Y` union types when parsing responses ([b366fa5](https://github.com/anthropics/anthropic-sdk-python/commit/b366fa5a1d62e4908a35415a1692f18621cf9e2c))
* **client:** don't raise TypeError for `X | Y` fields with unknown data ([30ebd69](https://github.com/anthropics/anthropic-sdk-python/commit/30ebd6963c4b21044fc8d7f8cf33a19981c74856))
* **client:** join multiple anthropic-beta values with a comma and no space ([#781](https://github.com/anthropics/anthropic-sdk-python/issues/781)) ([1680324](https://github.com/anthropics/anthropic-sdk-python/commit/168032429a6880ef7063de7680c7abe18e45be35))
* **tools:** tidy compact_before_next_turn() state and failure handling ([#804](https://github.com/anthropics/anthropic-sdk-python/issues/804)) ([d3a9fc8](https://github.com/anthropics/anthropic-sdk-python/commit/d3a9fc80f9792eda4944e33efb821306e632b7c6))


### Chores

* **deps:** require pydantic 1.10 or later ([91931e1](https://github.com/anthropics/anthropic-sdk-python/commit/91931e1d205839e72b2a4c2c851b18874f935943))
* **docs:** add descriptions for enum values and path parameters ([99184dc](https://github.com/anthropics/anthropic-sdk-python/commit/99184dc76a7a6c404478556483d2118498994a47))
* **docs:** clarify the compaction tool_changes and tool change descriptions ([eacc0ff](https://github.com/anthropics/anthropic-sdk-python/commit/eacc0ffde324201faac42fdcb60500b2076c25b6))
* **internal:** add more unnecessary cast comments ([9e6ce27](https://github.com/anthropics/anthropic-sdk-python/commit/9e6ce27b8d89c737bd427fc91b96f9932431f547))
* **internal:** pass strict= to zip() in the MCP tool helpers ([13cfe64](https://github.com/anthropics/anthropic-sdk-python/commit/13cfe644920119b718e0a73085b7ecd9726fb9e9))
* **internal:** remove an unused noqa comment from the model tests ([2c18298](https://github.com/anthropics/anthropic-sdk-python/commit/2c18298ff35a1b28b98d25b424e928b3865ef405))
* **internal:** set ruff's target version to Python 3.10 ([2bdfd41](https://github.com/anthropics/anthropic-sdk-python/commit/2bdfd415fe4842b44f871b31328cc76135b48fbb))

## 1.6.0 (2026-09-15)

Full Changelog: [v1.5.0...v1.6.0](https://github.com/anthropics/anthropic-sdk-python/compare/v1.5.0...v1.6.0)
Expand Down
6 changes: 6 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1783,7 +1783,13 @@ Types:
```python
from anthropic.types.beta.organization import (
BetaOrganizationRateLimit,
BetaOrganizationRateLimitBatchGroup,
BetaOrganizationRateLimitFilesGroup,
BetaOrganizationRateLimitModelGroup,
BetaOrganizationRateLimitSkillsGroup,
BetaOrganizationRateLimitTokenCountGroup,
BetaOrganizationRateLimitValue,
BetaOrganizationRateLimitWebSearchGroup,
)
```

Expand Down
12 changes: 4 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "anthropic"
version = "1.6.0"
version = "1.7.0"
description = "The official Python library for the anthropic API"
dynamic = ["readme"]
license = "MIT"
Expand All @@ -10,7 +10,7 @@ authors = [

dependencies = [
"httpx2>=2.0.0, <3",
"pydantic>=1.9.0, <3",
"pydantic>=1.10.0, <3",
"typing-extensions>=4.14, <5",
"anyio>=4.1.0, <5",
"sniffio>=1, <2",
Expand Down Expand Up @@ -91,7 +91,7 @@ dev = [
"httpx2>=2.9",
]
pydantic-v1 = [
"pydantic>=1.9.0,<2",
"pydantic>=1.10.0,<2",
]
pydantic-v2 = [
"pydantic~=2.0 ; python_full_version < '3.14'",
Expand Down Expand Up @@ -225,7 +225,7 @@ follow_imports = "skip"
[tool.ruff]
line-length = 120
output-format = "grouped"
target-version = "py38"
target-version = "py310"
extend-exclude = ["src/anthropic/_vendor"]

[tool.ruff.format]
Expand All @@ -239,8 +239,6 @@ select = [
"B",
# remove unused imports
"F401",
# check for missing future annotations
"FA102",
# bare except statements
"E722",
# unused arguments
Expand All @@ -263,8 +261,6 @@ unfixable = [
"T203",
]

extend-safe-fixes = ["FA102"]

[tool.ruff.lint.flake8-tidy-imports.banned-api]
"functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead"

Expand Down
Binary file modified scripts/mock-spec.json.gz
Binary file not shown.
21 changes: 16 additions & 5 deletions src/anthropic/_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

import os
import sys
import types
import inspect
import weakref
from typing import (
Expand Down Expand Up @@ -729,6 +731,14 @@ class CachedDiscriminatorType(Protocol):
DISCRIMINATOR_CACHE: weakref.WeakKeyDictionary[type, DiscriminatorDetails] = weakref.WeakKeyDictionary()


def _discriminator_cache_key(union: type) -> type:
if sys.version_info < (3, 14) and isinstance(cast(object, union), types.UnionType):
# `X | Y` can't be weakly referenced before Python 3.14, so key on the equal `typing.Union[X, Y]`.
# That object may be held only by `typing`'s LRU cache, so the cache entry can be dropped and rebuilt.
return cast(type, cast(Any, Union)[get_args(union)])
return union


class DiscriminatorDetails:
field_name: str
"""The name of the discriminator field in the variant class, e.g.
Expand Down Expand Up @@ -771,7 +781,8 @@ def __init__(


def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None:
cached = DISCRIMINATOR_CACHE.get(union)
key = _discriminator_cache_key(union)
cached = DISCRIMINATOR_CACHE.get(key)
if cached is not None:
return cached

Expand Down Expand Up @@ -814,7 +825,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
field_schema = field["schema"]

if field_schema["type"] == "literal":
for entry in cast("LiteralSchema", field_schema)["expected"]:
for entry in cast("LiteralSchema", field_schema)["expected"]: # pyright: ignore[reportUnnecessaryCast]
if isinstance(entry, str):
mapping[entry] = variant

Expand All @@ -826,7 +837,7 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
discriminator_field=discriminator_field_name,
discriminator_alias=discriminator_alias,
)
DISCRIMINATOR_CACHE.setdefault(union, details)
DISCRIMINATOR_CACHE.setdefault(key, details)
return details


Expand All @@ -838,12 +849,12 @@ def _extract_field_schema_pv2(model: type[BaseModel], field_name: str) -> ModelF
if schema["type"] != "model":
return None

schema = cast("ModelSchema", schema)
schema = cast("ModelSchema", schema) # pyright: ignore[reportUnnecessaryCast]
fields_schema = schema["schema"]
if fields_schema["type"] != "model-fields":
return None

fields_schema = cast("ModelFieldsSchema", fields_schema)
fields_schema = cast("ModelFieldsSchema", fields_schema) # pyright: ignore[reportUnnecessaryCast]
field = fields_schema["fields"].get(field_name)
if not field:
return None
Expand Down
3 changes: 2 additions & 1 deletion src/anthropic/_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER
from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type
from ._exceptions import AnthropicError, APIResponseValidationError
from ._utils._typing import is_union_type
from ._decoders.jsonl import JSONLDecoder, AsyncJSONLDecoder

if TYPE_CHECKING:
Expand Down Expand Up @@ -250,7 +251,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to is not object
and not origin is list
and not origin is dict
and not origin is Union
and not is_union_type(cast_to)
and not issubclass(origin, BaseModel)
):
raise RuntimeError(
Expand Down
2 changes: 1 addition & 1 deletion src/anthropic/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__title__ = "anthropic"
__version__ = "1.6.0" # x-release-please-version
__version__ = "1.7.0" # x-release-please-version
5 changes: 4 additions & 1 deletion src/anthropic/lib/bedrock/_stream_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ def _parse_message_from_event(self, event: EventStreamMessage) -> ServerSentEven
response_dict = event.to_response_dict()
parsed_response = self.parser.parse(response_dict, get_response_stream_shape())
if response_dict["status_code"] != 200:
raise ValueError(f"Bad response code, expected 200: {response_dict}")
# an `exception`/`error` frame: surface it the way a first-party stream `error` event does
error = parsed_response["Error"]
data = {"type": "error", "error": {"type": error["Code"], "message": error["Message"]}}
return ServerSentEvent(data=json.dumps(data), event="error")

chunk = parsed_response.get("chunk")
if not chunk:
Expand Down
2 changes: 1 addition & 1 deletion src/anthropic/lib/credentials/_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def _apply(self, request: httpx2.Request, token: str) -> None:
existing_flags = [flag.strip() for flag in existing_beta.split(",") if flag.strip()]
if OAUTH_API_BETA_HEADER not in existing_flags:
existing_flags.append(OAUTH_API_BETA_HEADER)
request.headers["anthropic-beta"] = ", ".join(existing_flags)
request.headers["anthropic-beta"] = ",".join(existing_flags)

@override
def sync_auth_flow(self, request: httpx2.Request) -> Generator[httpx2.Request, httpx2.Response, None]:
Expand Down
2 changes: 1 addition & 1 deletion src/anthropic/lib/middleware/_fallbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ def _with_middleware_headers(request: APIRequest, betas: tuple[AnthropicBetaPara
current = build_headers(request.headers)[0].get("anthropic-beta", "")
existing = {value.strip() for value in current.split(",")}
additions = dict.fromkeys(str(beta) for beta in betas if str(beta) not in existing)
beta_header = {"anthropic-beta": ", ".join(filter(None, [current, *additions]))} if current or additions else {}
beta_header = {"anthropic-beta": ",".join(filter(None, [current, *additions]))} if current or additions else {}
return request.copy(
headers=merge_headers(request.headers, beta_header, helper_header("fallback-refusal-middleware"))
)
Expand Down
Loading
Loading