anthropic 0.73.0__py3-none-any.whl → 0.74.1__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.
anthropic/__init__.py CHANGED
@@ -101,6 +101,7 @@ if not _t.TYPE_CHECKING:
101
101
  from .lib.tools import beta_tool, beta_async_tool
102
102
  from .lib.vertex import *
103
103
  from .lib.bedrock import *
104
+ from .lib.foundry import AnthropicFoundry as AnthropicFoundry, AsyncAnthropicFoundry as AsyncAnthropicFoundry
104
105
  from .lib.streaming import *
105
106
 
106
107
  _setup_logging()
anthropic/_client.py CHANGED
@@ -183,6 +183,10 @@ class Anthropic(SyncAPIClient):
183
183
 
184
184
  @override
185
185
  def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
186
+ if headers.get("Authorization") or headers.get("X-Api-Key"):
187
+ # valid
188
+ return
189
+
186
190
  if self.api_key and headers.get("X-Api-Key"):
187
191
  return
188
192
  if isinstance(custom_headers.get("X-Api-Key"), Omit):
@@ -423,6 +427,10 @@ class AsyncAnthropic(AsyncAPIClient):
423
427
 
424
428
  @override
425
429
  def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
430
+ if headers.get("Authorization") or headers.get("X-Api-Key"):
431
+ # valid
432
+ return
433
+
426
434
  if self.api_key and headers.get("X-Api-Key"):
427
435
  return
428
436
  if isinstance(custom_headers.get("X-Api-Key"), Omit):
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.73.0" # x-release-please-version
4
+ __version__ = "0.74.1" # x-release-please-version
anthropic/lib/_files.py CHANGED
@@ -22,7 +22,7 @@ def _collect_files(directory: Path, relative_to: Path, files: list[FileTypes]) -
22
22
  _collect_files(path, relative_to, files)
23
23
  continue
24
24
 
25
- files.append((str(path.relative_to(relative_to)), path.read_bytes()))
25
+ files.append((path.relative_to(relative_to).as_posix(), path.read_bytes()))
26
26
 
27
27
 
28
28
  async def async_files_from_dir(directory: str | os.PathLike[str]) -> list[FileTypes]:
@@ -39,4 +39,4 @@ async def _async_collect_files(directory: anyio.Path, relative_to: anyio.Path, f
39
39
  await _async_collect_files(path, relative_to, files)
40
40
  continue
41
41
 
42
- files.append((str(path.relative_to(relative_to)), await path.read_bytes()))
42
+ files.append((path.relative_to(relative_to).as_posix(), await path.read_bytes()))
@@ -0,0 +1,127 @@
1
+ # Anthropic Foundry
2
+
3
+ To use this library with Foundry, use the `AnthropicFoundry` class instead of the `Anthropic` class.
4
+
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install anthropic
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ### Basic Usage with API Key
15
+
16
+ ```python
17
+ from anthropic import AnthropicFoundry
18
+
19
+ client = AnthropicFoundry(
20
+ api_key="...", # defaults to ANTHROPIC_FOUNDRY_API_KEY environment variable
21
+ resource="my-resource", # your Foundry resource
22
+ )
23
+
24
+ message = client.messages.create(
25
+ model="claude-3-5-sonnet-20241022",
26
+ max_tokens=1024,
27
+ messages=[{"role": "user", "content": "Hello!"}],
28
+ )
29
+
30
+ print(message.content[0].text)
31
+ ```
32
+
33
+ ### Using Azure AD Token Provider
34
+
35
+ For enhanced security, you can use Azure AD (Microsoft Entra) authentication instead of an API key:
36
+
37
+ ```python
38
+ from anthropic import AnthropicFoundry
39
+ from azure.identity import DefaultAzureCredential
40
+ from azure.identity import get_bearer_token_provider
41
+
42
+ credential = DefaultAzureCredential()
43
+ token_provider = get_bearer_token_provider(
44
+ credential,
45
+ "https://ai.azure.com/.default"
46
+ )
47
+
48
+ client = AnthropicFoundry(
49
+ azure_ad_token_provider=token_provider,
50
+ resource="my-resource",
51
+ )
52
+
53
+ message = client.messages.create(
54
+ model="claude-3-5-sonnet-20241022",
55
+ max_tokens=1024,
56
+ messages=[{"role": "user", "content": "Hello!"}],
57
+ )
58
+
59
+ print(message.content[0].text)
60
+ ```
61
+
62
+ ## Examples
63
+
64
+ ### Streaming Messages
65
+
66
+ ```python
67
+ from anthropic import AnthropicFoundry
68
+
69
+ client = AnthropicFoundry(
70
+ api_key="...",
71
+ resource="my-resource",
72
+ )
73
+
74
+ with client.messages.stream(
75
+ model="claude-3-5-sonnet-20241022",
76
+ max_tokens=1024,
77
+ messages=[{"role": "user", "content": "Write a haiku about programming"}],
78
+ ) as stream:
79
+ for text in stream.text_stream:
80
+ print(text, end="", flush=True)
81
+ ```
82
+
83
+ ### Async Usage
84
+
85
+ ```python
86
+ from anthropic import AsyncAnthropicFoundry
87
+
88
+ async def main():
89
+ client = AsyncAnthropicFoundry(
90
+ api_key="...",
91
+ resource="my-resource",
92
+ )
93
+
94
+ message = await client.messages.create(
95
+ model="claude-3-5-sonnet-20241022",
96
+ max_tokens=1024,
97
+ messages=[{"role": "user", "content": "Hello!"}],
98
+ )
99
+
100
+ print(message.content[0].text)
101
+
102
+ import asyncio
103
+ asyncio.run(main())
104
+ ```
105
+
106
+ ### Async Streaming
107
+
108
+ ```python
109
+ from anthropic import AsyncAnthropicFoundry
110
+
111
+ async def main():
112
+ client = AsyncAnthropicFoundry(
113
+ api_key="...",
114
+ resource="my-resource",
115
+ )
116
+
117
+ async with client.messages.stream(
118
+ model="claude-3-5-sonnet-20241022",
119
+ max_tokens=1024,
120
+ messages=[{"role": "user", "content": "Write a haiku about programming"}],
121
+ ) as stream:
122
+ async for text in stream.text_stream:
123
+ print(text, end="", flush=True)
124
+
125
+ import asyncio
126
+ asyncio.run(main())
127
+ ```
@@ -0,0 +1,443 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import inspect
5
+ from typing import Any, Union, Mapping, TypeVar, Callable, Awaitable, cast, overload
6
+ from functools import cached_property
7
+ from typing_extensions import Self, override
8
+
9
+ import httpx
10
+
11
+ from .._types import NOT_GIVEN, Omit, Timeout, NotGiven
12
+ from .._utils import is_given
13
+ from .._client import Anthropic, AsyncAnthropic
14
+ from .._compat import model_copy
15
+ from .._models import FinalRequestOptions
16
+ from .._streaming import Stream, AsyncStream
17
+ from .._exceptions import AnthropicError
18
+ from .._base_client import DEFAULT_MAX_RETRIES, BaseClient
19
+ from ..resources.beta import Beta, AsyncBeta
20
+ from ..resources.messages import Messages, AsyncMessages
21
+ from ..resources.beta.messages import Messages as BetaMessages, AsyncMessages as AsyncBetaMessages
22
+
23
+ AzureADTokenProvider = Callable[[], str]
24
+ AsyncAzureADTokenProvider = Callable[[], "str | Awaitable[str]"]
25
+ _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient])
26
+ _DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]])
27
+
28
+
29
+ class MutuallyExclusiveAuthError(AnthropicError):
30
+ def __init__(self) -> None:
31
+ super().__init__(
32
+ "The `api_key` and `azure_ad_token_provider` arguments are mutually exclusive; Only one can be passed at a time"
33
+ )
34
+
35
+
36
+ class BaseFoundryClient(BaseClient[_HttpxClientT, _DefaultStreamT]): ...
37
+
38
+
39
+ class MessagesFoundry(Messages):
40
+ @cached_property
41
+ @override
42
+ def batches(self) -> None: # type: ignore[override]
43
+ """Batches endpoint is not supported for Anthropic Foundry client."""
44
+ return None
45
+
46
+
47
+ class BetaFoundryMessages(BetaMessages):
48
+ @cached_property
49
+ @override
50
+ def batches(self) -> None: # type: ignore[override]
51
+ """Batches endpoint is not supported for Anthropic Foundry client."""
52
+ return None
53
+
54
+
55
+ class BetaFoundry(Beta):
56
+ @cached_property
57
+ @override
58
+ def messages(self) -> BetaMessages: # type: ignore[override]
59
+ """Return beta messages resource instance with excluded unsupported endpoints."""
60
+ return BetaFoundryMessages(self._client)
61
+
62
+
63
+ class AsyncMessagesFoundry(AsyncMessages):
64
+ @cached_property
65
+ @override
66
+ def batches(self) -> None: # type: ignore[override]
67
+ """Batches endpoint is not supported for Anthropic Foundry client."""
68
+ return None
69
+
70
+
71
+ class AsyncBetaFoundryMessages(AsyncBetaMessages):
72
+ @cached_property
73
+ @override
74
+ def batches(self) -> None: # type: ignore[override]
75
+ """Batches endpoint is not supported for Anthropic Foundry client."""
76
+ return None
77
+
78
+
79
+ class AsyncBetaFoundry(AsyncBeta):
80
+ @cached_property
81
+ @override
82
+ def messages(self) -> AsyncBetaMessages: # type: ignore[override]
83
+ """Return beta messages resource instance with excluded unsupported endpoints."""
84
+ return AsyncBetaFoundryMessages(self._client)
85
+
86
+
87
+ # ==============================================================================
88
+
89
+
90
+ class AnthropicFoundry(BaseFoundryClient[httpx.Client, Stream[Any]], Anthropic):
91
+ @overload
92
+ def __init__(
93
+ self,
94
+ *,
95
+ resource: str | None = None,
96
+ api_key: str | None = None,
97
+ azure_ad_token_provider: AzureADTokenProvider | None = None,
98
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
99
+ max_retries: int = DEFAULT_MAX_RETRIES,
100
+ default_headers: Mapping[str, str] | None = None,
101
+ default_query: Mapping[str, object] | None = None,
102
+ http_client: httpx.Client | None = None,
103
+ _strict_response_validation: bool = False,
104
+ ) -> None: ...
105
+
106
+ @overload
107
+ def __init__(
108
+ self,
109
+ *,
110
+ base_url: str,
111
+ api_key: str | None = None,
112
+ azure_ad_token_provider: AzureADTokenProvider | None = None,
113
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
114
+ max_retries: int = DEFAULT_MAX_RETRIES,
115
+ default_headers: Mapping[str, str] | None = None,
116
+ default_query: Mapping[str, object] | None = None,
117
+ http_client: httpx.Client | None = None,
118
+ _strict_response_validation: bool = False,
119
+ ) -> None: ...
120
+
121
+ def __init__(
122
+ self,
123
+ *,
124
+ resource: str | None = None,
125
+ api_key: str | None = None,
126
+ azure_ad_token_provider: AzureADTokenProvider | None = None,
127
+ base_url: str | None = None,
128
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
129
+ max_retries: int = DEFAULT_MAX_RETRIES,
130
+ default_headers: Mapping[str, str] | None = None,
131
+ default_query: Mapping[str, object] | None = None,
132
+ http_client: httpx.Client | None = None,
133
+ _strict_response_validation: bool = False,
134
+ ) -> None:
135
+ """Construct a new synchronous Anthropic Foundry client instance.
136
+
137
+ This automatically infers the following arguments from their corresponding environment variables if they are not provided:
138
+ - `api_key` from `ANTHROPIC_FOUNDRY_API_KEY`
139
+ - `resource` from `ANTHROPIC_FOUNDRY_RESOURCE`
140
+ - `base_url` from `ANTHROPIC_FOUNDRY_BASE_URL`
141
+
142
+ Args:
143
+ resource: Your Foundry resource name, e.g. `example-resource` for `https://example-resource.services.ai.azure.com/anthropic/`
144
+ azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request.
145
+ """
146
+ api_key = api_key if api_key is not None else os.environ.get("ANTHROPIC_FOUNDRY_API_KEY")
147
+ resource = resource if resource is not None else os.environ.get("ANTHROPIC_FOUNDRY_RESOURCE")
148
+ base_url = base_url if base_url is not None else os.environ.get("ANTHROPIC_FOUNDRY_BASE_URL")
149
+
150
+ if api_key is None and azure_ad_token_provider is None:
151
+ raise AnthropicError(
152
+ "Missing credentials. Please pass one of `api_key`, `azure_ad_token_provider`, or the `ANTHROPIC_FOUNDRY_API_KEY` environment variable."
153
+ )
154
+
155
+ if base_url is None:
156
+ if resource is None:
157
+ raise ValueError(
158
+ "Must provide one of the `base_url` or `resource` arguments, or the `ANTHROPIC_FOUNDRY_RESOURCE` environment variable"
159
+ )
160
+ base_url = f"https://{resource}.services.ai.azure.com/anthropic/"
161
+ elif resource is not None:
162
+ raise ValueError("base_url and resource are mutually exclusive")
163
+
164
+ super().__init__(
165
+ api_key=api_key,
166
+ base_url=base_url,
167
+ timeout=timeout,
168
+ max_retries=max_retries,
169
+ default_headers=default_headers,
170
+ default_query=default_query,
171
+ http_client=http_client,
172
+ _strict_response_validation=_strict_response_validation,
173
+ )
174
+ self._azure_ad_token_provider = azure_ad_token_provider
175
+
176
+ @cached_property
177
+ @override
178
+ def models(self) -> None: # type: ignore[override]
179
+ """Models endpoint is not supported for Anthropic Foundry client."""
180
+ return None
181
+
182
+ @cached_property
183
+ @override
184
+ def messages(self) -> MessagesFoundry: # type: ignore[override]
185
+ """Return messages resource instance with excluded unsupported endpoints."""
186
+ return MessagesFoundry(client=self)
187
+
188
+ @cached_property
189
+ @override
190
+ def beta(self) -> Beta: # type: ignore[override]
191
+ """Return beta resource instance with excluded unsupported endpoints."""
192
+ return BetaFoundry(self)
193
+
194
+ @override
195
+ def copy(
196
+ self,
197
+ *,
198
+ api_key: str | None = None,
199
+ azure_ad_token_provider: AzureADTokenProvider | None = None,
200
+ auth_token: str | None = None,
201
+ base_url: str | httpx.URL | None = None,
202
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
203
+ http_client: httpx.Client | None = None,
204
+ max_retries: int | NotGiven = NOT_GIVEN,
205
+ default_headers: Mapping[str, str] | None = None,
206
+ set_default_headers: Mapping[str, str] | None = None,
207
+ default_query: Mapping[str, object] | None = None,
208
+ set_default_query: Mapping[str, object] | None = None,
209
+ _extra_kwargs: Mapping[str, Any] = {},
210
+ ) -> Self:
211
+ """
212
+ Create a new client instance re-using the same options given to the current client with optional overriding.
213
+ """
214
+ return super().copy(
215
+ api_key=api_key,
216
+ auth_token=auth_token,
217
+ base_url=base_url,
218
+ timeout=timeout,
219
+ http_client=http_client,
220
+ max_retries=max_retries,
221
+ default_headers=default_headers,
222
+ set_default_headers=set_default_headers,
223
+ default_query=default_query,
224
+ set_default_query=set_default_query,
225
+ _extra_kwargs={
226
+ "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider,
227
+ **_extra_kwargs,
228
+ },
229
+ )
230
+
231
+ with_options = copy
232
+
233
+ def _get_azure_ad_token(self) -> str | None:
234
+ provider = self._azure_ad_token_provider
235
+ if provider is not None:
236
+ token = provider()
237
+ if not token or not isinstance(token, str): # pyright: ignore[reportUnnecessaryIsInstance]
238
+ raise ValueError(
239
+ f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}",
240
+ )
241
+ return token
242
+
243
+ return None
244
+
245
+ @override
246
+ def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
247
+ headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {}
248
+
249
+ options = model_copy(options)
250
+ options.headers = headers
251
+
252
+ azure_ad_token = self._get_azure_ad_token()
253
+ if azure_ad_token is not None:
254
+ if headers.get("Authorization") is None:
255
+ headers["Authorization"] = f"Bearer {azure_ad_token}"
256
+ elif self.api_key is not None:
257
+ if headers.get("api-key") is None:
258
+ assert self.api_key is not None
259
+ headers["api-key"] = self.api_key
260
+ else:
261
+ # should never be hit
262
+ raise ValueError("Unable to handle auth")
263
+
264
+ return options
265
+
266
+
267
+ class AsyncAnthropicFoundry(BaseFoundryClient[httpx.AsyncClient, AsyncStream[Any]], AsyncAnthropic):
268
+ @overload
269
+ def __init__(
270
+ self,
271
+ *,
272
+ resource: str | None = None,
273
+ api_key: str | None = None,
274
+ azure_ad_token_provider: AsyncAzureADTokenProvider | None = None,
275
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
276
+ max_retries: int = DEFAULT_MAX_RETRIES,
277
+ default_headers: Mapping[str, str] | None = None,
278
+ default_query: Mapping[str, object] | None = None,
279
+ http_client: httpx.AsyncClient | None = None,
280
+ _strict_response_validation: bool = False,
281
+ ) -> None: ...
282
+
283
+ @overload
284
+ def __init__(
285
+ self,
286
+ *,
287
+ base_url: str,
288
+ api_key: str | None = None,
289
+ azure_ad_token_provider: AsyncAzureADTokenProvider | None = None,
290
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
291
+ max_retries: int = DEFAULT_MAX_RETRIES,
292
+ default_headers: Mapping[str, str] | None = None,
293
+ default_query: Mapping[str, object] | None = None,
294
+ http_client: httpx.AsyncClient | None = None,
295
+ _strict_response_validation: bool = False,
296
+ ) -> None: ...
297
+
298
+ def __init__(
299
+ self,
300
+ *,
301
+ resource: str | None = None,
302
+ api_key: str | None = None,
303
+ azure_ad_token_provider: AsyncAzureADTokenProvider | None = None,
304
+ base_url: str | None = None,
305
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
306
+ max_retries: int = DEFAULT_MAX_RETRIES,
307
+ default_headers: Mapping[str, str] | None = None,
308
+ default_query: Mapping[str, object] | None = None,
309
+ http_client: httpx.AsyncClient | None = None,
310
+ _strict_response_validation: bool = False,
311
+ ) -> None:
312
+ """Construct a new asynchronous Anthropic Foundry client instance.
313
+
314
+ This automatically infers the following arguments from their corresponding environment variables if they are not provided:
315
+ - `api_key` from `ANTHROPIC_FOUNDRY_API_KEY`
316
+ - `resource` from `ANTHROPIC_FOUNDRY_RESOURCE`
317
+ - `base_url` from `ANTHROPIC_FOUNDRY_BASE_URL`
318
+
319
+ Args:
320
+ resource: Your Foundry resource name, e.g. `example-resource` for `https://example-resource.services.ai.azure.com/anthropic/`
321
+ azure_ad_token_provider: A function that returns an Azure Active Directory token, will be invoked on every request.
322
+ """
323
+ api_key = api_key if api_key is not None else os.environ.get("ANTHROPIC_FOUNDRY_API_KEY")
324
+ resource = resource if resource is not None else os.environ.get("ANTHROPIC_FOUNDRY_RESOURCE")
325
+ base_url = base_url if base_url is not None else os.environ.get("ANTHROPIC_FOUNDRY_BASE_URL")
326
+
327
+ if api_key is None and azure_ad_token_provider is None:
328
+ raise AnthropicError(
329
+ "Missing credentials. Please pass one of `api_key`, `azure_ad_token_provider`, or the `ANTHROPIC_FOUNDRY_API_KEY` environment variable."
330
+ )
331
+
332
+ if base_url is None:
333
+ if resource is None:
334
+ raise ValueError(
335
+ "Must provide one of the `base_url` or `resource` arguments, or the `ANTHROPIC_FOUNDRY_RESOURCE` environment variable"
336
+ )
337
+ base_url = f"https://{resource}.services.ai.azure.com/anthropic/"
338
+ elif resource is not None:
339
+ raise ValueError("base_url and resource are mutually exclusive")
340
+
341
+ super().__init__(
342
+ api_key=api_key,
343
+ base_url=base_url,
344
+ timeout=timeout,
345
+ max_retries=max_retries,
346
+ default_headers=default_headers,
347
+ default_query=default_query,
348
+ http_client=http_client,
349
+ _strict_response_validation=_strict_response_validation,
350
+ )
351
+ self._azure_ad_token_provider = azure_ad_token_provider
352
+
353
+ @cached_property
354
+ @override
355
+ def models(self) -> None: # type: ignore[override]
356
+ """Models endpoint is not supported for Azure Anthropic client."""
357
+ return None
358
+
359
+ @cached_property
360
+ @override
361
+ def messages(self) -> AsyncMessagesFoundry: # type: ignore[override]
362
+ """Return messages resource instance with excluded unsupported endpoints."""
363
+ return AsyncMessagesFoundry(client=self)
364
+
365
+ @cached_property
366
+ @override
367
+ def beta(self) -> AsyncBetaFoundry: # type: ignore[override]
368
+ """Return beta resource instance with excluded unsupported endpoints."""
369
+ return AsyncBetaFoundry(client=self)
370
+
371
+ @override
372
+ def copy(
373
+ self,
374
+ *,
375
+ api_key: str | None = None,
376
+ azure_ad_token_provider: AsyncAzureADTokenProvider | None = None,
377
+ auth_token: str | None = None,
378
+ base_url: str | httpx.URL | None = None,
379
+ timeout: float | Timeout | None | NotGiven = NOT_GIVEN,
380
+ http_client: httpx.AsyncClient | None = None,
381
+ max_retries: int | NotGiven = NOT_GIVEN,
382
+ default_headers: Mapping[str, str] | None = None,
383
+ set_default_headers: Mapping[str, str] | None = None,
384
+ default_query: Mapping[str, object] | None = None,
385
+ set_default_query: Mapping[str, object] | None = None,
386
+ _extra_kwargs: Mapping[str, Any] = {},
387
+ ) -> Self:
388
+ """
389
+ Create a new client instance re-using the same options given to the current client with optional overriding.
390
+ """
391
+ return super().copy(
392
+ api_key=api_key,
393
+ auth_token=auth_token,
394
+ base_url=base_url,
395
+ timeout=timeout,
396
+ http_client=http_client,
397
+ max_retries=max_retries,
398
+ default_headers=default_headers,
399
+ set_default_headers=set_default_headers,
400
+ default_query=default_query,
401
+ set_default_query=set_default_query,
402
+ _extra_kwargs={
403
+ "azure_ad_token_provider": azure_ad_token_provider or self._azure_ad_token_provider,
404
+ **_extra_kwargs,
405
+ },
406
+ )
407
+
408
+ with_options = copy
409
+
410
+ async def _get_azure_ad_token(self) -> str | None:
411
+ provider = self._azure_ad_token_provider
412
+ if provider is not None:
413
+ token = provider()
414
+ if inspect.isawaitable(token):
415
+ token = await token
416
+ if not token or not isinstance(cast(Any, token), str):
417
+ raise ValueError(
418
+ f"Expected `azure_ad_token_provider` argument to return a string but it returned {token}",
419
+ )
420
+ return str(token)
421
+
422
+ return None
423
+
424
+ @override
425
+ async def _prepare_options(self, options: FinalRequestOptions) -> FinalRequestOptions:
426
+ headers: dict[str, str | Omit] = {**options.headers} if is_given(options.headers) else {}
427
+
428
+ options = model_copy(options)
429
+ options.headers = headers
430
+
431
+ azure_ad_token = await self._get_azure_ad_token()
432
+ if azure_ad_token is not None:
433
+ if headers.get("Authorization") is None:
434
+ headers["Authorization"] = f"Bearer {azure_ad_token}"
435
+ elif self.api_key is not None:
436
+ assert self.api_key is not None
437
+ if headers.get("api-key") is None:
438
+ headers["api-key"] = self.api_key
439
+ else:
440
+ # should never be hit
441
+ raise ValueError("Unable to handle auth")
442
+
443
+ return options
@@ -1076,9 +1076,9 @@ class Messages(SyncAPIResource):
1076
1076
 
1077
1077
  betas = [beta for beta in betas] if is_given(betas) else []
1078
1078
 
1079
- if "structured-outputs-2025-09-17" not in betas:
1079
+ if "structured-outputs-2025-11-13" not in betas:
1080
1080
  # Ensure structured outputs beta is included for parse method
1081
- betas.append("structured-outputs-2025-09-17")
1081
+ betas.append("structured-outputs-2025-11-13")
1082
1082
 
1083
1083
  extra_headers = {
1084
1084
  "X-Stainless-Helper": "beta.messages.parse",
@@ -2688,9 +2688,9 @@ class AsyncMessages(AsyncAPIResource):
2688
2688
  )
2689
2689
  betas = [beta for beta in betas] if is_given(betas) else []
2690
2690
 
2691
- if "structured-outputs-2025-09-17" not in betas:
2691
+ if "structured-outputs-2025-11-13" not in betas:
2692
2692
  # Ensure structured outputs beta is included for parse method
2693
- betas.append("structured-outputs-2025-09-17")
2693
+ betas.append("structured-outputs-2025-11-13")
2694
2694
 
2695
2695
  extra_headers = {
2696
2696
  "X-Stainless-Helper": "beta.messages.parse",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: anthropic
3
- Version: 0.73.0
3
+ Version: 0.74.1
4
4
  Summary: The official Python library for the anthropic API
5
5
  Project-URL: Homepage, https://github.com/anthropics/anthropic-sdk-python
6
6
  Project-URL: Repository, https://github.com/anthropics/anthropic-sdk-python
@@ -1,6 +1,6 @@
1
- anthropic/__init__.py,sha256=rppe09RSa1Lpxfa6FsTQuwOA0Y8XDaICjtgWwncpnLA,3057
1
+ anthropic/__init__.py,sha256=xp5IG2sv6wh0O6u-pJN8g3PJkQHfs2qIfU20muCRyj8,3167
2
2
  anthropic/_base_client.py,sha256=Ca5ANeCg2kvkN3Ego42boLcHIhj9npORXzh3VGQs1tw,72929
3
- anthropic/_client.py,sha256=M90bE_o_HRuBNrbA-D-grLZua841_5NTkzeUQpyE75Y,22812
3
+ anthropic/_client.py,sha256=_BM__6VgtQZZCkWMGv6z58yTESUDtQVt2QWZIy_ya7U,23030
4
4
  anthropic/_compat.py,sha256=t3bXgTygusFSjp0qoTb9D6E749djY0tFAwHMgKEE-Rw,6775
5
5
  anthropic/_constants.py,sha256=wADeUqY3lsseF0L6jIen-PexfQ06FOtf2dVESXDM828,885
6
6
  anthropic/_exceptions.py,sha256=bkSqVWxtRdRb31H7MIvtxfh5mo_Xf7Ib3nPTOmAOmGs,4073
@@ -12,7 +12,7 @@ anthropic/_resource.py,sha256=FYEOzfhB-XWTR2gyTmQuuFoecRiVXxe_SpjZlQQGytU,1080
12
12
  anthropic/_response.py,sha256=1Y7-OrGn1lOwvZ_SmMlwT9Nb2i9A1RYw2Q4-F1cwPSU,30542
13
13
  anthropic/_streaming.py,sha256=AVgSkkvKHZsFD4xQbkOi9Oi0vkHoEZbkccyUw5yIxmA,14072
14
14
  anthropic/_types.py,sha256=vEab5B5Hp7xQQafVrgSCHeEPUmf74jofqIPo-n7Xljk,7338
15
- anthropic/_version.py,sha256=BLfER8BI7EhiCmW-EJcMjRIx012RjifoyJ7qwdyvum8,162
15
+ anthropic/_version.py,sha256=RYabrekg643fRS1GXAocPuIMGw1-85RFzoldGyJ7Sxs,162
16
16
  anthropic/pagination.py,sha256=MgGFbx3GDm4XASijWas0-2eVb1iGR-DgqyPrDf5Jll8,5152
17
17
  anthropic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  anthropic/_decoders/jsonl.py,sha256=KDLw-Frjo7gRup5qDp_BWkXIZ-mFZU5vFDz0WBhEKcs,3510
@@ -31,7 +31,9 @@ anthropic/_utils/_typing.py,sha256=N_5PPuFNsaygbtA_npZd98SVN1LQQvFTKL6bkWPBZGU,4
31
31
  anthropic/_utils/_utils.py,sha256=ugfUaneOK7I8h9b3656flwf5u_kthY0gvNuqvgOLoSU,12252
32
32
  anthropic/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
33
33
  anthropic/lib/__init__.py,sha256=ed3VXosCln6iXSojwutNZjzjoIVpDLIHfMiiMiSHjlU,99
34
- anthropic/lib/_files.py,sha256=7gggVMi-rWE-42gElwl7nncy3Gf_V62Ga6cIln_yG_M,1209
34
+ anthropic/lib/_files.py,sha256=gVtOWR-evsIJV_HCX225tPRU6Dyj73FWXb7OPt5CVcQ,1221
35
+ anthropic/lib/foundry.md,sha256=jFWVnP5a8qARzQjUdtvxhF1p2pkPo2WCRfkumhvdlZw,2745
36
+ anthropic/lib/foundry.py,sha256=q4fZOnbBcBWFE_fVwL9EyJBFt-RFk0l78bzFxyO9Q2k,17537
35
37
  anthropic/lib/_extras/__init__.py,sha256=a9HX69-V9nROM4Em9a4y-xZTgiLE2jdlCyC6ZKtxfyY,53
36
38
  anthropic/lib/_extras/_common.py,sha256=IhHjAsirY2xfLJrzlt9rS_0IPsTJeWqKA2HWUuvDN14,348
37
39
  anthropic/lib/_extras/_google_auth.py,sha256=Wukh6VOgcDRYSsFCVT9tx_oXI1ApIsmioSLEMsYvDfw,688
@@ -67,7 +69,7 @@ anthropic/resources/beta/files.py,sha256=rz2seKKOcoF0ebUMEMF86LoPWi1YqK2zp-dMQ7t
67
69
  anthropic/resources/beta/models.py,sha256=1bPko6YIziXlKj9GWnAxReEoWIT_7TwBpU_oCUMhBlo,12516
68
70
  anthropic/resources/beta/messages/__init__.py,sha256=7ZO4hB7hPBhXQja7gMzkwLXQVDlyap4JsihpA0UKZjk,849
69
71
  anthropic/resources/beta/messages/batches.py,sha256=51m83Ijs6cIE_f4hRQNhSyNqDj5TVt0F0Bm4ryekoLw,36116
70
- anthropic/resources/beta/messages/messages.py,sha256=OPTTYEaPMx31_vHXsjkt9cvPXpKNTa-G1jt_iK98phc,151689
72
+ anthropic/resources/beta/messages/messages.py,sha256=tnm8ra108AC1AjQ2neWCFHbdYVQPU3_J1aKSWemjAVI,151689
71
73
  anthropic/resources/beta/skills/__init__.py,sha256=QMC_HEzfI-k0jhfKJThUUjf9wf7Vs8HTxSXYNnvVx2o,836
72
74
  anthropic/resources/beta/skills/skills.py,sha256=ytCR9JN7Qgn9GbWT0oBgpy-nvYXWwqoBvOzZ_iURANE,25036
73
75
  anthropic/resources/beta/skills/versions.py,sha256=iWSrZ4iqVGm16f7r_aE79gDxeUTUaSw5dEBAyHIxRu8,25212
@@ -411,7 +413,7 @@ anthropic/types/shared/not_found_error.py,sha256=R6OsCvAmsf_SB2TwoX6E63o049qZMaA
411
413
  anthropic/types/shared/overloaded_error.py,sha256=PlyhHt3wmzcnynSfkWbfP4XkLoWsPa9B39V3CyAdgx8,282
412
414
  anthropic/types/shared/permission_error.py,sha256=nuyxtLXOiEkYEbFRXiAWjxU6XtdyjkAaXQ2NgMB3pjw,282
413
415
  anthropic/types/shared/rate_limit_error.py,sha256=eYULATjXa6KKdqeBauest7RzuN-bhGsY5BWwH9eYv4c,280
414
- anthropic-0.73.0.dist-info/METADATA,sha256=BOMTTUbACjvJH9v6O9RAUEY3RgkH12gkbN5vRHAGeI8,28514
415
- anthropic-0.73.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
416
- anthropic-0.73.0.dist-info/licenses/LICENSE,sha256=i_lphP-Lz65-SMrnalKeiiUxe6ngKr9_08xk_flWV6Y,1056
417
- anthropic-0.73.0.dist-info/RECORD,,
416
+ anthropic-0.74.1.dist-info/METADATA,sha256=hj9E86URKPzwsGvQYSWbc106lywLRwyc6x-_TMkFtkU,28514
417
+ anthropic-0.74.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
418
+ anthropic-0.74.1.dist-info/licenses/LICENSE,sha256=i_lphP-Lz65-SMrnalKeiiUxe6ngKr9_08xk_flWV6Y,1056
419
+ anthropic-0.74.1.dist-info/RECORD,,