mirascope 1.0.5__py3-none-any.whl → 2.1.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 (632) hide show
  1. mirascope/__init__.py +6 -6
  2. mirascope/_stubs.py +384 -0
  3. mirascope/_utils.py +34 -0
  4. mirascope/api/__init__.py +14 -0
  5. mirascope/api/_generated/README.md +207 -0
  6. mirascope/api/_generated/__init__.py +444 -0
  7. mirascope/api/_generated/annotations/__init__.py +33 -0
  8. mirascope/api/_generated/annotations/client.py +506 -0
  9. mirascope/api/_generated/annotations/raw_client.py +1414 -0
  10. mirascope/api/_generated/annotations/types/__init__.py +31 -0
  11. mirascope/api/_generated/annotations/types/annotations_create_request_label.py +5 -0
  12. mirascope/api/_generated/annotations/types/annotations_create_response.py +48 -0
  13. mirascope/api/_generated/annotations/types/annotations_create_response_label.py +5 -0
  14. mirascope/api/_generated/annotations/types/annotations_get_response.py +48 -0
  15. mirascope/api/_generated/annotations/types/annotations_get_response_label.py +5 -0
  16. mirascope/api/_generated/annotations/types/annotations_list_request_label.py +5 -0
  17. mirascope/api/_generated/annotations/types/annotations_list_response.py +21 -0
  18. mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item.py +50 -0
  19. mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item_label.py +5 -0
  20. mirascope/api/_generated/annotations/types/annotations_update_request_label.py +5 -0
  21. mirascope/api/_generated/annotations/types/annotations_update_response.py +48 -0
  22. mirascope/api/_generated/annotations/types/annotations_update_response_label.py +5 -0
  23. mirascope/api/_generated/api_keys/__init__.py +17 -0
  24. mirascope/api/_generated/api_keys/client.py +530 -0
  25. mirascope/api/_generated/api_keys/raw_client.py +1236 -0
  26. mirascope/api/_generated/api_keys/types/__init__.py +15 -0
  27. mirascope/api/_generated/api_keys/types/api_keys_create_response.py +28 -0
  28. mirascope/api/_generated/api_keys/types/api_keys_get_response.py +27 -0
  29. mirascope/api/_generated/api_keys/types/api_keys_list_all_for_org_response_item.py +40 -0
  30. mirascope/api/_generated/api_keys/types/api_keys_list_response_item.py +27 -0
  31. mirascope/api/_generated/client.py +211 -0
  32. mirascope/api/_generated/core/__init__.py +52 -0
  33. mirascope/api/_generated/core/api_error.py +23 -0
  34. mirascope/api/_generated/core/client_wrapper.py +46 -0
  35. mirascope/api/_generated/core/datetime_utils.py +28 -0
  36. mirascope/api/_generated/core/file.py +67 -0
  37. mirascope/api/_generated/core/force_multipart.py +16 -0
  38. mirascope/api/_generated/core/http_client.py +543 -0
  39. mirascope/api/_generated/core/http_response.py +55 -0
  40. mirascope/api/_generated/core/jsonable_encoder.py +100 -0
  41. mirascope/api/_generated/core/pydantic_utilities.py +255 -0
  42. mirascope/api/_generated/core/query_encoder.py +58 -0
  43. mirascope/api/_generated/core/remove_none_from_dict.py +11 -0
  44. mirascope/api/_generated/core/request_options.py +35 -0
  45. mirascope/api/_generated/core/serialization.py +276 -0
  46. mirascope/api/_generated/docs/__init__.py +4 -0
  47. mirascope/api/_generated/docs/client.py +91 -0
  48. mirascope/api/_generated/docs/raw_client.py +178 -0
  49. mirascope/api/_generated/environment.py +9 -0
  50. mirascope/api/_generated/environments/__init__.py +23 -0
  51. mirascope/api/_generated/environments/client.py +649 -0
  52. mirascope/api/_generated/environments/raw_client.py +1567 -0
  53. mirascope/api/_generated/environments/types/__init__.py +25 -0
  54. mirascope/api/_generated/environments/types/environments_create_response.py +24 -0
  55. mirascope/api/_generated/environments/types/environments_get_analytics_response.py +60 -0
  56. mirascope/api/_generated/environments/types/environments_get_analytics_response_top_functions_item.py +24 -0
  57. mirascope/api/_generated/environments/types/environments_get_analytics_response_top_models_item.py +22 -0
  58. mirascope/api/_generated/environments/types/environments_get_response.py +24 -0
  59. mirascope/api/_generated/environments/types/environments_list_response_item.py +24 -0
  60. mirascope/api/_generated/environments/types/environments_update_response.py +24 -0
  61. mirascope/api/_generated/errors/__init__.py +25 -0
  62. mirascope/api/_generated/errors/bad_request_error.py +14 -0
  63. mirascope/api/_generated/errors/conflict_error.py +14 -0
  64. mirascope/api/_generated/errors/forbidden_error.py +11 -0
  65. mirascope/api/_generated/errors/internal_server_error.py +10 -0
  66. mirascope/api/_generated/errors/not_found_error.py +11 -0
  67. mirascope/api/_generated/errors/payment_required_error.py +15 -0
  68. mirascope/api/_generated/errors/service_unavailable_error.py +14 -0
  69. mirascope/api/_generated/errors/too_many_requests_error.py +15 -0
  70. mirascope/api/_generated/errors/unauthorized_error.py +11 -0
  71. mirascope/api/_generated/functions/__init__.py +39 -0
  72. mirascope/api/_generated/functions/client.py +647 -0
  73. mirascope/api/_generated/functions/raw_client.py +1890 -0
  74. mirascope/api/_generated/functions/types/__init__.py +53 -0
  75. mirascope/api/_generated/functions/types/functions_create_request_dependencies_value.py +20 -0
  76. mirascope/api/_generated/functions/types/functions_create_response.py +37 -0
  77. mirascope/api/_generated/functions/types/functions_create_response_dependencies_value.py +20 -0
  78. mirascope/api/_generated/functions/types/functions_find_by_hash_response.py +39 -0
  79. mirascope/api/_generated/functions/types/functions_find_by_hash_response_dependencies_value.py +20 -0
  80. mirascope/api/_generated/functions/types/functions_get_by_env_response.py +53 -0
  81. mirascope/api/_generated/functions/types/functions_get_by_env_response_dependencies_value.py +22 -0
  82. mirascope/api/_generated/functions/types/functions_get_response.py +37 -0
  83. mirascope/api/_generated/functions/types/functions_get_response_dependencies_value.py +20 -0
  84. mirascope/api/_generated/functions/types/functions_list_by_env_response.py +25 -0
  85. mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item.py +56 -0
  86. mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item_dependencies_value.py +22 -0
  87. mirascope/api/_generated/functions/types/functions_list_response.py +21 -0
  88. mirascope/api/_generated/functions/types/functions_list_response_functions_item.py +41 -0
  89. mirascope/api/_generated/functions/types/functions_list_response_functions_item_dependencies_value.py +20 -0
  90. mirascope/api/_generated/health/__init__.py +7 -0
  91. mirascope/api/_generated/health/client.py +92 -0
  92. mirascope/api/_generated/health/raw_client.py +175 -0
  93. mirascope/api/_generated/health/types/__init__.py +8 -0
  94. mirascope/api/_generated/health/types/health_check_response.py +22 -0
  95. mirascope/api/_generated/health/types/health_check_response_status.py +5 -0
  96. mirascope/api/_generated/organization_invitations/__init__.py +33 -0
  97. mirascope/api/_generated/organization_invitations/client.py +546 -0
  98. mirascope/api/_generated/organization_invitations/raw_client.py +1519 -0
  99. mirascope/api/_generated/organization_invitations/types/__init__.py +53 -0
  100. mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response.py +34 -0
  101. mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response_role.py +7 -0
  102. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_request_role.py +7 -0
  103. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response.py +48 -0
  104. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_role.py +7 -0
  105. mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_status.py +7 -0
  106. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response.py +48 -0
  107. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_role.py +7 -0
  108. mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_status.py +7 -0
  109. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item.py +48 -0
  110. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_role.py +7 -0
  111. mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_status.py +7 -0
  112. mirascope/api/_generated/organization_memberships/__init__.py +19 -0
  113. mirascope/api/_generated/organization_memberships/client.py +302 -0
  114. mirascope/api/_generated/organization_memberships/raw_client.py +736 -0
  115. mirascope/api/_generated/organization_memberships/types/__init__.py +27 -0
  116. mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item.py +33 -0
  117. mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item_role.py +7 -0
  118. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_request_role.py +7 -0
  119. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response.py +31 -0
  120. mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response_role.py +7 -0
  121. mirascope/api/_generated/organizations/__init__.py +51 -0
  122. mirascope/api/_generated/organizations/client.py +869 -0
  123. mirascope/api/_generated/organizations/raw_client.py +2593 -0
  124. mirascope/api/_generated/organizations/types/__init__.py +71 -0
  125. mirascope/api/_generated/organizations/types/organizations_create_payment_intent_response.py +24 -0
  126. mirascope/api/_generated/organizations/types/organizations_create_response.py +26 -0
  127. mirascope/api/_generated/organizations/types/organizations_create_response_role.py +5 -0
  128. mirascope/api/_generated/organizations/types/organizations_get_response.py +26 -0
  129. mirascope/api/_generated/organizations/types/organizations_get_response_role.py +5 -0
  130. mirascope/api/_generated/organizations/types/organizations_list_response_item.py +26 -0
  131. mirascope/api/_generated/organizations/types/organizations_list_response_item_role.py +5 -0
  132. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_request_target_plan.py +7 -0
  133. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response.py +47 -0
  134. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item.py +33 -0
  135. mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item_resource.py +7 -0
  136. mirascope/api/_generated/organizations/types/organizations_router_balance_response.py +24 -0
  137. mirascope/api/_generated/organizations/types/organizations_subscription_response.py +53 -0
  138. mirascope/api/_generated/organizations/types/organizations_subscription_response_current_plan.py +7 -0
  139. mirascope/api/_generated/organizations/types/organizations_subscription_response_payment_method.py +26 -0
  140. mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change.py +34 -0
  141. mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change_target_plan.py +7 -0
  142. mirascope/api/_generated/organizations/types/organizations_update_response.py +26 -0
  143. mirascope/api/_generated/organizations/types/organizations_update_response_role.py +5 -0
  144. mirascope/api/_generated/organizations/types/organizations_update_subscription_request_target_plan.py +7 -0
  145. mirascope/api/_generated/organizations/types/organizations_update_subscription_response.py +35 -0
  146. mirascope/api/_generated/project_memberships/__init__.py +29 -0
  147. mirascope/api/_generated/project_memberships/client.py +528 -0
  148. mirascope/api/_generated/project_memberships/raw_client.py +1278 -0
  149. mirascope/api/_generated/project_memberships/types/__init__.py +33 -0
  150. mirascope/api/_generated/project_memberships/types/project_memberships_create_request_role.py +7 -0
  151. mirascope/api/_generated/project_memberships/types/project_memberships_create_response.py +35 -0
  152. mirascope/api/_generated/project_memberships/types/project_memberships_create_response_role.py +7 -0
  153. mirascope/api/_generated/project_memberships/types/project_memberships_get_response.py +33 -0
  154. mirascope/api/_generated/project_memberships/types/project_memberships_get_response_role.py +7 -0
  155. mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item.py +33 -0
  156. mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item_role.py +7 -0
  157. mirascope/api/_generated/project_memberships/types/project_memberships_update_request_role.py +7 -0
  158. mirascope/api/_generated/project_memberships/types/project_memberships_update_response.py +35 -0
  159. mirascope/api/_generated/project_memberships/types/project_memberships_update_response_role.py +7 -0
  160. mirascope/api/_generated/projects/__init__.py +7 -0
  161. mirascope/api/_generated/projects/client.py +428 -0
  162. mirascope/api/_generated/projects/raw_client.py +1302 -0
  163. mirascope/api/_generated/projects/types/__init__.py +10 -0
  164. mirascope/api/_generated/projects/types/projects_create_response.py +25 -0
  165. mirascope/api/_generated/projects/types/projects_get_response.py +25 -0
  166. mirascope/api/_generated/projects/types/projects_list_response_item.py +25 -0
  167. mirascope/api/_generated/projects/types/projects_update_response.py +25 -0
  168. mirascope/api/_generated/reference.md +4987 -0
  169. mirascope/api/_generated/tags/__init__.py +19 -0
  170. mirascope/api/_generated/tags/client.py +504 -0
  171. mirascope/api/_generated/tags/raw_client.py +1288 -0
  172. mirascope/api/_generated/tags/types/__init__.py +17 -0
  173. mirascope/api/_generated/tags/types/tags_create_response.py +41 -0
  174. mirascope/api/_generated/tags/types/tags_get_response.py +41 -0
  175. mirascope/api/_generated/tags/types/tags_list_response.py +23 -0
  176. mirascope/api/_generated/tags/types/tags_list_response_tags_item.py +41 -0
  177. mirascope/api/_generated/tags/types/tags_update_response.py +41 -0
  178. mirascope/api/_generated/token_cost/__init__.py +7 -0
  179. mirascope/api/_generated/token_cost/client.py +160 -0
  180. mirascope/api/_generated/token_cost/raw_client.py +264 -0
  181. mirascope/api/_generated/token_cost/types/__init__.py +8 -0
  182. mirascope/api/_generated/token_cost/types/token_cost_calculate_request_usage.py +54 -0
  183. mirascope/api/_generated/token_cost/types/token_cost_calculate_response.py +52 -0
  184. mirascope/api/_generated/traces/__init__.py +97 -0
  185. mirascope/api/_generated/traces/client.py +1103 -0
  186. mirascope/api/_generated/traces/raw_client.py +2322 -0
  187. mirascope/api/_generated/traces/types/__init__.py +155 -0
  188. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item.py +29 -0
  189. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource.py +27 -0
  190. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item.py +23 -0
  191. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value.py +38 -0
  192. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_array_value.py +19 -0
  193. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_kvlist_value.py +22 -0
  194. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_kvlist_value_values_item.py +20 -0
  195. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item.py +29 -0
  196. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope.py +31 -0
  197. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item.py +23 -0
  198. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value.py +38 -0
  199. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_array_value.py +19 -0
  200. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_kvlist_value.py +22 -0
  201. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_kvlist_value_values_item.py +22 -0
  202. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item.py +48 -0
  203. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item.py +23 -0
  204. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value.py +38 -0
  205. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_array_value.py +19 -0
  206. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_kvlist_value.py +24 -0
  207. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_kvlist_value_values_item.py +22 -0
  208. mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_status.py +20 -0
  209. mirascope/api/_generated/traces/types/traces_create_response.py +24 -0
  210. mirascope/api/_generated/traces/types/traces_create_response_partial_success.py +22 -0
  211. mirascope/api/_generated/traces/types/traces_get_analytics_summary_response.py +60 -0
  212. mirascope/api/_generated/traces/types/traces_get_analytics_summary_response_top_functions_item.py +24 -0
  213. mirascope/api/_generated/traces/types/traces_get_analytics_summary_response_top_models_item.py +22 -0
  214. mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response.py +33 -0
  215. mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response_spans_item.py +88 -0
  216. mirascope/api/_generated/traces/types/traces_get_trace_detail_response.py +33 -0
  217. mirascope/api/_generated/traces/types/traces_get_trace_detail_response_spans_item.py +88 -0
  218. mirascope/api/_generated/traces/types/traces_list_by_function_hash_response.py +25 -0
  219. mirascope/api/_generated/traces/types/traces_list_by_function_hash_response_traces_item.py +44 -0
  220. mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item.py +26 -0
  221. mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item_operator.py +7 -0
  222. mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_by.py +7 -0
  223. mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_order.py +7 -0
  224. mirascope/api/_generated/traces/types/traces_search_by_env_response.py +26 -0
  225. mirascope/api/_generated/traces/types/traces_search_by_env_response_spans_item.py +50 -0
  226. mirascope/api/_generated/traces/types/traces_search_request_attribute_filters_item.py +26 -0
  227. mirascope/api/_generated/traces/types/traces_search_request_attribute_filters_item_operator.py +7 -0
  228. mirascope/api/_generated/traces/types/traces_search_request_sort_by.py +7 -0
  229. mirascope/api/_generated/traces/types/traces_search_request_sort_order.py +5 -0
  230. mirascope/api/_generated/traces/types/traces_search_response.py +26 -0
  231. mirascope/api/_generated/traces/types/traces_search_response_spans_item.py +50 -0
  232. mirascope/api/_generated/types/__init__.py +85 -0
  233. mirascope/api/_generated/types/already_exists_error.py +22 -0
  234. mirascope/api/_generated/types/already_exists_error_tag.py +5 -0
  235. mirascope/api/_generated/types/bad_request_error_body.py +50 -0
  236. mirascope/api/_generated/types/click_house_error.py +22 -0
  237. mirascope/api/_generated/types/database_error.py +22 -0
  238. mirascope/api/_generated/types/database_error_tag.py +5 -0
  239. mirascope/api/_generated/types/date.py +3 -0
  240. mirascope/api/_generated/types/http_api_decode_error.py +27 -0
  241. mirascope/api/_generated/types/http_api_decode_error_tag.py +5 -0
  242. mirascope/api/_generated/types/immutable_resource_error.py +22 -0
  243. mirascope/api/_generated/types/internal_server_error_body.py +49 -0
  244. mirascope/api/_generated/types/issue.py +38 -0
  245. mirascope/api/_generated/types/issue_tag.py +10 -0
  246. mirascope/api/_generated/types/not_found_error_body.py +22 -0
  247. mirascope/api/_generated/types/not_found_error_tag.py +5 -0
  248. mirascope/api/_generated/types/number_from_string.py +3 -0
  249. mirascope/api/_generated/types/permission_denied_error.py +22 -0
  250. mirascope/api/_generated/types/permission_denied_error_tag.py +5 -0
  251. mirascope/api/_generated/types/plan_limit_exceeded_error.py +32 -0
  252. mirascope/api/_generated/types/plan_limit_exceeded_error_tag.py +7 -0
  253. mirascope/api/_generated/types/pricing_unavailable_error.py +23 -0
  254. mirascope/api/_generated/types/property_key.py +7 -0
  255. mirascope/api/_generated/types/property_key_key.py +25 -0
  256. mirascope/api/_generated/types/property_key_key_tag.py +5 -0
  257. mirascope/api/_generated/types/rate_limit_error.py +31 -0
  258. mirascope/api/_generated/types/rate_limit_error_tag.py +5 -0
  259. mirascope/api/_generated/types/service_unavailable_error_body.py +24 -0
  260. mirascope/api/_generated/types/service_unavailable_error_tag.py +7 -0
  261. mirascope/api/_generated/types/stripe_error.py +20 -0
  262. mirascope/api/_generated/types/subscription_past_due_error.py +31 -0
  263. mirascope/api/_generated/types/subscription_past_due_error_tag.py +7 -0
  264. mirascope/api/_generated/types/unauthorized_error_body.py +21 -0
  265. mirascope/api/_generated/types/unauthorized_error_tag.py +5 -0
  266. mirascope/api/client.py +255 -0
  267. mirascope/api/settings.py +99 -0
  268. mirascope/llm/__init__.py +316 -0
  269. mirascope/llm/calls/__init__.py +17 -0
  270. mirascope/llm/calls/calls.py +348 -0
  271. mirascope/llm/calls/decorator.py +268 -0
  272. mirascope/llm/content/__init__.py +71 -0
  273. mirascope/llm/content/audio.py +173 -0
  274. mirascope/llm/content/document.py +94 -0
  275. mirascope/llm/content/image.py +206 -0
  276. mirascope/llm/content/text.py +47 -0
  277. mirascope/llm/content/thought.py +58 -0
  278. mirascope/llm/content/tool_call.py +69 -0
  279. mirascope/llm/content/tool_output.py +43 -0
  280. mirascope/llm/context/__init__.py +6 -0
  281. mirascope/llm/context/_utils.py +41 -0
  282. mirascope/llm/context/context.py +24 -0
  283. mirascope/llm/exceptions.py +360 -0
  284. mirascope/llm/formatting/__init__.py +39 -0
  285. mirascope/llm/formatting/format.py +291 -0
  286. mirascope/llm/formatting/from_call_args.py +30 -0
  287. mirascope/llm/formatting/output_parser.py +178 -0
  288. mirascope/llm/formatting/partial.py +131 -0
  289. mirascope/llm/formatting/primitives.py +192 -0
  290. mirascope/llm/formatting/types.py +83 -0
  291. mirascope/llm/mcp/__init__.py +5 -0
  292. mirascope/llm/mcp/mcp_client.py +130 -0
  293. mirascope/llm/messages/__init__.py +35 -0
  294. mirascope/llm/messages/_utils.py +34 -0
  295. mirascope/llm/messages/message.py +190 -0
  296. mirascope/llm/models/__init__.py +21 -0
  297. mirascope/llm/models/models.py +1339 -0
  298. mirascope/llm/models/params.py +72 -0
  299. mirascope/llm/models/thinking_config.py +61 -0
  300. mirascope/llm/prompts/__init__.py +34 -0
  301. mirascope/llm/prompts/_utils.py +31 -0
  302. mirascope/llm/prompts/decorator.py +215 -0
  303. mirascope/llm/prompts/prompts.py +484 -0
  304. mirascope/llm/prompts/protocols.py +65 -0
  305. mirascope/llm/providers/__init__.py +65 -0
  306. mirascope/llm/providers/anthropic/__init__.py +11 -0
  307. mirascope/llm/providers/anthropic/_utils/__init__.py +27 -0
  308. mirascope/llm/providers/anthropic/_utils/beta_decode.py +297 -0
  309. mirascope/llm/providers/anthropic/_utils/beta_encode.py +272 -0
  310. mirascope/llm/providers/anthropic/_utils/decode.py +326 -0
  311. mirascope/llm/providers/anthropic/_utils/encode.py +431 -0
  312. mirascope/llm/providers/anthropic/_utils/errors.py +46 -0
  313. mirascope/llm/providers/anthropic/beta_provider.py +338 -0
  314. mirascope/llm/providers/anthropic/model_id.py +23 -0
  315. mirascope/llm/providers/anthropic/model_info.py +87 -0
  316. mirascope/llm/providers/anthropic/provider.py +440 -0
  317. mirascope/llm/providers/base/__init__.py +14 -0
  318. mirascope/llm/providers/base/_utils.py +248 -0
  319. mirascope/llm/providers/base/base_provider.py +1463 -0
  320. mirascope/llm/providers/base/kwargs.py +12 -0
  321. mirascope/llm/providers/google/__init__.py +6 -0
  322. mirascope/llm/providers/google/_utils/__init__.py +17 -0
  323. mirascope/llm/providers/google/_utils/decode.py +357 -0
  324. mirascope/llm/providers/google/_utils/encode.py +418 -0
  325. mirascope/llm/providers/google/_utils/errors.py +50 -0
  326. mirascope/llm/providers/google/message.py +7 -0
  327. mirascope/llm/providers/google/model_id.py +22 -0
  328. mirascope/llm/providers/google/model_info.py +63 -0
  329. mirascope/llm/providers/google/provider.py +456 -0
  330. mirascope/llm/providers/mirascope/__init__.py +5 -0
  331. mirascope/llm/providers/mirascope/_utils.py +73 -0
  332. mirascope/llm/providers/mirascope/provider.py +313 -0
  333. mirascope/llm/providers/mlx/__init__.py +9 -0
  334. mirascope/llm/providers/mlx/_utils.py +141 -0
  335. mirascope/llm/providers/mlx/encoding/__init__.py +8 -0
  336. mirascope/llm/providers/mlx/encoding/base.py +69 -0
  337. mirascope/llm/providers/mlx/encoding/transformers.py +146 -0
  338. mirascope/llm/providers/mlx/mlx.py +242 -0
  339. mirascope/llm/providers/mlx/model_id.py +17 -0
  340. mirascope/llm/providers/mlx/provider.py +416 -0
  341. mirascope/llm/providers/model_id.py +16 -0
  342. mirascope/llm/providers/ollama/__init__.py +7 -0
  343. mirascope/llm/providers/ollama/provider.py +71 -0
  344. mirascope/llm/providers/openai/__init__.py +15 -0
  345. mirascope/llm/providers/openai/_utils/__init__.py +5 -0
  346. mirascope/llm/providers/openai/_utils/errors.py +46 -0
  347. mirascope/llm/providers/openai/completions/__init__.py +7 -0
  348. mirascope/llm/providers/openai/completions/_utils/__init__.py +18 -0
  349. mirascope/llm/providers/openai/completions/_utils/decode.py +252 -0
  350. mirascope/llm/providers/openai/completions/_utils/encode.py +390 -0
  351. mirascope/llm/providers/openai/completions/_utils/feature_info.py +50 -0
  352. mirascope/llm/providers/openai/completions/base_provider.py +522 -0
  353. mirascope/llm/providers/openai/completions/provider.py +28 -0
  354. mirascope/llm/providers/openai/model_id.py +31 -0
  355. mirascope/llm/providers/openai/model_info.py +303 -0
  356. mirascope/llm/providers/openai/provider.py +405 -0
  357. mirascope/llm/providers/openai/responses/__init__.py +5 -0
  358. mirascope/llm/providers/openai/responses/_utils/__init__.py +15 -0
  359. mirascope/llm/providers/openai/responses/_utils/decode.py +289 -0
  360. mirascope/llm/providers/openai/responses/_utils/encode.py +399 -0
  361. mirascope/llm/providers/openai/responses/provider.py +472 -0
  362. mirascope/llm/providers/openrouter/__init__.py +5 -0
  363. mirascope/llm/providers/openrouter/provider.py +67 -0
  364. mirascope/llm/providers/provider_id.py +26 -0
  365. mirascope/llm/providers/provider_registry.py +305 -0
  366. mirascope/llm/providers/together/__init__.py +7 -0
  367. mirascope/llm/providers/together/provider.py +40 -0
  368. mirascope/llm/responses/__init__.py +66 -0
  369. mirascope/llm/responses/_utils.py +146 -0
  370. mirascope/llm/responses/base_response.py +103 -0
  371. mirascope/llm/responses/base_stream_response.py +824 -0
  372. mirascope/llm/responses/finish_reason.py +28 -0
  373. mirascope/llm/responses/response.py +362 -0
  374. mirascope/llm/responses/root_response.py +248 -0
  375. mirascope/llm/responses/stream_response.py +577 -0
  376. mirascope/llm/responses/streams.py +363 -0
  377. mirascope/llm/responses/usage.py +139 -0
  378. mirascope/llm/tools/__init__.py +71 -0
  379. mirascope/llm/tools/_utils.py +34 -0
  380. mirascope/llm/tools/decorator.py +184 -0
  381. mirascope/llm/tools/protocols.py +96 -0
  382. mirascope/llm/tools/provider_tools.py +18 -0
  383. mirascope/llm/tools/tool_schema.py +321 -0
  384. mirascope/llm/tools/toolkit.py +178 -0
  385. mirascope/llm/tools/tools.py +263 -0
  386. mirascope/llm/tools/types.py +112 -0
  387. mirascope/llm/tools/web_search_tool.py +32 -0
  388. mirascope/llm/types/__init__.py +22 -0
  389. mirascope/llm/types/dataclass.py +9 -0
  390. mirascope/llm/types/jsonable.py +44 -0
  391. mirascope/llm/types/type_vars.py +19 -0
  392. mirascope/ops/__init__.py +129 -0
  393. mirascope/ops/_internal/__init__.py +5 -0
  394. mirascope/ops/_internal/closure.py +1172 -0
  395. mirascope/ops/_internal/configuration.py +177 -0
  396. mirascope/ops/_internal/context.py +76 -0
  397. mirascope/ops/_internal/exporters/__init__.py +26 -0
  398. mirascope/ops/_internal/exporters/exporters.py +362 -0
  399. mirascope/ops/_internal/exporters/processors.py +104 -0
  400. mirascope/ops/_internal/exporters/types.py +165 -0
  401. mirascope/ops/_internal/exporters/utils.py +66 -0
  402. mirascope/ops/_internal/instrumentation/__init__.py +28 -0
  403. mirascope/ops/_internal/instrumentation/llm/__init__.py +8 -0
  404. mirascope/ops/_internal/instrumentation/llm/common.py +500 -0
  405. mirascope/ops/_internal/instrumentation/llm/cost.py +190 -0
  406. mirascope/ops/_internal/instrumentation/llm/encode.py +238 -0
  407. mirascope/ops/_internal/instrumentation/llm/gen_ai_types/__init__.py +38 -0
  408. mirascope/ops/_internal/instrumentation/llm/gen_ai_types/gen_ai_input_messages.py +31 -0
  409. mirascope/ops/_internal/instrumentation/llm/gen_ai_types/gen_ai_output_messages.py +38 -0
  410. mirascope/ops/_internal/instrumentation/llm/gen_ai_types/gen_ai_system_instructions.py +18 -0
  411. mirascope/ops/_internal/instrumentation/llm/gen_ai_types/shared.py +100 -0
  412. mirascope/ops/_internal/instrumentation/llm/llm.py +161 -0
  413. mirascope/ops/_internal/instrumentation/llm/model.py +1777 -0
  414. mirascope/ops/_internal/instrumentation/llm/response.py +521 -0
  415. mirascope/ops/_internal/instrumentation/llm/serialize.py +324 -0
  416. mirascope/ops/_internal/instrumentation/providers/__init__.py +29 -0
  417. mirascope/ops/_internal/instrumentation/providers/anthropic.py +78 -0
  418. mirascope/ops/_internal/instrumentation/providers/base.py +179 -0
  419. mirascope/ops/_internal/instrumentation/providers/google_genai.py +85 -0
  420. mirascope/ops/_internal/instrumentation/providers/openai.py +82 -0
  421. mirascope/ops/_internal/propagation.py +198 -0
  422. mirascope/ops/_internal/protocols.py +133 -0
  423. mirascope/ops/_internal/session.py +139 -0
  424. mirascope/ops/_internal/spans.py +232 -0
  425. mirascope/ops/_internal/traced_calls.py +389 -0
  426. mirascope/ops/_internal/traced_functions.py +528 -0
  427. mirascope/ops/_internal/tracing.py +353 -0
  428. mirascope/ops/_internal/types.py +13 -0
  429. mirascope/ops/_internal/utils.py +131 -0
  430. mirascope/ops/_internal/versioned_calls.py +512 -0
  431. mirascope/ops/_internal/versioned_functions.py +357 -0
  432. mirascope/ops/_internal/versioning.py +303 -0
  433. mirascope/ops/exceptions.py +21 -0
  434. mirascope-2.1.1.dist-info/METADATA +231 -0
  435. mirascope-2.1.1.dist-info/RECORD +437 -0
  436. {mirascope-1.0.5.dist-info → mirascope-2.1.1.dist-info}/WHEEL +1 -1
  437. {mirascope-1.0.5.dist-info → mirascope-2.1.1.dist-info}/licenses/LICENSE +1 -1
  438. mirascope/beta/__init__.py +0 -0
  439. mirascope/beta/openai/__init__.py +0 -5
  440. mirascope/beta/openai/parse.py +0 -129
  441. mirascope/beta/rag/__init__.py +0 -24
  442. mirascope/beta/rag/base/__init__.py +0 -22
  443. mirascope/beta/rag/base/chunkers/__init__.py +0 -2
  444. mirascope/beta/rag/base/chunkers/base_chunker.py +0 -37
  445. mirascope/beta/rag/base/chunkers/text_chunker.py +0 -33
  446. mirascope/beta/rag/base/config.py +0 -8
  447. mirascope/beta/rag/base/document.py +0 -11
  448. mirascope/beta/rag/base/embedders.py +0 -35
  449. mirascope/beta/rag/base/embedding_params.py +0 -18
  450. mirascope/beta/rag/base/embedding_response.py +0 -30
  451. mirascope/beta/rag/base/query_results.py +0 -7
  452. mirascope/beta/rag/base/vectorstore_params.py +0 -18
  453. mirascope/beta/rag/base/vectorstores.py +0 -37
  454. mirascope/beta/rag/chroma/__init__.py +0 -11
  455. mirascope/beta/rag/chroma/types.py +0 -57
  456. mirascope/beta/rag/chroma/vectorstores.py +0 -97
  457. mirascope/beta/rag/cohere/__init__.py +0 -11
  458. mirascope/beta/rag/cohere/embedders.py +0 -87
  459. mirascope/beta/rag/cohere/embedding_params.py +0 -29
  460. mirascope/beta/rag/cohere/embedding_response.py +0 -29
  461. mirascope/beta/rag/cohere/py.typed +0 -0
  462. mirascope/beta/rag/openai/__init__.py +0 -11
  463. mirascope/beta/rag/openai/embedders.py +0 -144
  464. mirascope/beta/rag/openai/embedding_params.py +0 -18
  465. mirascope/beta/rag/openai/embedding_response.py +0 -14
  466. mirascope/beta/rag/openai/py.typed +0 -0
  467. mirascope/beta/rag/pinecone/__init__.py +0 -19
  468. mirascope/beta/rag/pinecone/types.py +0 -143
  469. mirascope/beta/rag/pinecone/vectorstores.py +0 -148
  470. mirascope/beta/rag/weaviate/__init__.py +0 -6
  471. mirascope/beta/rag/weaviate/types.py +0 -92
  472. mirascope/beta/rag/weaviate/vectorstores.py +0 -103
  473. mirascope/core/__init__.py +0 -55
  474. mirascope/core/anthropic/__init__.py +0 -21
  475. mirascope/core/anthropic/_call.py +0 -71
  476. mirascope/core/anthropic/_utils/__init__.py +0 -16
  477. mirascope/core/anthropic/_utils/_calculate_cost.py +0 -63
  478. mirascope/core/anthropic/_utils/_convert_message_params.py +0 -54
  479. mirascope/core/anthropic/_utils/_get_json_output.py +0 -34
  480. mirascope/core/anthropic/_utils/_handle_stream.py +0 -89
  481. mirascope/core/anthropic/_utils/_setup_call.py +0 -76
  482. mirascope/core/anthropic/call_params.py +0 -36
  483. mirascope/core/anthropic/call_response.py +0 -158
  484. mirascope/core/anthropic/call_response_chunk.py +0 -104
  485. mirascope/core/anthropic/dynamic_config.py +0 -26
  486. mirascope/core/anthropic/py.typed +0 -0
  487. mirascope/core/anthropic/stream.py +0 -140
  488. mirascope/core/anthropic/tool.py +0 -77
  489. mirascope/core/base/__init__.py +0 -40
  490. mirascope/core/base/_call_factory.py +0 -323
  491. mirascope/core/base/_create.py +0 -167
  492. mirascope/core/base/_extract.py +0 -139
  493. mirascope/core/base/_partial.py +0 -63
  494. mirascope/core/base/_utils/__init__.py +0 -64
  495. mirascope/core/base/_utils/_base_type.py +0 -17
  496. mirascope/core/base/_utils/_convert_base_model_to_base_tool.py +0 -45
  497. mirascope/core/base/_utils/_convert_base_type_to_base_tool.py +0 -24
  498. mirascope/core/base/_utils/_convert_function_to_base_tool.py +0 -126
  499. mirascope/core/base/_utils/_default_tool_docstring.py +0 -6
  500. mirascope/core/base/_utils/_extract_tool_return.py +0 -36
  501. mirascope/core/base/_utils/_format_template.py +0 -29
  502. mirascope/core/base/_utils/_get_audio_type.py +0 -18
  503. mirascope/core/base/_utils/_get_fn_args.py +0 -14
  504. mirascope/core/base/_utils/_get_image_type.py +0 -26
  505. mirascope/core/base/_utils/_get_metadata.py +0 -17
  506. mirascope/core/base/_utils/_get_possible_user_message_param.py +0 -21
  507. mirascope/core/base/_utils/_get_prompt_template.py +0 -25
  508. mirascope/core/base/_utils/_get_template_values.py +0 -52
  509. mirascope/core/base/_utils/_get_template_variables.py +0 -38
  510. mirascope/core/base/_utils/_json_mode_content.py +0 -15
  511. mirascope/core/base/_utils/_parse_content_template.py +0 -157
  512. mirascope/core/base/_utils/_parse_prompt_messages.py +0 -51
  513. mirascope/core/base/_utils/_protocols.py +0 -215
  514. mirascope/core/base/_utils/_setup_call.py +0 -64
  515. mirascope/core/base/_utils/_setup_extract_tool.py +0 -24
  516. mirascope/core/base/call_params.py +0 -6
  517. mirascope/core/base/call_response.py +0 -189
  518. mirascope/core/base/call_response_chunk.py +0 -91
  519. mirascope/core/base/dynamic_config.py +0 -55
  520. mirascope/core/base/message_param.py +0 -61
  521. mirascope/core/base/metadata.py +0 -13
  522. mirascope/core/base/prompt.py +0 -415
  523. mirascope/core/base/stream.py +0 -365
  524. mirascope/core/base/structured_stream.py +0 -251
  525. mirascope/core/base/tool.py +0 -126
  526. mirascope/core/base/toolkit.py +0 -146
  527. mirascope/core/cohere/__init__.py +0 -21
  528. mirascope/core/cohere/_call.py +0 -71
  529. mirascope/core/cohere/_utils/__init__.py +0 -16
  530. mirascope/core/cohere/_utils/_calculate_cost.py +0 -39
  531. mirascope/core/cohere/_utils/_convert_message_params.py +0 -31
  532. mirascope/core/cohere/_utils/_get_json_output.py +0 -31
  533. mirascope/core/cohere/_utils/_handle_stream.py +0 -33
  534. mirascope/core/cohere/_utils/_setup_call.py +0 -89
  535. mirascope/core/cohere/call_params.py +0 -57
  536. mirascope/core/cohere/call_response.py +0 -167
  537. mirascope/core/cohere/call_response_chunk.py +0 -101
  538. mirascope/core/cohere/dynamic_config.py +0 -24
  539. mirascope/core/cohere/py.typed +0 -0
  540. mirascope/core/cohere/stream.py +0 -113
  541. mirascope/core/cohere/tool.py +0 -92
  542. mirascope/core/gemini/__init__.py +0 -21
  543. mirascope/core/gemini/_call.py +0 -71
  544. mirascope/core/gemini/_utils/__init__.py +0 -16
  545. mirascope/core/gemini/_utils/_calculate_cost.py +0 -8
  546. mirascope/core/gemini/_utils/_convert_message_params.py +0 -74
  547. mirascope/core/gemini/_utils/_get_json_output.py +0 -33
  548. mirascope/core/gemini/_utils/_handle_stream.py +0 -33
  549. mirascope/core/gemini/_utils/_setup_call.py +0 -68
  550. mirascope/core/gemini/call_params.py +0 -28
  551. mirascope/core/gemini/call_response.py +0 -173
  552. mirascope/core/gemini/call_response_chunk.py +0 -85
  553. mirascope/core/gemini/dynamic_config.py +0 -26
  554. mirascope/core/gemini/stream.py +0 -121
  555. mirascope/core/gemini/tool.py +0 -104
  556. mirascope/core/groq/__init__.py +0 -21
  557. mirascope/core/groq/_call.py +0 -71
  558. mirascope/core/groq/_utils/__init__.py +0 -16
  559. mirascope/core/groq/_utils/_calculate_cost.py +0 -68
  560. mirascope/core/groq/_utils/_convert_message_params.py +0 -23
  561. mirascope/core/groq/_utils/_get_json_output.py +0 -27
  562. mirascope/core/groq/_utils/_handle_stream.py +0 -121
  563. mirascope/core/groq/_utils/_setup_call.py +0 -67
  564. mirascope/core/groq/call_params.py +0 -51
  565. mirascope/core/groq/call_response.py +0 -160
  566. mirascope/core/groq/call_response_chunk.py +0 -89
  567. mirascope/core/groq/dynamic_config.py +0 -26
  568. mirascope/core/groq/py.typed +0 -0
  569. mirascope/core/groq/stream.py +0 -136
  570. mirascope/core/groq/tool.py +0 -79
  571. mirascope/core/litellm/__init__.py +0 -6
  572. mirascope/core/litellm/_call.py +0 -73
  573. mirascope/core/litellm/_utils/__init__.py +0 -5
  574. mirascope/core/litellm/_utils/_setup_call.py +0 -46
  575. mirascope/core/litellm/py.typed +0 -0
  576. mirascope/core/mistral/__init__.py +0 -21
  577. mirascope/core/mistral/_call.py +0 -69
  578. mirascope/core/mistral/_utils/__init__.py +0 -16
  579. mirascope/core/mistral/_utils/_calculate_cost.py +0 -47
  580. mirascope/core/mistral/_utils/_convert_message_params.py +0 -23
  581. mirascope/core/mistral/_utils/_get_json_output.py +0 -28
  582. mirascope/core/mistral/_utils/_handle_stream.py +0 -121
  583. mirascope/core/mistral/_utils/_setup_call.py +0 -86
  584. mirascope/core/mistral/call_params.py +0 -36
  585. mirascope/core/mistral/call_response.py +0 -156
  586. mirascope/core/mistral/call_response_chunk.py +0 -84
  587. mirascope/core/mistral/dynamic_config.py +0 -24
  588. mirascope/core/mistral/py.typed +0 -0
  589. mirascope/core/mistral/stream.py +0 -117
  590. mirascope/core/mistral/tool.py +0 -77
  591. mirascope/core/openai/__init__.py +0 -21
  592. mirascope/core/openai/_call.py +0 -71
  593. mirascope/core/openai/_utils/__init__.py +0 -16
  594. mirascope/core/openai/_utils/_calculate_cost.py +0 -110
  595. mirascope/core/openai/_utils/_convert_message_params.py +0 -53
  596. mirascope/core/openai/_utils/_get_json_output.py +0 -27
  597. mirascope/core/openai/_utils/_handle_stream.py +0 -125
  598. mirascope/core/openai/_utils/_setup_call.py +0 -62
  599. mirascope/core/openai/call_params.py +0 -54
  600. mirascope/core/openai/call_response.py +0 -162
  601. mirascope/core/openai/call_response_chunk.py +0 -90
  602. mirascope/core/openai/dynamic_config.py +0 -26
  603. mirascope/core/openai/py.typed +0 -0
  604. mirascope/core/openai/stream.py +0 -148
  605. mirascope/core/openai/tool.py +0 -79
  606. mirascope/core/py.typed +0 -0
  607. mirascope/integrations/__init__.py +0 -20
  608. mirascope/integrations/_middleware_factory.py +0 -277
  609. mirascope/integrations/langfuse/__init__.py +0 -3
  610. mirascope/integrations/langfuse/_utils.py +0 -114
  611. mirascope/integrations/langfuse/_with_langfuse.py +0 -71
  612. mirascope/integrations/logfire/__init__.py +0 -3
  613. mirascope/integrations/logfire/_utils.py +0 -188
  614. mirascope/integrations/logfire/_with_logfire.py +0 -60
  615. mirascope/integrations/otel/__init__.py +0 -5
  616. mirascope/integrations/otel/_utils.py +0 -268
  617. mirascope/integrations/otel/_with_hyperdx.py +0 -61
  618. mirascope/integrations/otel/_with_otel.py +0 -60
  619. mirascope/integrations/tenacity.py +0 -50
  620. mirascope/py.typed +0 -0
  621. mirascope/v0/__init__.py +0 -43
  622. mirascope/v0/anthropic.py +0 -54
  623. mirascope/v0/base/__init__.py +0 -12
  624. mirascope/v0/base/calls.py +0 -118
  625. mirascope/v0/base/extractors.py +0 -122
  626. mirascope/v0/base/ops_utils.py +0 -207
  627. mirascope/v0/base/prompts.py +0 -48
  628. mirascope/v0/base/types.py +0 -14
  629. mirascope/v0/base/utils.py +0 -21
  630. mirascope/v0/openai.py +0 -54
  631. mirascope-1.0.5.dist-info/METADATA +0 -519
  632. mirascope-1.0.5.dist-info/RECORD +0 -198
@@ -0,0 +1,324 @@
1
+ """Mirascope-specific serialization for span attributes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from collections.abc import Sequence
7
+ from typing import Any, Protocol
8
+
9
+ from opentelemetry.util.types import AttributeValue
10
+
11
+ from .....llm import (
12
+ AnyToolSchema,
13
+ AssistantMessage,
14
+ Audio,
15
+ Base64ImageSource,
16
+ Document,
17
+ Image,
18
+ Jsonable,
19
+ Message,
20
+ ProviderTool,
21
+ RootResponse,
22
+ SystemMessage,
23
+ Text,
24
+ Thought,
25
+ ToolCall,
26
+ ToolOutput,
27
+ Usage,
28
+ UserMessage,
29
+ )
30
+ from .....llm.content.document import Base64DocumentSource, TextDocumentSource
31
+ from ...utils import json_dumps
32
+ from .cost import calculate_cost_async, calculate_cost_sync
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ class SpanProtocol(Protocol):
38
+ """Protocol for span objects that support setting attributes."""
39
+
40
+ def set(self, **attributes: AttributeValue) -> None:
41
+ """Set attributes on the span."""
42
+ ...
43
+
44
+
45
+ def _serialize_content_part(
46
+ part: Text | ToolCall | Thought | Image | Audio | Document | ToolOutput[Jsonable],
47
+ ) -> dict[str, Jsonable]:
48
+ """Serialize a single content part to a dict matching the Mirascope dataclass structure."""
49
+ if isinstance(part, Text):
50
+ return {"type": "text", "text": part.text}
51
+ elif isinstance(part, ToolCall):
52
+ return {
53
+ "type": "tool_call",
54
+ "id": part.id,
55
+ "name": part.name,
56
+ "args": part.args,
57
+ }
58
+ elif isinstance(part, Thought):
59
+ return {"type": "thought", "thought": part.thought}
60
+ elif isinstance(part, ToolOutput):
61
+ return {
62
+ "type": "tool_output",
63
+ "id": part.id,
64
+ "name": part.name,
65
+ "result": part.result,
66
+ }
67
+ elif isinstance(part, Image):
68
+ if isinstance(part.source, Base64ImageSource):
69
+ return {
70
+ "type": "image",
71
+ "source": {
72
+ "type": "base64_image_source",
73
+ "mime_type": part.source.mime_type,
74
+ "data": part.source.data,
75
+ },
76
+ }
77
+ else: # URLImageSource
78
+ return {
79
+ "type": "image",
80
+ "source": {"type": "url_image_source", "url": part.source.url},
81
+ }
82
+ elif isinstance(part, Audio):
83
+ return {
84
+ "type": "audio",
85
+ "source": {
86
+ "type": "base64_audio_source",
87
+ "mime_type": part.source.mime_type,
88
+ "data": part.source.data,
89
+ },
90
+ }
91
+ elif isinstance(part, Document):
92
+ # Document has multiple source types - serialize based on actual type
93
+ if isinstance(part.source, Base64DocumentSource):
94
+ return {
95
+ "type": "document",
96
+ "source": {
97
+ "type": "base64_document_source",
98
+ "data": part.source.data,
99
+ "media_type": part.source.media_type,
100
+ },
101
+ }
102
+ elif isinstance(part.source, TextDocumentSource):
103
+ return {
104
+ "type": "document",
105
+ "source": {
106
+ "type": "text_document_source",
107
+ "data": part.source.data,
108
+ "media_type": part.source.media_type,
109
+ },
110
+ }
111
+ else: # URLDocumentSource
112
+ return {
113
+ "type": "document",
114
+ "source": {
115
+ "type": "url_document_source",
116
+ "url": part.source.url,
117
+ },
118
+ }
119
+ return {"type": "unknown"} # pragma: no cover
120
+
121
+
122
+ def _serialize_message(message: Message) -> dict[str, Jsonable]:
123
+ """Serialize a Message to a dict matching the Mirascope dataclass structure."""
124
+ if isinstance(message, SystemMessage):
125
+ return {
126
+ "role": "system",
127
+ "content": _serialize_content_part(message.content),
128
+ }
129
+ elif isinstance(message, UserMessage):
130
+ return {
131
+ "role": "user",
132
+ "content": [_serialize_content_part(p) for p in message.content],
133
+ "name": message.name,
134
+ }
135
+ elif isinstance(message, AssistantMessage):
136
+ return {
137
+ "role": "assistant",
138
+ "content": [_serialize_content_part(p) for p in message.content],
139
+ "name": message.name,
140
+ }
141
+ return {"role": "unknown"} # pragma: no cover
142
+
143
+
144
+ def serialize_mirascope_messages(messages: Sequence[Message]) -> str:
145
+ """Serialize input messages to JSON for span attributes."""
146
+ return json_dumps([_serialize_message(m) for m in messages])
147
+
148
+
149
+ def serialize_mirascope_content(
150
+ content: Sequence[Text | ToolCall | Thought],
151
+ ) -> str:
152
+ """Serialize response content to JSON for span attributes."""
153
+ return json_dumps([_serialize_content_part(p) for p in content])
154
+
155
+
156
+ def serialize_mirascope_usage(usage: Usage | None) -> AttributeValue | None:
157
+ """Serialize response usage to JSON for span attributes. Returns None if usage is None."""
158
+ if usage is None:
159
+ return None
160
+ return json_dumps(
161
+ {
162
+ "input_tokens": usage.input_tokens,
163
+ "output_tokens": usage.output_tokens,
164
+ "cache_read_tokens": usage.cache_read_tokens,
165
+ "cache_write_tokens": usage.cache_write_tokens,
166
+ "reasoning_tokens": usage.reasoning_tokens,
167
+ "total_tokens": usage.total_tokens,
168
+ }
169
+ )
170
+
171
+
172
+ def _serialize_tool(tool: AnyToolSchema | ProviderTool) -> dict[str, Jsonable]:
173
+ if isinstance(tool, ProviderTool):
174
+ return {"name": tool.name, "type": "extension"}
175
+ result: dict[str, Jsonable] = {
176
+ "name": tool.name,
177
+ "description": tool.description,
178
+ "type": "function",
179
+ "parameters": tool.parameters.model_dump(by_alias=True, mode="json"),
180
+ }
181
+ if tool.strict is not None:
182
+ result["strict"] = tool.strict
183
+ return result
184
+
185
+
186
+ def serialize_tools(tools: Sequence[AnyToolSchema | ProviderTool]) -> str | None:
187
+ """Serialize a sequence of Mirascope tools"""
188
+ if not tools:
189
+ return None
190
+ return json_dumps([_serialize_tool(t) for t in tools])
191
+
192
+
193
+ def serialize_mirascope_cost(
194
+ input_cost: float,
195
+ output_cost: float,
196
+ total_cost: float,
197
+ cache_read_cost: float | None = None,
198
+ cache_write_cost: float | None = None,
199
+ ) -> str:
200
+ """Serialize cost to JSON for span attributes.
201
+
202
+ All costs are in centicents (1 centicent = $0.0001).
203
+ Consumers can divide by 10,000 to get dollar amounts.
204
+ """
205
+ return json_dumps(
206
+ {
207
+ "input_cost": input_cost,
208
+ "output_cost": output_cost,
209
+ "cache_read_cost": cache_read_cost,
210
+ "cache_write_cost": cache_write_cost,
211
+ "total_cost": total_cost,
212
+ }
213
+ )
214
+
215
+
216
+ def attach_mirascope_response(
217
+ span: SpanProtocol, response: RootResponse[Any, Any]
218
+ ) -> None:
219
+ """Attach Mirascope-specific response attributes to a span.
220
+
221
+ Sets the following attributes:
222
+ - mirascope.trace.output: Pretty-printed response
223
+ - mirascope.response.messages: Serialized input messages (excluding final assistant message)
224
+ - mirascope.response.content: Serialized response content
225
+ - mirascope.response.usage: Serialized usage (if available)
226
+ - mirascope.response.cost: Serialized cost (if available)
227
+ """
228
+ span.set(
229
+ **{
230
+ "mirascope.response.provider_id": response.provider_id,
231
+ "mirascope.response.model_id": response.model_id,
232
+ "mirascope.trace.output": response.pretty(),
233
+ "mirascope.response.messages": serialize_mirascope_messages(
234
+ response.messages[:-1]
235
+ ),
236
+ "mirascope.response.content": serialize_mirascope_content(response.content),
237
+ }
238
+ )
239
+ if (usage_json := serialize_mirascope_usage(response.usage)) is not None:
240
+ span.set(**{"mirascope.response.usage": usage_json})
241
+ logger.debug("Attached usage to span")
242
+ else:
243
+ logger.debug("No usage available, skipping cost calculation")
244
+
245
+ # Calculate and attach cost if usage is available
246
+ if response.usage is not None:
247
+ logger.debug("Attempting cost calculation (sync)")
248
+ cost = calculate_cost_sync(
249
+ response.provider_id, response.model_id, response.usage
250
+ )
251
+ if cost is not None:
252
+ span.set(
253
+ **{
254
+ "mirascope.response.cost": serialize_mirascope_cost(
255
+ input_cost=cost.input_cost_centicents,
256
+ output_cost=cost.output_cost_centicents,
257
+ total_cost=cost.total_cost_centicents,
258
+ cache_read_cost=cost.cache_read_cost_centicents,
259
+ cache_write_cost=cost.cache_write_cost_centicents,
260
+ )
261
+ }
262
+ )
263
+ logger.debug(
264
+ "Attached cost to span: total=%s centicents", cost.total_cost_centicents
265
+ )
266
+ else:
267
+ logger.debug("Cost calculation returned None, not attaching cost to span")
268
+
269
+
270
+ async def attach_mirascope_response_async(
271
+ span: SpanProtocol, response: RootResponse[Any, Any]
272
+ ) -> None:
273
+ """Attach Mirascope-specific response attributes to a span (async version).
274
+
275
+ Sets the following attributes:
276
+ - mirascope.trace.output: Pretty-printed response
277
+ - mirascope.response.messages: Serialized input messages (excluding final assistant message)
278
+ - mirascope.response.content: Serialized response content
279
+ - mirascope.response.usage: Serialized usage (if available)
280
+ - mirascope.response.cost: Serialized cost (if available)
281
+ """
282
+ span.set(
283
+ **{
284
+ "mirascope.response.provider_id": response.provider_id,
285
+ "mirascope.response.model_id": response.model_id,
286
+ "mirascope.trace.output": response.pretty(),
287
+ "mirascope.response.messages": serialize_mirascope_messages(
288
+ response.messages[:-1]
289
+ ),
290
+ "mirascope.response.content": serialize_mirascope_content(response.content),
291
+ }
292
+ )
293
+ if (usage_json := serialize_mirascope_usage(response.usage)) is not None:
294
+ span.set(**{"mirascope.response.usage": usage_json})
295
+ logger.debug("Attached usage to span (async)")
296
+ else:
297
+ logger.debug("No usage available, skipping cost calculation (async)")
298
+
299
+ # Calculate and attach cost if usage is available (async)
300
+ if response.usage is not None:
301
+ logger.debug("Attempting cost calculation (async)")
302
+ cost = await calculate_cost_async(
303
+ response.provider_id, response.model_id, response.usage
304
+ )
305
+ if cost is not None:
306
+ span.set(
307
+ **{
308
+ "mirascope.response.cost": serialize_mirascope_cost(
309
+ input_cost=cost.input_cost_centicents,
310
+ output_cost=cost.output_cost_centicents,
311
+ total_cost=cost.total_cost_centicents,
312
+ cache_read_cost=cost.cache_read_cost_centicents,
313
+ cache_write_cost=cost.cache_write_cost_centicents,
314
+ )
315
+ }
316
+ )
317
+ logger.debug(
318
+ "Attached cost to span (async): total=%s centicents",
319
+ cost.total_cost_centicents,
320
+ )
321
+ else:
322
+ logger.debug(
323
+ "Cost calculation returned None, not attaching cost to span (async)"
324
+ )
@@ -0,0 +1,29 @@
1
+ """Provider instrumentation modules."""
2
+
3
+ from .anthropic import (
4
+ instrument_anthropic,
5
+ is_anthropic_instrumented,
6
+ uninstrument_anthropic,
7
+ )
8
+ from .google_genai import (
9
+ instrument_google_genai,
10
+ is_google_genai_instrumented,
11
+ uninstrument_google_genai,
12
+ )
13
+ from .openai import (
14
+ instrument_openai,
15
+ is_openai_instrumented,
16
+ uninstrument_openai,
17
+ )
18
+
19
+ __all__ = [
20
+ "instrument_anthropic",
21
+ "instrument_google_genai",
22
+ "instrument_openai",
23
+ "is_anthropic_instrumented",
24
+ "is_google_genai_instrumented",
25
+ "is_openai_instrumented",
26
+ "uninstrument_anthropic",
27
+ "uninstrument_google_genai",
28
+ "uninstrument_openai",
29
+ ]
@@ -0,0 +1,78 @@
1
+ """OpenTelemetry instrumentation for Anthropic SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
8
+
9
+ from .base import BaseInstrumentation, ContentCaptureMode
10
+
11
+ if TYPE_CHECKING:
12
+ from opentelemetry.trace import TracerProvider
13
+
14
+
15
+ class AnthropicInstrumentation(BaseInstrumentation[AnthropicInstrumentor]):
16
+ """Manages OpenTelemetry instrumentation lifecycle for the Anthropic SDK."""
17
+
18
+ def _create_instrumentor(self) -> AnthropicInstrumentor:
19
+ """Create a new Anthropic instrumentor instance."""
20
+ return AnthropicInstrumentor()
21
+
22
+ def _configure_capture_content(self, capture_content: ContentCaptureMode) -> None:
23
+ """Configure environment variables for Anthropic content capture."""
24
+ if capture_content == "enabled":
25
+ self._set_env_var("TRACELOOP_TRACE_CONTENT", "true")
26
+ elif capture_content == "disabled":
27
+ self._set_env_var("TRACELOOP_TRACE_CONTENT", "false")
28
+
29
+
30
+ def instrument_anthropic(
31
+ *,
32
+ tracer_provider: TracerProvider | None = None,
33
+ capture_content: ContentCaptureMode = "default",
34
+ ) -> None:
35
+ """Enable OpenTelemetry instrumentation for the Anthropic Python SDK.
36
+
37
+ Uses the provided tracer_provider or the global OpenTelemetry tracer provider.
38
+
39
+ Args:
40
+ tracer_provider: Optional tracer provider to use. If not provided,
41
+ uses the global OpenTelemetry tracer provider.
42
+ capture_content: Controls whether to capture message content in spans.
43
+ - "enabled": Capture message content
44
+ - "disabled": Do not capture message content
45
+ - "default": Use the library's default behavior
46
+
47
+ Example:
48
+
49
+ Enable instrumentation with Mirascope Cloud:
50
+ ```python
51
+ from mirascope import ops
52
+
53
+ ops.configure()
54
+ ops.instrument_anthropic()
55
+ ```
56
+
57
+ Enable instrumentation with content capture:
58
+ ```python
59
+ from mirascope import ops
60
+
61
+ ops.configure()
62
+ ops.instrument_anthropic(capture_content="enabled")
63
+ ```
64
+ """
65
+ AnthropicInstrumentation().instrument(
66
+ tracer_provider=tracer_provider,
67
+ capture_content=capture_content,
68
+ )
69
+
70
+
71
+ def uninstrument_anthropic() -> None:
72
+ """Disable previously configured Anthropic instrumentation."""
73
+ AnthropicInstrumentation().uninstrument()
74
+
75
+
76
+ def is_anthropic_instrumented() -> bool:
77
+ """Return whether Anthropic instrumentation is currently active."""
78
+ return AnthropicInstrumentation().is_instrumented
@@ -0,0 +1,179 @@
1
+ """Base class for OpenTelemetry SDK instrumentation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import threading
7
+ from abc import ABC, abstractmethod
8
+ from typing import TYPE_CHECKING, Generic, Literal, Protocol, TypeVar
9
+
10
+ if TYPE_CHECKING:
11
+ from opentelemetry.trace import TracerProvider
12
+
13
+ ContentCaptureMode = Literal["enabled", "disabled", "default"]
14
+
15
+ # OpenTelemetry semantic conventions environment variable
16
+ OTEL_SEMCONV_STABILITY_OPT_IN = "OTEL_SEMCONV_STABILITY_OPT_IN"
17
+ OTEL_SEMCONV_STABILITY_VALUE = "gen_ai_latest_experimental"
18
+
19
+
20
+ class Instrumentor(Protocol):
21
+ """Protocol for OpenTelemetry instrumentors."""
22
+
23
+ def instrument(self, *, tracer_provider: TracerProvider | None = None) -> None:
24
+ """Enable instrumentation."""
25
+ ...
26
+
27
+ def uninstrument(self) -> None:
28
+ """Disable instrumentation."""
29
+ ...
30
+
31
+
32
+ InstrumentorT = TypeVar("InstrumentorT", bound=Instrumentor)
33
+
34
+
35
+ class BaseInstrumentation(ABC, Generic[InstrumentorT]):
36
+ """Base class for managing OpenTelemetry instrumentation lifecycle.
37
+
38
+ This class provides a thread-safe singleton pattern for SDK instrumentation.
39
+ Subclasses must implement `_create_instrumentor()` and `_configure_capture_content()`.
40
+
41
+ Each subclass gets its own `_instance` and `_instance_lock` via `__init_subclass__`,
42
+ ensuring that different providers can be initialized independently without blocking.
43
+ """
44
+
45
+ _instance: BaseInstrumentation[InstrumentorT] | None = None
46
+ _instance_lock: threading.Lock
47
+ _lock: threading.Lock
48
+ _instrumentor: InstrumentorT | None
49
+ _original_env: dict[str, str | None]
50
+
51
+ def __init_subclass__(cls, **kwargs: object) -> None:
52
+ """Initialize subclass with its own singleton instance and lock."""
53
+ super().__init_subclass__(**kwargs)
54
+ cls._instance = None
55
+ cls._instance_lock = threading.Lock()
56
+
57
+ def __new__(cls) -> BaseInstrumentation[InstrumentorT]:
58
+ """Create or return the singleton instance."""
59
+ if cls._instance is None:
60
+ with cls._instance_lock:
61
+ if cls._instance is None:
62
+ instance = super().__new__(cls)
63
+ instance._lock = threading.Lock()
64
+ instance._instrumentor = None
65
+ instance._original_env = {}
66
+ cls._instance = instance
67
+ return cls._instance
68
+
69
+ @property
70
+ def is_instrumented(self) -> bool:
71
+ """Return whether instrumentation is currently active."""
72
+ return self._instrumentor is not None
73
+
74
+ @abstractmethod
75
+ def _create_instrumentor(self) -> InstrumentorT:
76
+ """Create and return a new instrumentor instance.
77
+
78
+ Returns:
79
+ A new instance of the SDK-specific instrumentor.
80
+ """
81
+ ...
82
+
83
+ @abstractmethod
84
+ def _configure_capture_content(self, capture_content: ContentCaptureMode) -> None:
85
+ """Configure environment variables for content capture.
86
+
87
+ Args:
88
+ capture_content: The capture content mode to configure.
89
+ """
90
+ ...
91
+
92
+ def instrument(
93
+ self,
94
+ *,
95
+ tracer_provider: TracerProvider | None = None,
96
+ capture_content: ContentCaptureMode = "default",
97
+ ) -> None:
98
+ """Enable OpenTelemetry instrumentation for the SDK.
99
+
100
+ Args:
101
+ tracer_provider: Optional tracer provider to use. If not provided,
102
+ uses the global OpenTelemetry tracer provider.
103
+ capture_content: Controls whether to capture message content in spans.
104
+ """
105
+ with self._lock:
106
+ if self.is_instrumented:
107
+ return
108
+
109
+ self._set_env_var(
110
+ OTEL_SEMCONV_STABILITY_OPT_IN,
111
+ OTEL_SEMCONV_STABILITY_VALUE,
112
+ use_setdefault=True,
113
+ )
114
+
115
+ self._configure_capture_content(capture_content)
116
+
117
+ instrumentor = self._create_instrumentor()
118
+ try:
119
+ if tracer_provider is not None:
120
+ instrumentor.instrument(tracer_provider=tracer_provider)
121
+ else:
122
+ instrumentor.instrument()
123
+ except Exception:
124
+ self._restore_env_vars()
125
+ raise
126
+
127
+ self._instrumentor = instrumentor
128
+
129
+ def uninstrument(self) -> None:
130
+ """Disable previously configured instrumentation."""
131
+ with self._lock:
132
+ if self._instrumentor is None:
133
+ return
134
+
135
+ self._instrumentor.uninstrument()
136
+ self._instrumentor = None
137
+ self._restore_env_vars()
138
+
139
+ def _set_env_var(
140
+ self, key: str, value: str, *, use_setdefault: bool = False
141
+ ) -> None:
142
+ """Set an environment variable and track the original value.
143
+
144
+ Args:
145
+ key: The environment variable name.
146
+ value: The value to set.
147
+ use_setdefault: If True, only set if not already present.
148
+ """
149
+ if key not in self._original_env:
150
+ self._original_env[key] = os.environ.get(key)
151
+
152
+ if use_setdefault:
153
+ os.environ.setdefault(key, value)
154
+ else:
155
+ os.environ[key] = value
156
+
157
+ def _restore_env_vars(self) -> None:
158
+ """Restore all environment variables to their original values."""
159
+ for key, value in self._original_env.items():
160
+ if value is None:
161
+ os.environ.pop(key, None)
162
+ else:
163
+ os.environ[key] = value
164
+ self._original_env.clear()
165
+
166
+ @classmethod
167
+ def reset_for_testing(cls) -> None:
168
+ """Reset singleton instance for testing.
169
+
170
+ This properly cleans up the instrumentor and restores environment variables
171
+ before resetting the instance.
172
+ """
173
+ with cls._instance_lock:
174
+ if cls._instance is not None:
175
+ if cls._instance._instrumentor is not None:
176
+ cls._instance._instrumentor.uninstrument()
177
+ cls._instance._instrumentor = None
178
+ cls._instance._restore_env_vars()
179
+ cls._instance = None
@@ -0,0 +1,85 @@
1
+ """OpenTelemetry instrumentation for Google GenAI SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
8
+
9
+ from .base import BaseInstrumentation, ContentCaptureMode
10
+
11
+ if TYPE_CHECKING:
12
+ from opentelemetry.trace import TracerProvider
13
+
14
+
15
+ class GoogleGenAIInstrumentation(BaseInstrumentation[GoogleGenAiSdkInstrumentor]):
16
+ """Manages OpenTelemetry instrumentation lifecycle for the Google GenAI SDK."""
17
+
18
+ def _create_instrumentor(self) -> GoogleGenAiSdkInstrumentor:
19
+ """Create a new Google GenAI instrumentor instance."""
20
+ return GoogleGenAiSdkInstrumentor()
21
+
22
+ def _configure_capture_content(self, capture_content: ContentCaptureMode) -> None:
23
+ """Configure environment variables for Google GenAI content capture."""
24
+ # Google GenAI uses ContentCapturingMode enum instead of true/false.
25
+ # Valid values: NO_CONTENT, SPAN_ONLY, EVENT_ONLY, SPAN_AND_EVENT
26
+ if capture_content == "enabled":
27
+ self._set_env_var(
28
+ "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT",
29
+ "SPAN_AND_EVENT",
30
+ )
31
+ elif capture_content == "disabled":
32
+ self._set_env_var(
33
+ "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT", "NO_CONTENT"
34
+ )
35
+
36
+
37
+ def instrument_google_genai(
38
+ *,
39
+ tracer_provider: TracerProvider | None = None,
40
+ capture_content: ContentCaptureMode = "default",
41
+ ) -> None:
42
+ """Enable OpenTelemetry instrumentation for the Google GenAI Python SDK.
43
+
44
+ Uses the provided tracer_provider or the global OpenTelemetry tracer provider.
45
+
46
+ Args:
47
+ tracer_provider: Optional tracer provider to use. If not provided,
48
+ uses the global OpenTelemetry tracer provider.
49
+ capture_content: Controls whether to capture message content in spans.
50
+ - "enabled": Capture message content
51
+ - "disabled": Do not capture message content
52
+ - "default": Use the library's default behavior
53
+
54
+ Example:
55
+
56
+ Enable instrumentation with Mirascope Cloud:
57
+ ```python
58
+ from mirascope import ops
59
+
60
+ ops.configure()
61
+ ops.instrument_google_genai()
62
+ ```
63
+
64
+ Enable instrumentation with content capture:
65
+ ```python
66
+ from mirascope import ops
67
+
68
+ ops.configure()
69
+ ops.instrument_google_genai(capture_content="enabled")
70
+ ```
71
+ """
72
+ GoogleGenAIInstrumentation().instrument(
73
+ tracer_provider=tracer_provider,
74
+ capture_content=capture_content,
75
+ )
76
+
77
+
78
+ def uninstrument_google_genai() -> None:
79
+ """Disable previously configured Google GenAI instrumentation."""
80
+ GoogleGenAIInstrumentation().uninstrument()
81
+
82
+
83
+ def is_google_genai_instrumented() -> bool:
84
+ """Return whether Google GenAI instrumentation is currently active."""
85
+ return GoogleGenAIInstrumentation().is_instrumented