mirascope 2.0.0a3__py3-none-any.whl → 2.0.0a5__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 (118) hide show
  1. mirascope/api/_generated/__init__.py +78 -6
  2. mirascope/api/_generated/api_keys/__init__.py +7 -0
  3. mirascope/api/_generated/api_keys/client.py +453 -0
  4. mirascope/api/_generated/api_keys/raw_client.py +853 -0
  5. mirascope/api/_generated/api_keys/types/__init__.py +9 -0
  6. mirascope/api/_generated/api_keys/types/api_keys_create_response.py +36 -0
  7. mirascope/api/_generated/api_keys/types/api_keys_get_response.py +35 -0
  8. mirascope/api/_generated/api_keys/types/api_keys_list_response_item.py +35 -0
  9. mirascope/api/_generated/client.py +14 -0
  10. mirascope/api/_generated/environments/__init__.py +17 -0
  11. mirascope/api/_generated/environments/client.py +532 -0
  12. mirascope/api/_generated/environments/raw_client.py +1088 -0
  13. mirascope/api/_generated/environments/types/__init__.py +15 -0
  14. mirascope/api/_generated/environments/types/environments_create_response.py +26 -0
  15. mirascope/api/_generated/environments/types/environments_get_response.py +26 -0
  16. mirascope/api/_generated/environments/types/environments_list_response_item.py +26 -0
  17. mirascope/api/_generated/environments/types/environments_update_response.py +26 -0
  18. mirascope/api/_generated/errors/__init__.py +11 -1
  19. mirascope/api/_generated/errors/conflict_error.py +15 -0
  20. mirascope/api/_generated/errors/forbidden_error.py +15 -0
  21. mirascope/api/_generated/errors/internal_server_error.py +15 -0
  22. mirascope/api/_generated/errors/not_found_error.py +15 -0
  23. mirascope/api/_generated/organizations/__init__.py +25 -0
  24. mirascope/api/_generated/organizations/client.py +404 -0
  25. mirascope/api/_generated/organizations/raw_client.py +902 -0
  26. mirascope/api/_generated/organizations/types/__init__.py +23 -0
  27. mirascope/api/_generated/organizations/types/organizations_create_response.py +25 -0
  28. mirascope/api/_generated/organizations/types/organizations_create_response_role.py +7 -0
  29. mirascope/api/_generated/organizations/types/organizations_get_response.py +25 -0
  30. mirascope/api/_generated/organizations/types/organizations_get_response_role.py +7 -0
  31. mirascope/api/_generated/organizations/types/organizations_list_response_item.py +25 -0
  32. mirascope/api/_generated/organizations/types/organizations_list_response_item_role.py +7 -0
  33. mirascope/api/_generated/organizations/types/organizations_update_response.py +25 -0
  34. mirascope/api/_generated/organizations/types/organizations_update_response_role.py +7 -0
  35. mirascope/api/_generated/projects/__init__.py +17 -0
  36. mirascope/api/_generated/projects/client.py +482 -0
  37. mirascope/api/_generated/projects/raw_client.py +1058 -0
  38. mirascope/api/_generated/projects/types/__init__.py +15 -0
  39. mirascope/api/_generated/projects/types/projects_create_response.py +31 -0
  40. mirascope/api/_generated/projects/types/projects_get_response.py +31 -0
  41. mirascope/api/_generated/projects/types/projects_list_response_item.py +31 -0
  42. mirascope/api/_generated/projects/types/projects_update_response.py +31 -0
  43. mirascope/api/_generated/reference.md +1311 -0
  44. mirascope/api/_generated/types/__init__.py +20 -4
  45. mirascope/api/_generated/types/already_exists_error.py +24 -0
  46. mirascope/api/_generated/types/already_exists_error_tag.py +5 -0
  47. mirascope/api/_generated/types/database_error.py +24 -0
  48. mirascope/api/_generated/types/database_error_tag.py +5 -0
  49. mirascope/api/_generated/types/http_api_decode_error.py +1 -3
  50. mirascope/api/_generated/types/issue.py +1 -5
  51. mirascope/api/_generated/types/not_found_error_body.py +24 -0
  52. mirascope/api/_generated/types/not_found_error_tag.py +5 -0
  53. mirascope/api/_generated/types/permission_denied_error.py +24 -0
  54. mirascope/api/_generated/types/permission_denied_error_tag.py +7 -0
  55. mirascope/api/_generated/types/property_key.py +2 -2
  56. mirascope/api/_generated/types/{property_key_tag.py → property_key_key.py} +3 -5
  57. mirascope/api/_generated/types/{property_key_tag_tag.py → property_key_key_tag.py} +1 -1
  58. mirascope/llm/__init__.py +6 -2
  59. mirascope/llm/exceptions.py +28 -0
  60. mirascope/llm/providers/__init__.py +12 -4
  61. mirascope/llm/providers/anthropic/__init__.py +6 -1
  62. mirascope/llm/providers/anthropic/_utils/__init__.py +17 -5
  63. mirascope/llm/providers/anthropic/_utils/beta_decode.py +271 -0
  64. mirascope/llm/providers/anthropic/_utils/beta_encode.py +216 -0
  65. mirascope/llm/providers/anthropic/_utils/decode.py +39 -7
  66. mirascope/llm/providers/anthropic/_utils/encode.py +156 -64
  67. mirascope/llm/providers/anthropic/_utils/errors.py +46 -0
  68. mirascope/llm/providers/anthropic/beta_provider.py +328 -0
  69. mirascope/llm/providers/anthropic/model_id.py +10 -27
  70. mirascope/llm/providers/anthropic/model_info.py +87 -0
  71. mirascope/llm/providers/anthropic/provider.py +132 -145
  72. mirascope/llm/providers/base/__init__.py +2 -1
  73. mirascope/llm/providers/base/_utils.py +15 -1
  74. mirascope/llm/providers/base/base_provider.py +173 -58
  75. mirascope/llm/providers/google/_utils/__init__.py +2 -0
  76. mirascope/llm/providers/google/_utils/decode.py +55 -3
  77. mirascope/llm/providers/google/_utils/encode.py +14 -6
  78. mirascope/llm/providers/google/_utils/errors.py +49 -0
  79. mirascope/llm/providers/google/model_id.py +7 -13
  80. mirascope/llm/providers/google/model_info.py +62 -0
  81. mirascope/llm/providers/google/provider.py +13 -8
  82. mirascope/llm/providers/mlx/_utils.py +31 -2
  83. mirascope/llm/providers/mlx/encoding/transformers.py +17 -1
  84. mirascope/llm/providers/mlx/provider.py +12 -0
  85. mirascope/llm/providers/ollama/__init__.py +19 -0
  86. mirascope/llm/providers/ollama/provider.py +71 -0
  87. mirascope/llm/providers/openai/__init__.py +10 -1
  88. mirascope/llm/providers/openai/_utils/__init__.py +5 -0
  89. mirascope/llm/providers/openai/_utils/errors.py +46 -0
  90. mirascope/llm/providers/openai/completions/__init__.py +6 -1
  91. mirascope/llm/providers/openai/completions/_utils/decode.py +57 -5
  92. mirascope/llm/providers/openai/completions/_utils/encode.py +9 -8
  93. mirascope/llm/providers/openai/completions/base_provider.py +513 -0
  94. mirascope/llm/providers/openai/completions/provider.py +13 -447
  95. mirascope/llm/providers/openai/model_info.py +57 -0
  96. mirascope/llm/providers/openai/provider.py +30 -5
  97. mirascope/llm/providers/openai/responses/_utils/decode.py +55 -4
  98. mirascope/llm/providers/openai/responses/_utils/encode.py +9 -9
  99. mirascope/llm/providers/openai/responses/provider.py +33 -28
  100. mirascope/llm/providers/provider_id.py +11 -1
  101. mirascope/llm/providers/provider_registry.py +59 -4
  102. mirascope/llm/providers/together/__init__.py +19 -0
  103. mirascope/llm/providers/together/provider.py +40 -0
  104. mirascope/llm/responses/__init__.py +3 -0
  105. mirascope/llm/responses/base_response.py +4 -0
  106. mirascope/llm/responses/base_stream_response.py +25 -1
  107. mirascope/llm/responses/finish_reason.py +1 -0
  108. mirascope/llm/responses/response.py +9 -0
  109. mirascope/llm/responses/root_response.py +5 -1
  110. mirascope/llm/responses/usage.py +95 -0
  111. mirascope/ops/_internal/closure.py +62 -11
  112. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/METADATA +3 -3
  113. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/RECORD +115 -56
  114. mirascope/llm/providers/load_provider.py +0 -48
  115. mirascope/llm/providers/openai/shared/__init__.py +0 -7
  116. mirascope/llm/providers/openai/shared/_utils.py +0 -59
  117. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/WHEEL +0 -0
  118. {mirascope-2.0.0a3.dist-info → mirascope-2.0.0a5.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,9 @@
1
- """Anthropic message encoding and request preparation."""
1
+ """Shared Anthropic encoding utilities."""
2
2
 
3
3
  import json
4
4
  from collections.abc import Sequence
5
5
  from functools import lru_cache
6
- from typing import Literal, TypedDict, cast
6
+ from typing import Any, Literal, TypedDict, cast
7
7
  from typing_extensions import Required
8
8
 
9
9
  from anthropic import Omit, types as anthropic_types
@@ -22,14 +22,14 @@ from ...base import Params, _utils as _base_utils
22
22
  from ..model_id import AnthropicModelId, model_name
23
23
 
24
24
  DEFAULT_MAX_TOKENS = 16000
25
+ # TODO: Change DEFAULT_FORMAT_MODE to strict when strict is no longer a beta feature.
26
+ DEFAULT_FORMAT_MODE = "tool"
25
27
 
26
28
  AnthropicImageMimeType = Literal["image/jpeg", "image/png", "image/gif", "image/webp"]
27
29
 
28
30
 
29
- def encode_image_mime_type(
30
- mime_type: ImageMimeType,
31
- ) -> AnthropicImageMimeType:
32
- """Convert an ImageMimeType into anthropic supported mime type"""
31
+ def encode_image_mime_type(mime_type: ImageMimeType) -> AnthropicImageMimeType:
32
+ """Convert an ImageMimeType into anthropic supported mime type."""
33
33
  if mime_type in ("image/jpeg", "image/png", "image/gif", "image/webp"):
34
34
  return mime_type
35
35
  raise FeatureNotSupportedError(
@@ -37,13 +37,60 @@ def encode_image_mime_type(
37
37
  ) # pragma: no cover
38
38
 
39
39
 
40
+ class ProcessedParams(TypedDict, total=False):
41
+ """Common parameters processed from Params."""
42
+
43
+ temperature: float
44
+ max_tokens: int
45
+ top_p: float
46
+ top_k: int
47
+ stop_sequences: list[str]
48
+ thinking: dict[str, Any]
49
+ encode_thoughts: bool
50
+
51
+
52
+ def process_params(params: Params, default_max_tokens: int) -> ProcessedParams:
53
+ """Process common Anthropic parameters from Params.
54
+
55
+ Returns a dict with processed parameters that can be merged into kwargs.
56
+ """
57
+ result: ProcessedParams = {
58
+ "max_tokens": default_max_tokens,
59
+ "encode_thoughts": False,
60
+ }
61
+
62
+ with _base_utils.ensure_all_params_accessed(
63
+ params=params, provider_id="anthropic", unsupported_params=["seed"]
64
+ ) as param_accessor:
65
+ if param_accessor.temperature is not None:
66
+ result["temperature"] = param_accessor.temperature
67
+ if param_accessor.max_tokens is not None:
68
+ result["max_tokens"] = param_accessor.max_tokens
69
+ if param_accessor.top_p is not None:
70
+ result["top_p"] = param_accessor.top_p
71
+ if param_accessor.top_k is not None:
72
+ result["top_k"] = param_accessor.top_k
73
+ if param_accessor.stop_sequences is not None:
74
+ result["stop_sequences"] = param_accessor.stop_sequences
75
+ if param_accessor.thinking is not None:
76
+ if param_accessor.thinking:
77
+ budget_tokens = max(1024, result["max_tokens"] // 2)
78
+ result["thinking"] = {"type": "enabled", "budget_tokens": budget_tokens}
79
+ else:
80
+ result["thinking"] = {"type": "disabled"}
81
+ if param_accessor.encode_thoughts_as_text:
82
+ result["encode_thoughts"] = True
83
+
84
+ return result
85
+
86
+
40
87
  class MessageCreateKwargs(TypedDict, total=False):
41
88
  """Kwargs for Anthropic Message.create method."""
42
89
 
43
90
  model: Required[str]
44
91
  max_tokens: Required[int]
45
92
  messages: Sequence[anthropic_types.MessageParam]
46
- system: str | Omit
93
+ system: Sequence[anthropic_types.TextBlockParam] | Omit
47
94
  tools: Sequence[anthropic_types.ToolParam] | Omit
48
95
  tool_choice: anthropic_types.ToolChoiceParam | Omit
49
96
  temperature: float | Omit
@@ -53,8 +100,10 @@ class MessageCreateKwargs(TypedDict, total=False):
53
100
  thinking: anthropic_types.ThinkingConfigParam | Omit
54
101
 
55
102
 
56
- def _encode_content(
57
- content: Sequence[ContentPart], encode_thoughts: bool
103
+ def encode_content(
104
+ content: Sequence[ContentPart],
105
+ encode_thoughts: bool,
106
+ add_cache_control: bool,
58
107
  ) -> str | Sequence[anthropic_types.ContentBlockParam]:
59
108
  """Convert mirascope content to Anthropic content format."""
60
109
 
@@ -65,15 +114,42 @@ def _encode_content(
65
114
  "anthropic",
66
115
  message="Anthropic does not support empty message content.",
67
116
  )
117
+ if add_cache_control:
118
+ return [
119
+ anthropic_types.TextBlockParam(
120
+ type="text",
121
+ text=content[0].text,
122
+ cache_control={"type": "ephemeral"},
123
+ )
124
+ ]
68
125
  return content[0].text
69
126
 
70
127
  blocks: list[anthropic_types.ContentBlockParam] = []
71
128
 
72
- for part in content:
129
+ # Find the last cacheable content part (text, image, tool_result, or tool_call)
130
+ last_cacheable_index = -1
131
+ if add_cache_control:
132
+ for i in range(len(content) - 1, -1, -1):
133
+ part = content[i]
134
+ if part.type in ("text", "image", "tool_output", "tool_call"):
135
+ if part.type == "text" and not part.text: # pragma: no cover
136
+ continue # Skip empty text
137
+ last_cacheable_index = i
138
+ break
139
+
140
+ for i, part in enumerate(content):
141
+ should_add_cache = add_cache_control and i == last_cacheable_index
142
+
73
143
  if part.type == "text":
74
144
  if part.text:
75
145
  blocks.append(
76
- anthropic_types.TextBlockParam(type="text", text=part.text)
146
+ anthropic_types.TextBlockParam(
147
+ type="text",
148
+ text=part.text,
149
+ cache_control={"type": "ephemeral"}
150
+ if should_add_cache
151
+ else None,
152
+ )
77
153
  )
78
154
  elif part.type == "image":
79
155
  source: (
@@ -91,7 +167,13 @@ def _encode_content(
91
167
  type="url",
92
168
  url=part.source.url,
93
169
  )
94
- blocks.append(anthropic_types.ImageBlockParam(type="image", source=source))
170
+ blocks.append(
171
+ anthropic_types.ImageBlockParam(
172
+ type="image",
173
+ source=source,
174
+ cache_control={"type": "ephemeral"} if should_add_cache else None,
175
+ )
176
+ )
95
177
  elif part.type == "audio":
96
178
  raise FeatureNotSupportedError(
97
179
  "audio input",
@@ -104,6 +186,7 @@ def _encode_content(
104
186
  type="tool_result",
105
187
  tool_use_id=part.id,
106
188
  content=str(part.value),
189
+ cache_control={"type": "ephemeral"} if should_add_cache else None,
107
190
  )
108
191
  )
109
192
  elif part.type == "tool_call":
@@ -113,6 +196,7 @@ def _encode_content(
113
196
  id=part.id,
114
197
  name=part.name,
115
198
  input=json.loads(part.args),
199
+ cache_control={"type": "ephemeral"} if should_add_cache else None,
116
200
  )
117
201
  )
118
202
  elif part.type == "thought":
@@ -139,33 +223,60 @@ def _encode_message(
139
223
  message: UserMessage | AssistantMessage,
140
224
  model_id: AnthropicModelId,
141
225
  encode_thoughts: bool,
226
+ add_cache_control: bool = False,
142
227
  ) -> anthropic_types.MessageParam:
143
- """Convert user or assistant `Message`s to Anthropic `MessageParam` format.
228
+ """Convert user or assistant Message to Anthropic MessageParam format.
144
229
 
145
230
  Args:
146
- messages: A Sequence containing `UserMessage`s or `AssistantMessage`s
147
- model_id: The Anthropic model ID being used
148
-
149
- Returns:
150
- A Sequence of converted Anthropic `MessageParam`
231
+ message: The message to encode
232
+ model_id: The Anthropic model ID
233
+ encode_thoughts: Whether to encode thought blocks as text
234
+ add_cache_control: Whether to add cache_control to the last content block
151
235
  """
152
-
153
236
  if (
154
237
  message.role == "assistant"
155
238
  and message.provider_id == "anthropic"
156
239
  and message.model_id == model_id
157
240
  and message.raw_message
158
241
  and not encode_thoughts
242
+ and not add_cache_control
159
243
  ):
160
244
  return cast(anthropic_types.MessageParam, message.raw_message)
245
+
246
+ content = encode_content(message.content, encode_thoughts, add_cache_control)
247
+
161
248
  return {
162
249
  "role": message.role,
163
- "content": _encode_content(message.content, encode_thoughts),
250
+ "content": content,
164
251
  }
165
252
 
166
253
 
254
+ def _encode_messages(
255
+ messages: Sequence[UserMessage | AssistantMessage],
256
+ model_id: AnthropicModelId,
257
+ encode_thoughts: bool,
258
+ ) -> Sequence[anthropic_types.MessageParam]:
259
+ """Encode messages and add cache control for multi-turn conversations.
260
+
261
+ If the conversation contains assistant messages (indicating multi-turn),
262
+ adds cache_control to the last content block of the last message.
263
+ """
264
+ # Detect multi-turn conversations by checking for assistant messages
265
+ has_assistant_message = any(msg.role == "assistant" for msg in messages)
266
+
267
+ # Encode messages, adding cache_control to the last message if multi-turn
268
+ encoded_messages: list[anthropic_types.MessageParam] = []
269
+ for i, message in enumerate(messages):
270
+ is_last = i == len(messages) - 1
271
+ add_cache = has_assistant_message and is_last
272
+ encoded_messages.append(
273
+ _encode_message(message, model_id, encode_thoughts, add_cache)
274
+ )
275
+ return encoded_messages
276
+
277
+
167
278
  @lru_cache(maxsize=128)
168
- def _convert_tool_to_tool_param(tool: AnyToolSchema) -> anthropic_types.ToolParam:
279
+ def convert_tool_to_tool_param(tool: AnyToolSchema) -> anthropic_types.ToolParam:
169
280
  """Convert a single Mirascope tool to Anthropic tool format with caching."""
170
281
  schema_dict = tool.parameters.model_dump(by_alias=True, exclude_none=True)
171
282
  schema_dict["type"] = "object"
@@ -184,54 +295,29 @@ def encode_request(
184
295
  format: type[FormattableT] | Format[FormattableT] | None,
185
296
  params: Params,
186
297
  ) -> tuple[Sequence[Message], Format[FormattableT] | None, MessageCreateKwargs]:
187
- """Prepares a request for the `Anthropic.messages.create` method."""
188
- if not model_id.startswith("anthropic/"): # pragma: no cover
189
- raise ValueError(
190
- f"Model ID must start with 'anthropic/' prefix, got: {model_id}"
191
- )
298
+ """Prepares a request for the Anthropic messages.create method."""
299
+
300
+ processed = process_params(params, DEFAULT_MAX_TOKENS)
301
+ encode_thoughts = processed.pop("encode_thoughts", False)
302
+ max_tokens = processed.pop("max_tokens", DEFAULT_MAX_TOKENS)
192
303
 
193
304
  kwargs: MessageCreateKwargs = MessageCreateKwargs(
194
- {
195
- "model": model_name(model_id),
196
- "max_tokens": DEFAULT_MAX_TOKENS,
197
- }
305
+ {"model": model_name(model_id), "max_tokens": max_tokens, **processed}
198
306
  )
199
- encode_thoughts = False
200
-
201
- with _base_utils.ensure_all_params_accessed(
202
- params=params, provider_id="anthropic", unsupported_params=["seed"]
203
- ) as param_accessor:
204
- if param_accessor.temperature is not None:
205
- kwargs["temperature"] = param_accessor.temperature
206
- if param_accessor.max_tokens is not None:
207
- kwargs["max_tokens"] = param_accessor.max_tokens
208
- if param_accessor.top_p is not None:
209
- kwargs["top_p"] = param_accessor.top_p
210
- if param_accessor.top_k is not None:
211
- kwargs["top_k"] = param_accessor.top_k
212
- if param_accessor.stop_sequences is not None:
213
- kwargs["stop_sequences"] = param_accessor.stop_sequences
214
- if param_accessor.thinking is not None:
215
- if param_accessor.thinking:
216
- # Set budget to 50% of max_tokens with minimum of 1024
217
- budget_tokens = max(1024, kwargs["max_tokens"] // 2)
218
- kwargs["thinking"] = {"type": "enabled", "budget_tokens": budget_tokens}
219
- else:
220
- kwargs["thinking"] = {"type": "disabled"}
221
- if param_accessor.encode_thoughts_as_text:
222
- encode_thoughts = True
223
307
 
224
308
  tools = tools.tools if isinstance(tools, BaseToolkit) else tools or []
225
- anthropic_tools = [_convert_tool_to_tool_param(tool) for tool in tools]
226
- format = resolve_format(format, default_mode="tool")
309
+ anthropic_tools = [convert_tool_to_tool_param(tool) for tool in tools]
310
+ format = resolve_format(format, default_mode=DEFAULT_FORMAT_MODE)
227
311
  if format is not None:
228
312
  if format.mode == "strict":
229
313
  raise FormattingModeNotSupportedError(
230
- formatting_mode="strict", provider_id="anthropic"
314
+ formatting_mode="strict",
315
+ provider_id="anthropic",
316
+ model_id=model_id,
231
317
  )
232
- elif format.mode == "tool":
318
+ if format.mode == "tool":
233
319
  format_tool_schema = _formatting_utils.create_tool_schema(format)
234
- anthropic_tools.append(_convert_tool_to_tool_param(format_tool_schema))
320
+ anthropic_tools.append(convert_tool_to_tool_param(format_tool_schema))
235
321
  if tools:
236
322
  kwargs["tool_choice"] = {"type": "any"}
237
323
  else:
@@ -247,18 +333,24 @@ def encode_request(
247
333
  )
248
334
 
249
335
  if anthropic_tools:
336
+ # Add cache control to the last tool for prompt caching
337
+ last_tool = anthropic_tools[-1]
338
+ last_tool["cache_control"] = {"type": "ephemeral"}
250
339
  kwargs["tools"] = anthropic_tools
251
340
 
252
341
  system_message_content, remaining_messages = _base_utils.extract_system_message(
253
342
  messages
254
343
  )
255
344
 
256
- kwargs["messages"] = [
257
- _encode_message(remaining_message, model_id, encode_thoughts)
258
- for remaining_message in remaining_messages
259
- ]
345
+ kwargs["messages"] = _encode_messages(remaining_messages, model_id, encode_thoughts)
260
346
 
261
347
  if system_message_content:
262
- kwargs["system"] = system_message_content
348
+ kwargs["system"] = [
349
+ anthropic_types.TextBlockParam(
350
+ type="text",
351
+ text=system_message_content,
352
+ cache_control={"type": "ephemeral"},
353
+ )
354
+ ]
263
355
 
264
356
  return messages, format, kwargs
@@ -0,0 +1,46 @@
1
+ """Anthropic error handling utilities."""
2
+
3
+ from anthropic import (
4
+ AnthropicError,
5
+ APIConnectionError as AnthropicAPIConnectionError,
6
+ APIResponseValidationError as AnthropicAPIResponseValidationError,
7
+ APITimeoutError as AnthropicAPITimeoutError,
8
+ AuthenticationError as AnthropicAuthenticationError,
9
+ BadRequestError as AnthropicBadRequestError,
10
+ ConflictError as AnthropicConflictError,
11
+ InternalServerError as AnthropicInternalServerError,
12
+ NotFoundError as AnthropicNotFoundError,
13
+ PermissionDeniedError as AnthropicPermissionDeniedError,
14
+ RateLimitError as AnthropicRateLimitError,
15
+ UnprocessableEntityError as AnthropicUnprocessableEntityError,
16
+ )
17
+
18
+ from ....exceptions import (
19
+ APIError,
20
+ AuthenticationError,
21
+ BadRequestError,
22
+ ConnectionError,
23
+ NotFoundError,
24
+ PermissionError,
25
+ RateLimitError,
26
+ ResponseValidationError,
27
+ ServerError,
28
+ TimeoutError,
29
+ )
30
+ from ...base import ProviderErrorMap
31
+
32
+ # Shared error mapping used by both AnthropicProvider and AnthropicBetaProvider
33
+ ANTHROPIC_ERROR_MAP: ProviderErrorMap = {
34
+ AnthropicAuthenticationError: AuthenticationError,
35
+ AnthropicPermissionDeniedError: PermissionError,
36
+ AnthropicBadRequestError: BadRequestError,
37
+ AnthropicUnprocessableEntityError: BadRequestError,
38
+ AnthropicNotFoundError: NotFoundError,
39
+ AnthropicConflictError: BadRequestError,
40
+ AnthropicRateLimitError: RateLimitError,
41
+ AnthropicInternalServerError: ServerError,
42
+ AnthropicAPITimeoutError: TimeoutError,
43
+ AnthropicAPIConnectionError: ConnectionError,
44
+ AnthropicAPIResponseValidationError: ResponseValidationError,
45
+ AnthropicError: APIError, # Catch-all for unknown Anthropic errors
46
+ }