mirascope 2.0.0a6__py3-none-any.whl → 2.0.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.
Files changed (226) hide show
  1. mirascope/api/_generated/__init__.py +186 -5
  2. mirascope/api/_generated/annotations/client.py +38 -6
  3. mirascope/api/_generated/annotations/raw_client.py +366 -47
  4. mirascope/api/_generated/annotations/types/annotations_create_response.py +19 -6
  5. mirascope/api/_generated/annotations/types/annotations_get_response.py +19 -6
  6. mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item.py +22 -7
  7. mirascope/api/_generated/annotations/types/annotations_update_response.py +19 -6
  8. mirascope/api/_generated/api_keys/__init__.py +12 -2
  9. mirascope/api/_generated/api_keys/client.py +107 -6
  10. mirascope/api/_generated/api_keys/raw_client.py +486 -38
  11. mirascope/api/_generated/api_keys/types/__init__.py +7 -1
  12. mirascope/api/_generated/api_keys/types/api_keys_list_all_for_org_response_item.py +40 -0
  13. mirascope/api/_generated/client.py +36 -0
  14. mirascope/api/_generated/docs/raw_client.py +71 -9
  15. mirascope/api/_generated/environment.py +3 -3
  16. mirascope/api/_generated/environments/__init__.py +6 -0
  17. mirascope/api/_generated/environments/client.py +158 -9
  18. mirascope/api/_generated/environments/raw_client.py +620 -52
  19. mirascope/api/_generated/environments/types/__init__.py +10 -0
  20. mirascope/api/_generated/environments/types/environments_get_analytics_response.py +60 -0
  21. mirascope/api/_generated/environments/types/environments_get_analytics_response_top_functions_item.py +24 -0
  22. mirascope/api/_generated/{organizations/types/organizations_credits_response.py → environments/types/environments_get_analytics_response_top_models_item.py} +6 -3
  23. mirascope/api/_generated/errors/__init__.py +6 -0
  24. mirascope/api/_generated/errors/bad_request_error.py +5 -2
  25. mirascope/api/_generated/errors/conflict_error.py +5 -2
  26. mirascope/api/_generated/errors/payment_required_error.py +15 -0
  27. mirascope/api/_generated/errors/service_unavailable_error.py +14 -0
  28. mirascope/api/_generated/errors/too_many_requests_error.py +15 -0
  29. mirascope/api/_generated/functions/__init__.py +10 -0
  30. mirascope/api/_generated/functions/client.py +222 -8
  31. mirascope/api/_generated/functions/raw_client.py +975 -134
  32. mirascope/api/_generated/functions/types/__init__.py +28 -4
  33. mirascope/api/_generated/functions/types/functions_get_by_env_response.py +53 -0
  34. mirascope/api/_generated/functions/types/functions_get_by_env_response_dependencies_value.py +22 -0
  35. mirascope/api/_generated/functions/types/functions_list_by_env_response.py +25 -0
  36. mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item.py +56 -0
  37. mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item_dependencies_value.py +22 -0
  38. mirascope/api/_generated/health/raw_client.py +74 -10
  39. mirascope/api/_generated/organization_invitations/__init__.py +33 -0
  40. mirascope/api/_generated/organization_invitations/client.py +546 -0
  41. mirascope/api/_generated/organization_invitations/raw_client.py +1519 -0
  42. mirascope/api/_generated/organization_invitations/types/__init__.py +53 -0
  43. mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response.py +34 -0
  44. mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response_role.py +7 -0
  45. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_request_role.py +7 -0
  46. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response.py +48 -0
  47. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_role.py +7 -0
  48. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_status.py +7 -0
  49. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response.py +48 -0
  50. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_role.py +7 -0
  51. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_status.py +7 -0
  52. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item.py +48 -0
  53. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_role.py +7 -0
  54. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_status.py +7 -0
  55. mirascope/api/_generated/organization_memberships/__init__.py +19 -0
  56. mirascope/api/_generated/organization_memberships/client.py +302 -0
  57. mirascope/api/_generated/organization_memberships/raw_client.py +736 -0
  58. mirascope/api/_generated/organization_memberships/types/__init__.py +27 -0
  59. mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item.py +33 -0
  60. mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item_role.py +7 -0
  61. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_request_role.py +7 -0
  62. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response.py +31 -0
  63. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response_role.py +7 -0
  64. mirascope/api/_generated/organizations/__init__.py +26 -2
  65. mirascope/api/_generated/organizations/client.py +442 -20
  66. mirascope/api/_generated/organizations/raw_client.py +1763 -164
  67. mirascope/api/_generated/organizations/types/__init__.py +48 -2
  68. mirascope/api/_generated/organizations/types/organizations_create_payment_intent_response.py +24 -0
  69. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_request_target_plan.py +7 -0
  70. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response.py +47 -0
  71. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item.py +33 -0
  72. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item_resource.py +7 -0
  73. mirascope/api/_generated/organizations/types/organizations_router_balance_response.py +24 -0
  74. mirascope/api/_generated/organizations/types/organizations_subscription_response.py +53 -0
  75. mirascope/api/_generated/organizations/types/organizations_subscription_response_current_plan.py +7 -0
  76. mirascope/api/_generated/organizations/types/organizations_subscription_response_payment_method.py +26 -0
  77. mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change.py +34 -0
  78. mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change_target_plan.py +7 -0
  79. mirascope/api/_generated/organizations/types/organizations_update_subscription_request_target_plan.py +7 -0
  80. mirascope/api/_generated/organizations/types/organizations_update_subscription_response.py +35 -0
  81. mirascope/api/_generated/project_memberships/__init__.py +25 -0
  82. mirascope/api/_generated/project_memberships/client.py +437 -0
  83. mirascope/api/_generated/project_memberships/raw_client.py +1039 -0
  84. mirascope/api/_generated/project_memberships/types/__init__.py +29 -0
  85. mirascope/api/_generated/project_memberships/types/project_memberships_create_request_role.py +7 -0
  86. mirascope/api/_generated/project_memberships/types/project_memberships_create_response.py +35 -0
  87. mirascope/api/_generated/project_memberships/types/project_memberships_create_response_role.py +7 -0
  88. mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item.py +33 -0
  89. mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item_role.py +7 -0
  90. mirascope/api/_generated/project_memberships/types/project_memberships_update_request_role.py +7 -0
  91. mirascope/api/_generated/project_memberships/types/project_memberships_update_response.py +35 -0
  92. mirascope/api/_generated/project_memberships/types/project_memberships_update_response_role.py +7 -0
  93. mirascope/api/_generated/projects/raw_client.py +415 -58
  94. mirascope/api/_generated/reference.md +2767 -397
  95. mirascope/api/_generated/tags/__init__.py +19 -0
  96. mirascope/api/_generated/tags/client.py +504 -0
  97. mirascope/api/_generated/tags/raw_client.py +1288 -0
  98. mirascope/api/_generated/tags/types/__init__.py +17 -0
  99. mirascope/api/_generated/tags/types/tags_create_response.py +41 -0
  100. mirascope/api/_generated/tags/types/tags_get_response.py +41 -0
  101. mirascope/api/_generated/tags/types/tags_list_response.py +23 -0
  102. mirascope/api/_generated/tags/types/tags_list_response_tags_item.py +41 -0
  103. mirascope/api/_generated/tags/types/tags_update_response.py +41 -0
  104. mirascope/api/_generated/token_cost/__init__.py +7 -0
  105. mirascope/api/_generated/token_cost/client.py +160 -0
  106. mirascope/api/_generated/token_cost/raw_client.py +264 -0
  107. mirascope/api/_generated/token_cost/types/__init__.py +8 -0
  108. mirascope/api/_generated/token_cost/types/token_cost_calculate_request_usage.py +54 -0
  109. mirascope/api/_generated/token_cost/types/token_cost_calculate_response.py +52 -0
  110. mirascope/api/_generated/traces/__init__.py +20 -0
  111. mirascope/api/_generated/traces/client.py +543 -0
  112. mirascope/api/_generated/traces/raw_client.py +1366 -96
  113. mirascope/api/_generated/traces/types/__init__.py +28 -0
  114. mirascope/api/_generated/traces/types/traces_get_analytics_summary_response.py +6 -0
  115. mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response.py +33 -0
  116. mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response_spans_item.py +88 -0
  117. mirascope/api/_generated/traces/types/traces_get_trace_detail_response_spans_item.py +0 -2
  118. mirascope/api/_generated/traces/types/traces_list_by_function_hash_response.py +25 -0
  119. mirascope/api/_generated/traces/types/traces_list_by_function_hash_response_traces_item.py +44 -0
  120. mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item.py +26 -0
  121. mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item_operator.py +7 -0
  122. mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_by.py +7 -0
  123. mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_order.py +7 -0
  124. mirascope/api/_generated/traces/types/traces_search_by_env_response.py +26 -0
  125. mirascope/api/_generated/traces/types/traces_search_by_env_response_spans_item.py +50 -0
  126. mirascope/api/_generated/traces/types/traces_search_response_spans_item.py +10 -1
  127. mirascope/api/_generated/types/__init__.py +32 -2
  128. mirascope/api/_generated/types/bad_request_error_body.py +50 -0
  129. mirascope/api/_generated/types/date.py +3 -0
  130. mirascope/api/_generated/types/immutable_resource_error.py +22 -0
  131. mirascope/api/_generated/types/internal_server_error_body.py +3 -3
  132. mirascope/api/_generated/types/plan_limit_exceeded_error.py +32 -0
  133. mirascope/api/_generated/types/plan_limit_exceeded_error_tag.py +7 -0
  134. mirascope/api/_generated/types/pricing_unavailable_error.py +23 -0
  135. mirascope/api/_generated/types/rate_limit_error.py +31 -0
  136. mirascope/api/_generated/types/rate_limit_error_tag.py +5 -0
  137. mirascope/api/_generated/types/service_unavailable_error_body.py +24 -0
  138. mirascope/api/_generated/types/service_unavailable_error_tag.py +7 -0
  139. mirascope/api/_generated/types/subscription_past_due_error.py +31 -0
  140. mirascope/api/_generated/types/subscription_past_due_error_tag.py +7 -0
  141. mirascope/api/settings.py +19 -1
  142. mirascope/llm/__init__.py +53 -10
  143. mirascope/llm/calls/__init__.py +2 -1
  144. mirascope/llm/calls/calls.py +3 -1
  145. mirascope/llm/calls/decorator.py +21 -7
  146. mirascope/llm/content/tool_output.py +22 -5
  147. mirascope/llm/exceptions.py +284 -71
  148. mirascope/llm/formatting/__init__.py +17 -0
  149. mirascope/llm/formatting/format.py +112 -35
  150. mirascope/llm/formatting/output_parser.py +178 -0
  151. mirascope/llm/formatting/partial.py +80 -7
  152. mirascope/llm/formatting/primitives.py +192 -0
  153. mirascope/llm/formatting/types.py +20 -8
  154. mirascope/llm/messages/__init__.py +3 -0
  155. mirascope/llm/messages/_utils.py +34 -0
  156. mirascope/llm/models/__init__.py +5 -0
  157. mirascope/llm/models/models.py +137 -69
  158. mirascope/llm/{providers/base → models}/params.py +7 -57
  159. mirascope/llm/models/thinking_config.py +61 -0
  160. mirascope/llm/prompts/_utils.py +0 -32
  161. mirascope/llm/prompts/decorator.py +16 -5
  162. mirascope/llm/prompts/prompts.py +131 -68
  163. mirascope/llm/providers/__init__.py +1 -4
  164. mirascope/llm/providers/anthropic/_utils/__init__.py +2 -0
  165. mirascope/llm/providers/anthropic/_utils/beta_decode.py +18 -9
  166. mirascope/llm/providers/anthropic/_utils/beta_encode.py +62 -13
  167. mirascope/llm/providers/anthropic/_utils/decode.py +18 -9
  168. mirascope/llm/providers/anthropic/_utils/encode.py +26 -7
  169. mirascope/llm/providers/anthropic/_utils/errors.py +2 -2
  170. mirascope/llm/providers/anthropic/beta_provider.py +64 -18
  171. mirascope/llm/providers/anthropic/provider.py +91 -33
  172. mirascope/llm/providers/base/__init__.py +0 -4
  173. mirascope/llm/providers/base/_utils.py +55 -6
  174. mirascope/llm/providers/base/base_provider.py +116 -37
  175. mirascope/llm/providers/google/_utils/__init__.py +2 -0
  176. mirascope/llm/providers/google/_utils/decode.py +20 -7
  177. mirascope/llm/providers/google/_utils/encode.py +26 -7
  178. mirascope/llm/providers/google/_utils/errors.py +3 -2
  179. mirascope/llm/providers/google/provider.py +64 -18
  180. mirascope/llm/providers/mirascope/_utils.py +13 -17
  181. mirascope/llm/providers/mirascope/provider.py +49 -18
  182. mirascope/llm/providers/mlx/_utils.py +7 -2
  183. mirascope/llm/providers/mlx/encoding/base.py +5 -2
  184. mirascope/llm/providers/mlx/encoding/transformers.py +5 -2
  185. mirascope/llm/providers/mlx/mlx.py +23 -6
  186. mirascope/llm/providers/mlx/provider.py +42 -13
  187. mirascope/llm/providers/openai/_utils/errors.py +2 -2
  188. mirascope/llm/providers/openai/completions/_utils/encode.py +20 -16
  189. mirascope/llm/providers/openai/completions/base_provider.py +40 -11
  190. mirascope/llm/providers/openai/provider.py +40 -10
  191. mirascope/llm/providers/openai/responses/_utils/__init__.py +2 -0
  192. mirascope/llm/providers/openai/responses/_utils/decode.py +19 -6
  193. mirascope/llm/providers/openai/responses/_utils/encode.py +22 -10
  194. mirascope/llm/providers/openai/responses/provider.py +56 -18
  195. mirascope/llm/providers/provider_registry.py +93 -19
  196. mirascope/llm/responses/__init__.py +6 -1
  197. mirascope/llm/responses/_utils.py +102 -12
  198. mirascope/llm/responses/base_response.py +5 -2
  199. mirascope/llm/responses/base_stream_response.py +115 -25
  200. mirascope/llm/responses/response.py +2 -1
  201. mirascope/llm/responses/root_response.py +89 -17
  202. mirascope/llm/responses/stream_response.py +6 -9
  203. mirascope/llm/tools/decorator.py +9 -4
  204. mirascope/llm/tools/tool_schema.py +12 -6
  205. mirascope/llm/tools/toolkit.py +35 -27
  206. mirascope/llm/tools/tools.py +45 -20
  207. mirascope/ops/__init__.py +4 -0
  208. mirascope/ops/_internal/configuration.py +82 -31
  209. mirascope/ops/_internal/exporters/exporters.py +64 -11
  210. mirascope/ops/_internal/instrumentation/llm/common.py +530 -0
  211. mirascope/ops/_internal/instrumentation/llm/cost.py +190 -0
  212. mirascope/ops/_internal/instrumentation/llm/encode.py +1 -1
  213. mirascope/ops/_internal/instrumentation/llm/llm.py +116 -1242
  214. mirascope/ops/_internal/instrumentation/llm/model.py +1798 -0
  215. mirascope/ops/_internal/instrumentation/llm/response.py +521 -0
  216. mirascope/ops/_internal/instrumentation/llm/serialize.py +300 -0
  217. mirascope/ops/_internal/protocols.py +83 -1
  218. mirascope/ops/_internal/traced_calls.py +4 -0
  219. mirascope/ops/_internal/traced_functions.py +118 -8
  220. mirascope/ops/_internal/tracing.py +78 -1
  221. mirascope/ops/_internal/utils.py +52 -4
  222. {mirascope-2.0.0a6.dist-info → mirascope-2.0.1.dist-info}/METADATA +12 -11
  223. mirascope-2.0.1.dist-info/RECORD +423 -0
  224. {mirascope-2.0.0a6.dist-info → mirascope-2.0.1.dist-info}/licenses/LICENSE +1 -1
  225. mirascope-2.0.0a6.dist-info/RECORD +0 -316
  226. {mirascope-2.0.0a6.dist-info → mirascope-2.0.1.dist-info}/WHEEL +0 -0
@@ -9,8 +9,8 @@ from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeAlias, cast, overl
9
9
  from typing_extensions import TypeVar, Unpack
10
10
 
11
11
  from ...context import Context, DepsT
12
- from ...exceptions import APIError, MirascopeLLMError
13
- from ...formatting import Format, FormattableT
12
+ from ...exceptions import APIError, ProviderError
13
+ from ...formatting import Format, FormattableT, OutputParser
14
14
  from ...messages import Message, UserContent, user
15
15
  from ...responses import (
16
16
  AsyncChunkIterator,
@@ -34,10 +34,9 @@ from ...tools import (
34
34
  Tool,
35
35
  Toolkit,
36
36
  )
37
- from .params import Params
38
37
 
39
38
  if TYPE_CHECKING:
40
- from ...exceptions import MirascopeLLMError
39
+ from ...models import Params
41
40
  from ..provider_id import ProviderId
42
41
 
43
42
  ProviderClientT = TypeVar("ProviderClientT")
@@ -47,7 +46,7 @@ Provider: TypeAlias = "BaseProvider[Any]"
47
46
 
48
47
  ProviderErrorMap: TypeAlias = Mapping[
49
48
  type[Exception],
50
- "type[MirascopeLLMError] | Callable[[Exception], type[MirascopeLLMError]]",
49
+ "type[ProviderError] | Callable[[Exception], type[ProviderError]]",
51
50
  ]
52
51
  """Mapping from provider SDK exceptions to Mirascope error types.
53
52
 
@@ -85,7 +84,7 @@ class BaseProvider(Generic[ProviderClientT], ABC):
85
84
  (e.g., lambda e: NotFoundError if e.code == "model_not_found" else BadRequestError)
86
85
 
87
86
  The mapping is walked via the exception's MRO, allowing both specific error handling
88
- and fallback to base SDK error types (e.g., AnthropicError -> APIError).
87
+ and fallback to base SDK error types (e.g., AnthropicError -> ProviderError).
89
88
  """
90
89
 
91
90
  client: ProviderClientT
@@ -96,7 +95,7 @@ class BaseProvider(Generic[ProviderClientT], ABC):
96
95
 
97
96
  Walks the exception's MRO to find the first matching error type in the
98
97
  provider's error_map, allowing both specific error handling and fallback
99
- to base SDK error types (e.g., AnthropicError -> APIError).
98
+ to base SDK error types (e.g., AnthropicError -> ProviderError).
100
99
  """
101
100
  try:
102
101
  yield
@@ -107,16 +106,24 @@ class BaseProvider(Generic[ProviderClientT], ABC):
107
106
  error_type_or_fn = self.error_map[error_class]
108
107
 
109
108
  if isinstance(error_type_or_fn, type):
110
- error_type = cast(type[MirascopeLLMError], error_type_or_fn)
109
+ error_type = cast(type[ProviderError], error_type_or_fn)
111
110
  else:
112
111
  error_type = error_type_or_fn(e)
113
112
 
114
113
  # Construct Mirascope error with metadata
115
- error: MirascopeLLMError = error_type(str(e))
116
- if isinstance(error, APIError):
117
- error.status_code = self.get_error_status(e)
118
- error.provider = self.id
119
- error.original_exception = e
114
+ if issubclass(error_type, APIError):
115
+ error: ProviderError = error_type(
116
+ str(e),
117
+ provider=self.id,
118
+ status_code=self.get_error_status(e),
119
+ original_exception=e,
120
+ )
121
+ else:
122
+ error = error_type(
123
+ str(e),
124
+ provider=self.id,
125
+ original_exception=e,
126
+ )
120
127
  raise error from e
121
128
 
122
129
  # Not in error_map - not a provider error, re-raise as-is
@@ -170,7 +177,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
170
177
  model_id: str,
171
178
  messages: Sequence[Message],
172
179
  tools: Sequence[Tool] | Toolkit | None = None,
173
- format: type[FormattableT] | Format[FormattableT] | None,
180
+ format: type[FormattableT]
181
+ | Format[FormattableT]
182
+ | OutputParser[FormattableT]
183
+ | None,
174
184
  **params: Unpack[Params],
175
185
  ) -> Response | Response[FormattableT]:
176
186
  """Generate an `llm.Response` with an optional response format."""
@@ -182,7 +192,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
182
192
  model_id: str,
183
193
  messages: Sequence[Message],
184
194
  tools: Sequence[Tool] | Toolkit | None = None,
185
- format: type[FormattableT] | Format[FormattableT] | None = None,
195
+ format: type[FormattableT]
196
+ | Format[FormattableT]
197
+ | OutputParser[FormattableT]
198
+ | None = None,
186
199
  **params: Unpack[Params],
187
200
  ) -> Response | Response[FormattableT]:
188
201
  """Generate an `llm.Response` by synchronously calling this client's LLM provider.
@@ -213,7 +226,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
213
226
  model_id: str,
214
227
  messages: Sequence[Message],
215
228
  tools: Sequence[Tool] | Toolkit | None = None,
216
- format: type[FormattableT] | Format[FormattableT] | None = None,
229
+ format: type[FormattableT]
230
+ | Format[FormattableT]
231
+ | OutputParser[FormattableT]
232
+ | None = None,
217
233
  **params: Unpack[Params],
218
234
  ) -> Response | Response[FormattableT]:
219
235
  """Implementation for call(). Subclasses override this method."""
@@ -261,7 +277,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
261
277
  tools: Sequence[Tool | ContextTool[DepsT]]
262
278
  | ContextToolkit[DepsT]
263
279
  | None = None,
264
- format: type[FormattableT] | Format[FormattableT] | None,
280
+ format: type[FormattableT]
281
+ | Format[FormattableT]
282
+ | OutputParser[FormattableT]
283
+ | None,
265
284
  **params: Unpack[Params],
266
285
  ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
267
286
  """Generate an `llm.ContextResponse` with an optional response format."""
@@ -276,7 +295,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
276
295
  tools: Sequence[Tool | ContextTool[DepsT]]
277
296
  | ContextToolkit[DepsT]
278
297
  | None = None,
279
- format: type[FormattableT] | Format[FormattableT] | None = None,
298
+ format: type[FormattableT]
299
+ | Format[FormattableT]
300
+ | OutputParser[FormattableT]
301
+ | None = None,
280
302
  **params: Unpack[Params],
281
303
  ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
282
304
  """Generate an `llm.ContextResponse` by synchronously calling this client's LLM provider.
@@ -312,7 +334,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
312
334
  tools: Sequence[Tool | ContextTool[DepsT]]
313
335
  | ContextToolkit[DepsT]
314
336
  | None = None,
315
- format: type[FormattableT] | Format[FormattableT] | None = None,
337
+ format: type[FormattableT]
338
+ | Format[FormattableT]
339
+ | OutputParser[FormattableT]
340
+ | None = None,
316
341
  **params: Unpack[Params],
317
342
  ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
318
343
  """Implementation for context_call(). Subclasses override this method."""
@@ -351,7 +376,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
351
376
  model_id: str,
352
377
  messages: Sequence[Message],
353
378
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
354
- format: type[FormattableT] | Format[FormattableT] | None,
379
+ format: type[FormattableT]
380
+ | Format[FormattableT]
381
+ | OutputParser[FormattableT]
382
+ | None,
355
383
  **params: Unpack[Params],
356
384
  ) -> AsyncResponse | AsyncResponse[FormattableT]:
357
385
  """Generate an `llm.AsyncResponse` with an optional response format."""
@@ -363,7 +391,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
363
391
  model_id: str,
364
392
  messages: Sequence[Message],
365
393
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
366
- format: type[FormattableT] | Format[FormattableT] | None = None,
394
+ format: type[FormattableT]
395
+ | Format[FormattableT]
396
+ | OutputParser[FormattableT]
397
+ | None = None,
367
398
  **params: Unpack[Params],
368
399
  ) -> AsyncResponse | AsyncResponse[FormattableT]:
369
400
  """Generate an `llm.AsyncResponse` by asynchronously calling this client's LLM provider.
@@ -394,7 +425,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
394
425
  model_id: str,
395
426
  messages: Sequence[Message],
396
427
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
397
- format: type[FormattableT] | Format[FormattableT] | None = None,
428
+ format: type[FormattableT]
429
+ | Format[FormattableT]
430
+ | OutputParser[FormattableT]
431
+ | None = None,
398
432
  **params: Unpack[Params],
399
433
  ) -> AsyncResponse | AsyncResponse[FormattableT]:
400
434
  """Implementation for call_async(). Subclasses override this method."""
@@ -442,7 +476,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
442
476
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
443
477
  | AsyncContextToolkit[DepsT]
444
478
  | None = None,
445
- format: type[FormattableT] | Format[FormattableT] | None,
479
+ format: type[FormattableT]
480
+ | Format[FormattableT]
481
+ | OutputParser[FormattableT]
482
+ | None,
446
483
  **params: Unpack[Params],
447
484
  ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
448
485
  """Generate an `llm.AsyncContextResponse` with an optional response format."""
@@ -457,7 +494,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
457
494
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
458
495
  | AsyncContextToolkit[DepsT]
459
496
  | None = None,
460
- format: type[FormattableT] | Format[FormattableT] | None = None,
497
+ format: type[FormattableT]
498
+ | Format[FormattableT]
499
+ | OutputParser[FormattableT]
500
+ | None = None,
461
501
  **params: Unpack[Params],
462
502
  ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
463
503
  """Generate an `llm.AsyncContextResponse` by asynchronously calling this client's LLM provider.
@@ -493,7 +533,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
493
533
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
494
534
  | AsyncContextToolkit[DepsT]
495
535
  | None = None,
496
- format: type[FormattableT] | Format[FormattableT] | None = None,
536
+ format: type[FormattableT]
537
+ | Format[FormattableT]
538
+ | OutputParser[FormattableT]
539
+ | None = None,
497
540
  **params: Unpack[Params],
498
541
  ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
499
542
  """Implementation for context_call_async(). Subclasses override this method."""
@@ -532,7 +575,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
532
575
  model_id: str,
533
576
  messages: Sequence[Message],
534
577
  tools: Sequence[Tool] | Toolkit | None = None,
535
- format: type[FormattableT] | Format[FormattableT] | None,
578
+ format: type[FormattableT]
579
+ | Format[FormattableT]
580
+ | OutputParser[FormattableT]
581
+ | None,
536
582
  **params: Unpack[Params],
537
583
  ) -> StreamResponse | StreamResponse[FormattableT]:
538
584
  """Stream an `llm.StreamResponse` with an optional response format."""
@@ -544,7 +590,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
544
590
  model_id: str,
545
591
  messages: Sequence[Message],
546
592
  tools: Sequence[Tool] | Toolkit | None = None,
547
- format: type[FormattableT] | Format[FormattableT] | None = None,
593
+ format: type[FormattableT]
594
+ | Format[FormattableT]
595
+ | OutputParser[FormattableT]
596
+ | None = None,
548
597
  **params: Unpack[Params],
549
598
  ) -> StreamResponse | StreamResponse[FormattableT]:
550
599
  """Generate an `llm.StreamResponse` by synchronously streaming from this client's LLM provider.
@@ -579,7 +628,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
579
628
  model_id: str,
580
629
  messages: Sequence[Message],
581
630
  tools: Sequence[Tool] | Toolkit | None = None,
582
- format: type[FormattableT] | Format[FormattableT] | None = None,
631
+ format: type[FormattableT]
632
+ | Format[FormattableT]
633
+ | OutputParser[FormattableT]
634
+ | None = None,
583
635
  **params: Unpack[Params],
584
636
  ) -> StreamResponse | StreamResponse[FormattableT]:
585
637
  """Implementation for stream(). Subclasses override this method."""
@@ -627,7 +679,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
627
679
  tools: Sequence[Tool | ContextTool[DepsT]]
628
680
  | ContextToolkit[DepsT]
629
681
  | None = None,
630
- format: type[FormattableT] | Format[FormattableT] | None,
682
+ format: type[FormattableT]
683
+ | Format[FormattableT]
684
+ | OutputParser[FormattableT]
685
+ | None,
631
686
  **params: Unpack[Params],
632
687
  ) -> (
633
688
  ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]
@@ -644,7 +699,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
644
699
  tools: Sequence[Tool | ContextTool[DepsT]]
645
700
  | ContextToolkit[DepsT]
646
701
  | None = None,
647
- format: type[FormattableT] | Format[FormattableT] | None = None,
702
+ format: type[FormattableT]
703
+ | Format[FormattableT]
704
+ | OutputParser[FormattableT]
705
+ | None = None,
648
706
  **params: Unpack[Params],
649
707
  ) -> (
650
708
  ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]
@@ -686,7 +744,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
686
744
  tools: Sequence[Tool | ContextTool[DepsT]]
687
745
  | ContextToolkit[DepsT]
688
746
  | None = None,
689
- format: type[FormattableT] | Format[FormattableT] | None = None,
747
+ format: type[FormattableT]
748
+ | Format[FormattableT]
749
+ | OutputParser[FormattableT]
750
+ | None = None,
690
751
  **params: Unpack[Params],
691
752
  ) -> (
692
753
  ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]
@@ -727,7 +788,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
727
788
  model_id: str,
728
789
  messages: Sequence[Message],
729
790
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
730
- format: type[FormattableT] | Format[FormattableT] | None,
791
+ format: type[FormattableT]
792
+ | Format[FormattableT]
793
+ | OutputParser[FormattableT]
794
+ | None,
731
795
  **params: Unpack[Params],
732
796
  ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
733
797
  """Stream an `llm.AsyncStreamResponse` with an optional response format."""
@@ -739,7 +803,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
739
803
  model_id: str,
740
804
  messages: Sequence[Message],
741
805
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
742
- format: type[FormattableT] | Format[FormattableT] | None = None,
806
+ format: type[FormattableT]
807
+ | Format[FormattableT]
808
+ | OutputParser[FormattableT]
809
+ | None = None,
743
810
  **params: Unpack[Params],
744
811
  ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
745
812
  """Generate an `llm.AsyncStreamResponse` by asynchronously streaming from this client's LLM provider.
@@ -774,7 +841,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
774
841
  model_id: str,
775
842
  messages: Sequence[Message],
776
843
  tools: Sequence[AsyncTool] | AsyncToolkit | None = None,
777
- format: type[FormattableT] | Format[FormattableT] | None = None,
844
+ format: type[FormattableT]
845
+ | Format[FormattableT]
846
+ | OutputParser[FormattableT]
847
+ | None = None,
778
848
  **params: Unpack[Params],
779
849
  ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
780
850
  """Implementation for stream_async(). Subclasses override this method."""
@@ -822,7 +892,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
822
892
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
823
893
  | AsyncContextToolkit[DepsT]
824
894
  | None = None,
825
- format: type[FormattableT] | Format[FormattableT] | None,
895
+ format: type[FormattableT]
896
+ | Format[FormattableT]
897
+ | OutputParser[FormattableT]
898
+ | None,
826
899
  **params: Unpack[Params],
827
900
  ) -> (
828
901
  AsyncContextStreamResponse[DepsT, None]
@@ -840,7 +913,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
840
913
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
841
914
  | AsyncContextToolkit[DepsT]
842
915
  | None = None,
843
- format: type[FormattableT] | Format[FormattableT] | None = None,
916
+ format: type[FormattableT]
917
+ | Format[FormattableT]
918
+ | OutputParser[FormattableT]
919
+ | None = None,
844
920
  **params: Unpack[Params],
845
921
  ) -> (
846
922
  AsyncContextStreamResponse[DepsT, None]
@@ -883,7 +959,10 @@ class BaseProvider(Generic[ProviderClientT], ABC):
883
959
  tools: Sequence[AsyncTool | AsyncContextTool[DepsT]]
884
960
  | AsyncContextToolkit[DepsT]
885
961
  | None = None,
886
- format: type[FormattableT] | Format[FormattableT] | None = None,
962
+ format: type[FormattableT]
963
+ | Format[FormattableT]
964
+ | OutputParser[FormattableT]
965
+ | None = None,
887
966
  **params: Unpack[Params],
888
967
  ) -> (
889
968
  AsyncContextStreamResponse[DepsT, None]
@@ -1,3 +1,4 @@
1
+ from ...base._utils import get_include_thoughts
1
2
  from .decode import (
2
3
  decode_async_stream,
3
4
  decode_response,
@@ -12,4 +13,5 @@ __all__ = [
12
13
  "decode_response",
13
14
  "decode_stream",
14
15
  "encode_request",
16
+ "get_include_thoughts",
15
17
  ]
@@ -126,6 +126,8 @@ def _decode_candidate_content(
126
126
  def decode_response(
127
127
  response: genai_types.GenerateContentResponse,
128
128
  model_id: GoogleModelId,
129
+ *,
130
+ include_thoughts: bool,
129
131
  ) -> tuple[AssistantMessage, FinishReason | None, Usage | None]:
130
132
  """Returns an `AssistantMessage`, `FinishReason`, and `Usage` extracted from a `GenerateContentResponse`"""
131
133
  content: Sequence[AssistantContentPart] = []
@@ -134,6 +136,8 @@ def decode_response(
134
136
 
135
137
  if response.candidates and (candidate := response.candidates[0]):
136
138
  content = _decode_candidate_content(candidate)
139
+ if not include_thoughts:
140
+ content = [part for part in content if part.type != "thought"]
137
141
  candidate_content = candidate.content
138
142
  if candidate.finish_reason:
139
143
  finish_reason = GOOGLE_FINISH_REASON_MAP.get(candidate.finish_reason)
@@ -155,12 +159,13 @@ def decode_response(
155
159
  class _GoogleChunkProcessor:
156
160
  """Processes Google stream chunks and maintains state across chunks."""
157
161
 
158
- def __init__(self) -> None:
162
+ def __init__(self, *, include_thoughts: bool) -> None:
159
163
  self.current_content_type: Literal["text", "tool_call", "thought"] | None = None
160
164
  self.accumulated_parts: list[genai_types.Part] = []
161
165
  self.reconstructed_content = genai_types.Content(parts=[])
162
166
  # Track previous cumulative usage to compute deltas
163
167
  self.prev_usage = Usage()
168
+ self.include_thoughts = include_thoughts
164
169
 
165
170
  def process_chunk(
166
171
  self, chunk: genai_types.GenerateContentResponse
@@ -175,7 +180,8 @@ class _GoogleChunkProcessor:
175
180
  for part in candidate.content.parts:
176
181
  self.accumulated_parts.append(part)
177
182
  if self.current_content_type == "thought" and not part.thought:
178
- yield ThoughtEndChunk()
183
+ if self.include_thoughts:
184
+ yield ThoughtEndChunk()
179
185
  self.current_content_type = None
180
186
  elif (
181
187
  self.current_content_type == "text" and not part.text
@@ -193,13 +199,15 @@ class _GoogleChunkProcessor:
193
199
 
194
200
  if part.thought:
195
201
  if self.current_content_type is None:
196
- yield ThoughtStartChunk()
202
+ if self.include_thoughts:
203
+ yield ThoughtStartChunk()
197
204
  self.current_content_type = "thought"
198
205
  if not part.text:
199
206
  raise ValueError(
200
207
  "Inside thought part with no text content"
201
208
  ) # pragma: no cover
202
- yield ThoughtChunk(delta=part.text)
209
+ if self.include_thoughts:
210
+ yield ThoughtChunk(delta=part.text)
203
211
 
204
212
  elif part.text:
205
213
  if self.current_content_type is None:
@@ -235,7 +243,8 @@ class _GoogleChunkProcessor:
235
243
  if self.current_content_type == "text":
236
244
  yield TextEndChunk()
237
245
  elif self.current_content_type == "thought":
238
- yield ThoughtEndChunk() # pragma: no cover
246
+ if self.include_thoughts: # pragma: no cover
247
+ yield ThoughtEndChunk()
239
248
  elif self.current_content_type is not None:
240
249
  raise NotImplementedError
241
250
 
@@ -275,9 +284,11 @@ class _GoogleChunkProcessor:
275
284
 
276
285
  def decode_stream(
277
286
  google_stream: Iterator[genai_types.GenerateContentResponse],
287
+ *,
288
+ include_thoughts: bool,
278
289
  ) -> ChunkIterator:
279
290
  """Returns a ChunkIterator converted from a Google stream."""
280
- processor = _GoogleChunkProcessor()
291
+ processor = _GoogleChunkProcessor(include_thoughts=include_thoughts)
281
292
  for chunk in google_stream:
282
293
  yield from processor.process_chunk(chunk)
283
294
  yield processor.raw_message_chunk()
@@ -285,9 +296,11 @@ def decode_stream(
285
296
 
286
297
  async def decode_async_stream(
287
298
  google_stream: AsyncIterator[genai_types.GenerateContentResponse],
299
+ *,
300
+ include_thoughts: bool,
288
301
  ) -> AsyncChunkIterator:
289
302
  """Returns an AsyncChunkIterator converted from a Google async stream."""
290
- processor = _GoogleChunkProcessor()
303
+ processor = _GoogleChunkProcessor(include_thoughts=include_thoughts)
291
304
  async for chunk in google_stream:
292
305
  for item in processor.process_chunk(chunk):
293
306
  yield item
@@ -1,10 +1,12 @@
1
1
  """Google message encoding and request preparation."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import base64
4
6
  import json
5
7
  from collections.abc import Sequence
6
8
  from functools import lru_cache
7
- from typing import Any, TypedDict, cast
9
+ from typing import TYPE_CHECKING, Any, TypedDict, cast
8
10
  from typing_extensions import Required
9
11
 
10
12
  from google.genai import types as genai_types
@@ -14,14 +16,18 @@ from ....exceptions import FeatureNotSupportedError
14
16
  from ....formatting import (
15
17
  Format,
16
18
  FormattableT,
19
+ OutputParser,
17
20
  resolve_format,
18
21
  )
19
22
  from ....messages import AssistantMessage, Message, UserMessage
20
23
  from ....tools import FORMAT_TOOL_NAME, AnyToolSchema, BaseToolkit
21
- from ...base import Params, ThinkingConfig, ThinkingLevel, _utils as _base_utils
24
+ from ...base import _utils as _base_utils
22
25
  from ..model_id import GoogleModelId, model_name
23
26
  from ..model_info import MODELS_WITHOUT_STRUCTURED_OUTPUT_AND_TOOLS_SUPPORT
24
27
 
28
+ if TYPE_CHECKING:
29
+ from ....models import Params, ThinkingConfig, ThinkingLevel
30
+
25
31
  UNKNOWN_TOOL_ID = "google_unknown_tool_id"
26
32
 
27
33
  # Thinking level to a float multiplier % of max tokens (for 2.5 models using budget)
@@ -82,7 +88,7 @@ def google_thinking_config(
82
88
  See: https://ai.google.dev/gemini-api/docs/gemini-3#thinking_level
83
89
  """
84
90
  level: ThinkingLevel = thinking_config.get("level", "default")
85
- include_summaries = thinking_config.get("include_summaries")
91
+ include_thoughts = thinking_config.get("include_thoughts")
86
92
 
87
93
  result = genai_types.ThinkingConfigDict()
88
94
 
@@ -108,8 +114,8 @@ def google_thinking_config(
108
114
  budget = int(multiplier * max_tokens)
109
115
 
110
116
  result["thinking_budget"] = budget
111
- if include_summaries is not None:
112
- result["include_thoughts"] = include_summaries
117
+ if include_thoughts is not None:
118
+ result["include_thoughts"] = include_thoughts
113
119
 
114
120
  return result
115
121
 
@@ -193,7 +199,7 @@ def _encode_content(
193
199
  function_response=genai_types.FunctionResponseDict(
194
200
  id=part.id if part.id != UNKNOWN_TOOL_ID else None,
195
201
  name=part.name,
196
- response={"output": str(part.value)},
202
+ response={"output": str(part.result)},
197
203
  )
198
204
  )
199
205
  )
@@ -265,7 +271,10 @@ def encode_request(
265
271
  model_id: GoogleModelId,
266
272
  messages: Sequence[Message],
267
273
  tools: Sequence[AnyToolSchema] | BaseToolkit[AnyToolSchema] | None,
268
- format: type[FormattableT] | Format[FormattableT] | None,
274
+ format: type[FormattableT]
275
+ | Format[FormattableT]
276
+ | OutputParser[FormattableT]
277
+ | None,
269
278
  params: Params,
270
279
  ) -> tuple[Sequence[Message], Format[FormattableT] | None, GoogleKwargs]:
271
280
  """Prepares a request for the genai `Client.models.generate_content` method."""
@@ -306,6 +315,16 @@ def encode_request(
306
315
  encode_thoughts_as_text = True
307
316
 
308
317
  tools = tools.tools if isinstance(tools, BaseToolkit) else tools or []
318
+
319
+ if _base_utils.has_strict_tools(tools):
320
+ raise FeatureNotSupportedError(
321
+ feature="strict tools",
322
+ provider_id="google",
323
+ model_id=model_id,
324
+ message="Google does not support strict mode for tools. "
325
+ "Set strict=False on your tools or omit the strict parameter.",
326
+ )
327
+
309
328
  google_tools: list[genai_types.ToolDict] = []
310
329
 
311
330
  allows_strict_mode_with_tools = (
@@ -11,20 +11,21 @@ from ....exceptions import (
11
11
  BadRequestError,
12
12
  NotFoundError,
13
13
  PermissionError,
14
+ ProviderError,
14
15
  RateLimitError,
15
16
  ServerError,
16
17
  )
17
18
  from ...base import ProviderErrorMap
18
19
 
19
20
 
20
- def map_google_error(e: Exception) -> type[APIError]:
21
+ def map_google_error(e: Exception) -> type[ProviderError]:
21
22
  """Map Google error to appropriate Mirascope error type.
22
23
 
23
24
  Google only provides ClientError (4xx) and ServerError (5xx) with status codes,
24
25
  so we map based on status code and message patterns.
25
26
  """
26
27
  if not isinstance(e, GoogleClientError | GoogleServerError):
27
- return APIError
28
+ return ProviderError
28
29
 
29
30
  # Authentication errors (401) or 400 with "API key not valid"
30
31
  if e.code == 401 or (e.code == 400 and "API key not valid" in str(e)):