anthropic 0.74.1__py3-none-any.whl → 0.76.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. anthropic/_base_client.py +140 -11
  2. anthropic/_client.py +4 -12
  3. anthropic/_models.py +16 -1
  4. anthropic/_streaming.py +78 -76
  5. anthropic/_types.py +12 -2
  6. anthropic/_version.py +1 -1
  7. anthropic/lib/streaming/_beta_messages.py +1 -1
  8. anthropic/lib/tools/_beta_compaction_control.py +48 -0
  9. anthropic/lib/tools/_beta_functions.py +30 -8
  10. anthropic/lib/tools/_beta_runner.py +233 -34
  11. anthropic/resources/beta/messages/messages.py +134 -27
  12. anthropic/resources/messages/messages.py +4 -0
  13. anthropic/types/anthropic_beta_param.py +1 -0
  14. anthropic/types/beta/__init__.py +31 -0
  15. anthropic/types/beta/beta_code_execution_tool_20250522_param.py +9 -1
  16. anthropic/types/beta/beta_code_execution_tool_20250825_param.py +9 -1
  17. anthropic/types/beta/beta_container.py +4 -0
  18. anthropic/types/beta/beta_container_params.py +2 -0
  19. anthropic/types/beta/beta_container_upload_block.py +2 -0
  20. anthropic/types/beta/beta_container_upload_block_param.py +5 -0
  21. anthropic/types/beta/beta_content_block.py +2 -0
  22. anthropic/types/beta/beta_content_block_param.py +2 -0
  23. anthropic/types/beta/beta_direct_caller.py +13 -0
  24. anthropic/types/beta/beta_direct_caller_param.py +13 -0
  25. anthropic/types/beta/beta_mcp_tool_config_param.py +15 -0
  26. anthropic/types/beta/beta_mcp_tool_default_config_param.py +15 -0
  27. anthropic/types/beta/beta_mcp_toolset_param.py +34 -0
  28. anthropic/types/beta/beta_memory_tool_20250818_param.py +11 -1
  29. anthropic/types/beta/beta_output_config_param.py +13 -0
  30. anthropic/types/beta/beta_raw_content_block_start_event.py +2 -0
  31. anthropic/types/beta/beta_server_tool_caller.py +15 -0
  32. anthropic/types/beta/beta_server_tool_caller_param.py +15 -0
  33. anthropic/types/beta/beta_server_tool_use_block.py +20 -4
  34. anthropic/types/beta/beta_server_tool_use_block_param.py +19 -4
  35. anthropic/types/beta/beta_skill.py +2 -0
  36. anthropic/types/beta/beta_skill_params.py +2 -0
  37. anthropic/types/beta/beta_tool_bash_20241022_param.py +11 -1
  38. anthropic/types/beta/beta_tool_bash_20250124_param.py +11 -1
  39. anthropic/types/beta/beta_tool_choice_any_param.py +2 -0
  40. anthropic/types/beta/beta_tool_choice_auto_param.py +2 -0
  41. anthropic/types/beta/beta_tool_choice_none_param.py +2 -0
  42. anthropic/types/beta/beta_tool_choice_tool_param.py +2 -0
  43. anthropic/types/beta/beta_tool_computer_use_20241022_param.py +11 -1
  44. anthropic/types/beta/beta_tool_computer_use_20250124_param.py +11 -1
  45. anthropic/types/beta/beta_tool_computer_use_20251124_param.py +47 -0
  46. anthropic/types/beta/beta_tool_param.py +16 -1
  47. anthropic/types/beta/beta_tool_reference_block.py +13 -0
  48. anthropic/types/beta/beta_tool_reference_block_param.py +21 -0
  49. anthropic/types/beta/beta_tool_result_block_param.py +6 -1
  50. anthropic/types/beta/beta_tool_search_tool_bm25_20251119_param.py +33 -0
  51. anthropic/types/beta/beta_tool_search_tool_regex_20251119_param.py +33 -0
  52. anthropic/types/beta/beta_tool_search_tool_result_block.py +20 -0
  53. anthropic/types/beta/beta_tool_search_tool_result_block_param.py +25 -0
  54. anthropic/types/beta/beta_tool_search_tool_result_error.py +16 -0
  55. anthropic/types/beta/beta_tool_search_tool_result_error_param.py +13 -0
  56. anthropic/types/beta/beta_tool_search_tool_search_result_block.py +15 -0
  57. anthropic/types/beta/beta_tool_search_tool_search_result_block_param.py +16 -0
  58. anthropic/types/beta/beta_tool_text_editor_20241022_param.py +11 -1
  59. anthropic/types/beta/beta_tool_text_editor_20250124_param.py +11 -1
  60. anthropic/types/beta/beta_tool_text_editor_20250429_param.py +11 -1
  61. anthropic/types/beta/beta_tool_text_editor_20250728_param.py +11 -1
  62. anthropic/types/beta/beta_tool_union_param.py +8 -0
  63. anthropic/types/beta/beta_tool_use_block.py +11 -3
  64. anthropic/types/beta/beta_tool_use_block_param.py +10 -3
  65. anthropic/types/beta/beta_web_fetch_tool_20250910_param.py +9 -1
  66. anthropic/types/beta/beta_web_search_tool_20250305_param.py +14 -1
  67. anthropic/types/beta/message_count_tokens_params.py +15 -0
  68. anthropic/types/beta/message_create_params.py +7 -0
  69. anthropic/types/beta/messages/batch_create_params.py +4 -4
  70. anthropic/types/beta/messages/beta_message_batch_individual_response.py +4 -0
  71. anthropic/types/messages/batch_create_params.py +2 -2
  72. anthropic/types/messages/message_batch_individual_response.py +4 -0
  73. anthropic/types/model.py +2 -0
  74. anthropic/types/model_param.py +2 -0
  75. anthropic/types/tool_choice_any_param.py +2 -0
  76. anthropic/types/tool_choice_auto_param.py +2 -0
  77. anthropic/types/tool_choice_none_param.py +2 -0
  78. anthropic/types/tool_choice_tool_param.py +2 -0
  79. anthropic/types/tool_param.py +5 -0
  80. anthropic/types/web_search_tool_20250305_param.py +5 -0
  81. {anthropic-0.74.1.dist-info → anthropic-0.76.0.dist-info}/METADATA +4 -2
  82. {anthropic-0.74.1.dist-info → anthropic-0.76.0.dist-info}/RECORD +84 -64
  83. {anthropic-0.74.1.dist-info → anthropic-0.76.0.dist-info}/WHEEL +0 -0
  84. {anthropic-0.74.1.dist-info → anthropic-0.76.0.dist-info}/licenses/LICENSE +0 -0
anthropic/_base_client.py CHANGED
@@ -10,6 +10,7 @@ import asyncio
10
10
  import inspect
11
11
  import logging
12
12
  import platform
13
+ import warnings
13
14
  import email.utils
14
15
  from types import TracebackType
15
16
  from random import random
@@ -54,9 +55,11 @@ from ._types import (
54
55
  ResponseT,
55
56
  AnyMapping,
56
57
  PostParser,
58
+ BinaryTypes,
57
59
  RequestFiles,
58
60
  HttpxSendArgs,
59
61
  RequestOptions,
62
+ AsyncBinaryTypes,
60
63
  HttpxRequestFiles,
61
64
  ModelBuilderProtocol,
62
65
  not_given,
@@ -490,8 +493,19 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
490
493
  retries_taken: int = 0,
491
494
  ) -> httpx.Request:
492
495
  if log.isEnabledFor(logging.DEBUG):
493
- log.debug("Request options: %s", model_dump(options, exclude_unset=True))
494
-
496
+ log.debug(
497
+ "Request options: %s",
498
+ model_dump(
499
+ options,
500
+ exclude_unset=True,
501
+ # Pydantic v1 can't dump every type we support in content, so we exclude it for now.
502
+ exclude={
503
+ "content",
504
+ }
505
+ if PYDANTIC_V1
506
+ else {},
507
+ ),
508
+ )
495
509
  kwargs: dict[str, Any] = {}
496
510
 
497
511
  json_data = options.json_data
@@ -545,7 +559,13 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
545
559
  is_body_allowed = options.method.lower() != "get"
546
560
 
547
561
  if is_body_allowed:
548
- if isinstance(json_data, bytes):
562
+ if options.content is not None and json_data is not None:
563
+ raise TypeError("Passing both `content` and `json_data` is not supported")
564
+ if options.content is not None and files is not None:
565
+ raise TypeError("Passing both `content` and `files` is not supported")
566
+ if options.content is not None:
567
+ kwargs["content"] = options.content
568
+ elif isinstance(json_data, bytes):
549
569
  kwargs["content"] = json_data
550
570
  else:
551
571
  kwargs["json"] = json_data if is_given(json_data) else None
@@ -1278,6 +1298,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1278
1298
  *,
1279
1299
  cast_to: Type[ResponseT],
1280
1300
  body: Body | None = None,
1301
+ content: BinaryTypes | None = None,
1281
1302
  options: RequestOptions = {},
1282
1303
  files: RequestFiles | None = None,
1283
1304
  stream: Literal[False] = False,
@@ -1290,6 +1311,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1290
1311
  *,
1291
1312
  cast_to: Type[ResponseT],
1292
1313
  body: Body | None = None,
1314
+ content: BinaryTypes | None = None,
1293
1315
  options: RequestOptions = {},
1294
1316
  files: RequestFiles | None = None,
1295
1317
  stream: Literal[True],
@@ -1303,6 +1325,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1303
1325
  *,
1304
1326
  cast_to: Type[ResponseT],
1305
1327
  body: Body | None = None,
1328
+ content: BinaryTypes | None = None,
1306
1329
  options: RequestOptions = {},
1307
1330
  files: RequestFiles | None = None,
1308
1331
  stream: bool,
@@ -1315,13 +1338,25 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1315
1338
  *,
1316
1339
  cast_to: Type[ResponseT],
1317
1340
  body: Body | None = None,
1341
+ content: BinaryTypes | None = None,
1318
1342
  options: RequestOptions = {},
1319
1343
  files: RequestFiles | None = None,
1320
1344
  stream: bool = False,
1321
1345
  stream_cls: type[_StreamT] | None = None,
1322
1346
  ) -> ResponseT | _StreamT:
1347
+ if body is not None and content is not None:
1348
+ raise TypeError("Passing both `body` and `content` is not supported")
1349
+ if files is not None and content is not None:
1350
+ raise TypeError("Passing both `files` and `content` is not supported")
1351
+ if isinstance(body, bytes):
1352
+ warnings.warn(
1353
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1354
+ "Please pass raw bytes via the `content` parameter instead.",
1355
+ DeprecationWarning,
1356
+ stacklevel=2,
1357
+ )
1323
1358
  opts = FinalRequestOptions.construct(
1324
- method="post", url=path, json_data=body, files=to_httpx_files(files), **options
1359
+ method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1325
1360
  )
1326
1361
  return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
1327
1362
 
@@ -1331,9 +1366,24 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1331
1366
  *,
1332
1367
  cast_to: Type[ResponseT],
1333
1368
  body: Body | None = None,
1369
+ content: BinaryTypes | None = None,
1370
+ files: RequestFiles | None = None,
1334
1371
  options: RequestOptions = {},
1335
1372
  ) -> ResponseT:
1336
- opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
1373
+ if body is not None and content is not None:
1374
+ raise TypeError("Passing both `body` and `content` is not supported")
1375
+ if files is not None and content is not None:
1376
+ raise TypeError("Passing both `files` and `content` is not supported")
1377
+ if isinstance(body, bytes):
1378
+ warnings.warn(
1379
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1380
+ "Please pass raw bytes via the `content` parameter instead.",
1381
+ DeprecationWarning,
1382
+ stacklevel=2,
1383
+ )
1384
+ opts = FinalRequestOptions.construct(
1385
+ method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1386
+ )
1337
1387
  return self.request(cast_to, opts)
1338
1388
 
1339
1389
  def put(
@@ -1342,11 +1392,23 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1342
1392
  *,
1343
1393
  cast_to: Type[ResponseT],
1344
1394
  body: Body | None = None,
1395
+ content: BinaryTypes | None = None,
1345
1396
  files: RequestFiles | None = None,
1346
1397
  options: RequestOptions = {},
1347
1398
  ) -> ResponseT:
1399
+ if body is not None and content is not None:
1400
+ raise TypeError("Passing both `body` and `content` is not supported")
1401
+ if files is not None and content is not None:
1402
+ raise TypeError("Passing both `files` and `content` is not supported")
1403
+ if isinstance(body, bytes):
1404
+ warnings.warn(
1405
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1406
+ "Please pass raw bytes via the `content` parameter instead.",
1407
+ DeprecationWarning,
1408
+ stacklevel=2,
1409
+ )
1348
1410
  opts = FinalRequestOptions.construct(
1349
- method="put", url=path, json_data=body, files=to_httpx_files(files), **options
1411
+ method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1350
1412
  )
1351
1413
  return self.request(cast_to, opts)
1352
1414
 
@@ -1356,9 +1418,19 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1356
1418
  *,
1357
1419
  cast_to: Type[ResponseT],
1358
1420
  body: Body | None = None,
1421
+ content: BinaryTypes | None = None,
1359
1422
  options: RequestOptions = {},
1360
1423
  ) -> ResponseT:
1361
- opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
1424
+ if body is not None and content is not None:
1425
+ raise TypeError("Passing both `body` and `content` is not supported")
1426
+ if isinstance(body, bytes):
1427
+ warnings.warn(
1428
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1429
+ "Please pass raw bytes via the `content` parameter instead.",
1430
+ DeprecationWarning,
1431
+ stacklevel=2,
1432
+ )
1433
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
1362
1434
  return self.request(cast_to, opts)
1363
1435
 
1364
1436
  def get_api_list(
@@ -1854,6 +1926,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1854
1926
  *,
1855
1927
  cast_to: Type[ResponseT],
1856
1928
  body: Body | None = None,
1929
+ content: AsyncBinaryTypes | None = None,
1857
1930
  files: RequestFiles | None = None,
1858
1931
  options: RequestOptions = {},
1859
1932
  stream: Literal[False] = False,
@@ -1866,6 +1939,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1866
1939
  *,
1867
1940
  cast_to: Type[ResponseT],
1868
1941
  body: Body | None = None,
1942
+ content: AsyncBinaryTypes | None = None,
1869
1943
  files: RequestFiles | None = None,
1870
1944
  options: RequestOptions = {},
1871
1945
  stream: Literal[True],
@@ -1879,6 +1953,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1879
1953
  *,
1880
1954
  cast_to: Type[ResponseT],
1881
1955
  body: Body | None = None,
1956
+ content: AsyncBinaryTypes | None = None,
1882
1957
  files: RequestFiles | None = None,
1883
1958
  options: RequestOptions = {},
1884
1959
  stream: bool,
@@ -1891,13 +1966,25 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1891
1966
  *,
1892
1967
  cast_to: Type[ResponseT],
1893
1968
  body: Body | None = None,
1969
+ content: AsyncBinaryTypes | None = None,
1894
1970
  files: RequestFiles | None = None,
1895
1971
  options: RequestOptions = {},
1896
1972
  stream: bool = False,
1897
1973
  stream_cls: type[_AsyncStreamT] | None = None,
1898
1974
  ) -> ResponseT | _AsyncStreamT:
1975
+ if body is not None and content is not None:
1976
+ raise TypeError("Passing both `body` and `content` is not supported")
1977
+ if files is not None and content is not None:
1978
+ raise TypeError("Passing both `files` and `content` is not supported")
1979
+ if isinstance(body, bytes):
1980
+ warnings.warn(
1981
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1982
+ "Please pass raw bytes via the `content` parameter instead.",
1983
+ DeprecationWarning,
1984
+ stacklevel=2,
1985
+ )
1899
1986
  opts = FinalRequestOptions.construct(
1900
- method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options
1987
+ method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
1901
1988
  )
1902
1989
  return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
1903
1990
 
@@ -1907,9 +1994,29 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1907
1994
  *,
1908
1995
  cast_to: Type[ResponseT],
1909
1996
  body: Body | None = None,
1997
+ content: AsyncBinaryTypes | None = None,
1998
+ files: RequestFiles | None = None,
1910
1999
  options: RequestOptions = {},
1911
2000
  ) -> ResponseT:
1912
- opts = FinalRequestOptions.construct(method="patch", url=path, json_data=body, **options)
2001
+ if body is not None and content is not None:
2002
+ raise TypeError("Passing both `body` and `content` is not supported")
2003
+ if files is not None and content is not None:
2004
+ raise TypeError("Passing both `files` and `content` is not supported")
2005
+ if isinstance(body, bytes):
2006
+ warnings.warn(
2007
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2008
+ "Please pass raw bytes via the `content` parameter instead.",
2009
+ DeprecationWarning,
2010
+ stacklevel=2,
2011
+ )
2012
+ opts = FinalRequestOptions.construct(
2013
+ method="patch",
2014
+ url=path,
2015
+ json_data=body,
2016
+ content=content,
2017
+ files=await async_to_httpx_files(files),
2018
+ **options,
2019
+ )
1913
2020
  return await self.request(cast_to, opts)
1914
2021
 
1915
2022
  async def put(
@@ -1918,11 +2025,23 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1918
2025
  *,
1919
2026
  cast_to: Type[ResponseT],
1920
2027
  body: Body | None = None,
2028
+ content: AsyncBinaryTypes | None = None,
1921
2029
  files: RequestFiles | None = None,
1922
2030
  options: RequestOptions = {},
1923
2031
  ) -> ResponseT:
2032
+ if body is not None and content is not None:
2033
+ raise TypeError("Passing both `body` and `content` is not supported")
2034
+ if files is not None and content is not None:
2035
+ raise TypeError("Passing both `files` and `content` is not supported")
2036
+ if isinstance(body, bytes):
2037
+ warnings.warn(
2038
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2039
+ "Please pass raw bytes via the `content` parameter instead.",
2040
+ DeprecationWarning,
2041
+ stacklevel=2,
2042
+ )
1924
2043
  opts = FinalRequestOptions.construct(
1925
- method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options
2044
+ method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
1926
2045
  )
1927
2046
  return await self.request(cast_to, opts)
1928
2047
 
@@ -1932,9 +2051,19 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1932
2051
  *,
1933
2052
  cast_to: Type[ResponseT],
1934
2053
  body: Body | None = None,
2054
+ content: AsyncBinaryTypes | None = None,
1935
2055
  options: RequestOptions = {},
1936
2056
  ) -> ResponseT:
1937
- opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, **options)
2057
+ if body is not None and content is not None:
2058
+ raise TypeError("Passing both `body` and `content` is not supported")
2059
+ if isinstance(body, bytes):
2060
+ warnings.warn(
2061
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
2062
+ "Please pass raw bytes via the `content` parameter instead.",
2063
+ DeprecationWarning,
2064
+ stacklevel=2,
2065
+ )
2066
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
1938
2067
  return await self.request(cast_to, opts)
1939
2068
 
1940
2069
  def get_api_list(
anthropic/_client.py CHANGED
@@ -187,14 +187,10 @@ class Anthropic(SyncAPIClient):
187
187
  # valid
188
188
  return
189
189
 
190
- if self.api_key and headers.get("X-Api-Key"):
191
- return
192
- if isinstance(custom_headers.get("X-Api-Key"), Omit):
190
+ if headers.get("X-Api-Key") or isinstance(custom_headers.get("X-Api-Key"), Omit):
193
191
  return
194
192
 
195
- if self.auth_token and headers.get("Authorization"):
196
- return
197
- if isinstance(custom_headers.get("Authorization"), Omit):
193
+ if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
198
194
  return
199
195
 
200
196
  raise TypeError(
@@ -431,14 +427,10 @@ class AsyncAnthropic(AsyncAPIClient):
431
427
  # valid
432
428
  return
433
429
 
434
- if self.api_key and headers.get("X-Api-Key"):
435
- return
436
- if isinstance(custom_headers.get("X-Api-Key"), Omit):
430
+ if headers.get("X-Api-Key") or isinstance(custom_headers.get("X-Api-Key"), Omit):
437
431
  return
438
432
 
439
- if self.auth_token and headers.get("Authorization"):
440
- return
441
- if isinstance(custom_headers.get("Authorization"), Omit):
433
+ if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
442
434
  return
443
435
 
444
436
  raise TypeError(
anthropic/_models.py CHANGED
@@ -3,7 +3,20 @@ from __future__ import annotations
3
3
  import os
4
4
  import inspect
5
5
  import weakref
6
- from typing import TYPE_CHECKING, Any, Type, Union, Generic, TypeVar, Callable, Optional, cast
6
+ from typing import (
7
+ IO,
8
+ TYPE_CHECKING,
9
+ Any,
10
+ Type,
11
+ Union,
12
+ Generic,
13
+ TypeVar,
14
+ Callable,
15
+ Iterable,
16
+ Optional,
17
+ AsyncIterable,
18
+ cast,
19
+ )
7
20
  from datetime import date, datetime
8
21
  from typing_extensions import (
9
22
  List,
@@ -833,6 +846,7 @@ class FinalRequestOptionsInput(TypedDict, total=False):
833
846
  timeout: float | Timeout | None
834
847
  files: HttpxRequestFiles | None
835
848
  idempotency_key: str
849
+ content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None]
836
850
  json_data: Body
837
851
  extra_json: AnyMapping
838
852
  follow_redirects: bool
@@ -851,6 +865,7 @@ class FinalRequestOptions(pydantic.BaseModel):
851
865
  post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven()
852
866
  follow_redirects: Union[bool, None] = None
853
867
 
868
+ content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None
854
869
  # It should be noted that we cannot use `json` here as that would override
855
870
  # a BaseModel method in an incompatible fashion.
856
871
  json_data: Union[Body, None] = None
anthropic/_streaming.py CHANGED
@@ -77,44 +77,45 @@ class Stream(Generic[_T], metaclass=_SyncStreamMeta):
77
77
  process_data = self._client._process_response_data
78
78
  iterator = self._iter_events()
79
79
 
80
- for sse in iterator:
81
- if sse.event == "completion":
82
- yield process_data(data=sse.json(), cast_to=cast_to, response=response)
83
-
84
- if (
85
- sse.event == "message_start"
86
- or sse.event == "message_delta"
87
- or sse.event == "message_stop"
88
- or sse.event == "content_block_start"
89
- or sse.event == "content_block_delta"
90
- or sse.event == "content_block_stop"
91
- ):
92
- data = sse.json()
93
- if is_dict(data) and "type" not in data:
94
- data["type"] = sse.event
95
-
96
- yield process_data(data=data, cast_to=cast_to, response=response)
97
-
98
- if sse.event == "ping":
99
- continue
100
-
101
- if sse.event == "error":
102
- body = sse.data
103
-
104
- try:
105
- body = sse.json()
106
- err_msg = f"{body}"
107
- except Exception:
108
- err_msg = sse.data or f"Error code: {response.status_code}"
109
-
110
- raise self._client._make_status_error(
111
- err_msg,
112
- body=body,
113
- response=self.response,
114
- )
115
-
116
- # As we might not fully consume the response stream, we need to close it explicitly
117
- response.close()
80
+ try:
81
+ for sse in iterator:
82
+ if sse.event == "completion":
83
+ yield process_data(data=sse.json(), cast_to=cast_to, response=response)
84
+
85
+ if (
86
+ sse.event == "message_start"
87
+ or sse.event == "message_delta"
88
+ or sse.event == "message_stop"
89
+ or sse.event == "content_block_start"
90
+ or sse.event == "content_block_delta"
91
+ or sse.event == "content_block_stop"
92
+ ):
93
+ data = sse.json()
94
+ if is_dict(data) and "type" not in data:
95
+ data["type"] = sse.event
96
+
97
+ yield process_data(data=data, cast_to=cast_to, response=response)
98
+
99
+ if sse.event == "ping":
100
+ continue
101
+
102
+ if sse.event == "error":
103
+ body = sse.data
104
+
105
+ try:
106
+ body = sse.json()
107
+ err_msg = f"{body}"
108
+ except Exception:
109
+ err_msg = sse.data or f"Error code: {response.status_code}"
110
+
111
+ raise self._client._make_status_error(
112
+ err_msg,
113
+ body=body,
114
+ response=self.response,
115
+ )
116
+ finally:
117
+ # Ensure the response is closed even if the consumer doesn't read all data
118
+ response.close()
118
119
 
119
120
  def __enter__(self) -> Self:
120
121
  return self
@@ -194,44 +195,45 @@ class AsyncStream(Generic[_T], metaclass=_AsyncStreamMeta):
194
195
  process_data = self._client._process_response_data
195
196
  iterator = self._iter_events()
196
197
 
197
- async for sse in iterator:
198
- if sse.event == "completion":
199
- yield process_data(data=sse.json(), cast_to=cast_to, response=response)
200
-
201
- if (
202
- sse.event == "message_start"
203
- or sse.event == "message_delta"
204
- or sse.event == "message_stop"
205
- or sse.event == "content_block_start"
206
- or sse.event == "content_block_delta"
207
- or sse.event == "content_block_stop"
208
- ):
209
- data = sse.json()
210
- if is_dict(data) and "type" not in data:
211
- data["type"] = sse.event
212
-
213
- yield process_data(data=data, cast_to=cast_to, response=response)
214
-
215
- if sse.event == "ping":
216
- continue
217
-
218
- if sse.event == "error":
219
- body = sse.data
220
-
221
- try:
222
- body = sse.json()
223
- err_msg = f"{body}"
224
- except Exception:
225
- err_msg = sse.data or f"Error code: {response.status_code}"
226
-
227
- raise self._client._make_status_error(
228
- err_msg,
229
- body=body,
230
- response=self.response,
231
- )
232
-
233
- # As we might not fully consume the response stream, we need to close it explicitly
234
- await response.aclose()
198
+ try:
199
+ async for sse in iterator:
200
+ if sse.event == "completion":
201
+ yield process_data(data=sse.json(), cast_to=cast_to, response=response)
202
+
203
+ if (
204
+ sse.event == "message_start"
205
+ or sse.event == "message_delta"
206
+ or sse.event == "message_stop"
207
+ or sse.event == "content_block_start"
208
+ or sse.event == "content_block_delta"
209
+ or sse.event == "content_block_stop"
210
+ ):
211
+ data = sse.json()
212
+ if is_dict(data) and "type" not in data:
213
+ data["type"] = sse.event
214
+
215
+ yield process_data(data=data, cast_to=cast_to, response=response)
216
+
217
+ if sse.event == "ping":
218
+ continue
219
+
220
+ if sse.event == "error":
221
+ body = sse.data
222
+
223
+ try:
224
+ body = sse.json()
225
+ err_msg = f"{body}"
226
+ except Exception:
227
+ err_msg = sse.data or f"Error code: {response.status_code}"
228
+
229
+ raise self._client._make_status_error(
230
+ err_msg,
231
+ body=body,
232
+ response=self.response,
233
+ )
234
+ finally:
235
+ # Ensure the response is closed even if the consumer doesn't read all data
236
+ await response.aclose()
235
237
 
236
238
  async def __aenter__(self) -> Self:
237
239
  return self
anthropic/_types.py CHANGED
@@ -13,9 +13,11 @@ from typing import (
13
13
  Mapping,
14
14
  TypeVar,
15
15
  Callable,
16
+ Iterable,
16
17
  Iterator,
17
18
  Optional,
18
19
  Sequence,
20
+ AsyncIterable,
19
21
  )
20
22
  from typing_extensions import (
21
23
  Set,
@@ -57,6 +59,13 @@ if TYPE_CHECKING:
57
59
  else:
58
60
  Base64FileInput = Union[IO[bytes], PathLike]
59
61
  FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8.
62
+
63
+
64
+ # Used for sending raw binary data / streaming data in request bodies
65
+ # e.g. for file uploads without multipart encoding
66
+ BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]]
67
+ AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]]
68
+
60
69
  FileTypes = Union[
61
70
  # file (or bytes)
62
71
  FileContent,
@@ -245,6 +254,9 @@ _T_co = TypeVar("_T_co", covariant=True)
245
254
  if TYPE_CHECKING:
246
255
  # This works because str.__contains__ does not accept object (either in typeshed or at runtime)
247
256
  # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285
257
+ #
258
+ # Note: index() and count() methods are intentionally omitted to allow pyright to properly
259
+ # infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr.
248
260
  class SequenceNotStr(Protocol[_T_co]):
249
261
  @overload
250
262
  def __getitem__(self, index: SupportsIndex, /) -> _T_co: ...
@@ -253,8 +265,6 @@ if TYPE_CHECKING:
253
265
  def __contains__(self, value: object, /) -> bool: ...
254
266
  def __len__(self) -> int: ...
255
267
  def __iter__(self) -> Iterator[_T_co]: ...
256
- def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ...
257
- def count(self, value: Any, /) -> int: ...
258
268
  def __reversed__(self) -> Iterator[_T_co]: ...
259
269
  else:
260
270
  # just point this to a normal `Sequence` at runtime to avoid having to special case
anthropic/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "anthropic"
4
- __version__ = "0.74.1" # x-release-please-version
4
+ __version__ = "0.76.0" # x-release-please-version
@@ -468,7 +468,7 @@ def accumulate_event(
468
468
  current_snapshot.content.append(
469
469
  cast(
470
470
  Any, # Pydantic does not support generic unions at runtime
471
- construct_type(type_=ParsedBetaContentBlock, value=event.content_block.model_dump()),
471
+ construct_type(type_=ParsedBetaContentBlock, value=event.content_block.to_dict()),
472
472
  ),
473
473
  )
474
474
  elif event.type == "content_block_delta":
@@ -0,0 +1,48 @@
1
+ from typing import TypedDict
2
+ from typing_extensions import Required
3
+
4
+ DEFAULT_SUMMARY_PROMPT = """You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
5
+ 1. Task Overview
6
+ The user's core request and success criteria
7
+ Any clarifications or constraints they specified
8
+ 2. Current State
9
+ What has been completed so far
10
+ Files created, modified, or analyzed (with paths if relevant)
11
+ Key outputs or artifacts produced
12
+ 3. Important Discoveries
13
+ Technical constraints or requirements uncovered
14
+ Decisions made and their rationale
15
+ Errors encountered and how they were resolved
16
+ What approaches were tried that didn't work (and why)
17
+ 4. Next Steps
18
+ Specific actions needed to complete the task
19
+ Any blockers or open questions to resolve
20
+ Priority order if multiple steps remain
21
+ 5. Context to Preserve
22
+ User preferences or style requirements
23
+ Domain-specific details that aren't obvious
24
+ Any promises made to the user
25
+ Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.
26
+ Wrap your summary in <summary></summary> tags."""
27
+
28
+ DEFAULT_THRESHOLD = 100_000
29
+
30
+
31
+ class CompactionControl(TypedDict, total=False):
32
+ context_token_threshold: int
33
+ """The context token threshold at which to trigger compaction.
34
+
35
+ When the cumulative token count (input + output) across all messages exceeds this threshold,
36
+ the message history will be automatically summarized and compressed. Defaults to 100,000 tokens.
37
+ """
38
+
39
+ model: str
40
+ """
41
+ The model to use for generating the compaction summary.
42
+ If not specified, defaults to the same model used for the tool runner.
43
+ """
44
+
45
+ summary_prompt: str
46
+ """The prompt used to instruct the model on how to generate the summary."""
47
+
48
+ enabled: Required[bool]