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,1777 @@
1
+ """OpenTelemetry GenAI instrumentation for `mirascope.llm.Model` methods."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import weakref
6
+ from collections.abc import AsyncIterator, Iterator, Sequence
7
+ from contextlib import AbstractContextManager
8
+ from functools import wraps
9
+ from types import TracebackType
10
+ from typing import (
11
+ TYPE_CHECKING,
12
+ Any,
13
+ cast,
14
+ overload,
15
+ )
16
+
17
+ from opentelemetry import trace as otel_trace
18
+
19
+ from .....llm import (
20
+ AsyncContextResponse,
21
+ AsyncContextStreamResponse,
22
+ AsyncContextTools,
23
+ AsyncResponse,
24
+ AsyncStreamResponse,
25
+ AsyncTools,
26
+ Context,
27
+ ContextResponse,
28
+ ContextStreamResponse,
29
+ ContextTools,
30
+ DepsT,
31
+ FormatSpec,
32
+ FormattableT,
33
+ Message,
34
+ Model,
35
+ Response,
36
+ RootResponse,
37
+ StreamResponse,
38
+ StreamResponseChunk,
39
+ Tools,
40
+ UserContent,
41
+ )
42
+ from .....llm.messages import promote_to_messages, user
43
+ from .common import (
44
+ FormatParam,
45
+ SpanContext,
46
+ attach_response,
47
+ attach_response_async,
48
+ record_dropped_params,
49
+ start_model_span,
50
+ )
51
+
52
+ if TYPE_CHECKING:
53
+ from opentelemetry.trace import Span
54
+
55
+
56
+ # =============================================================================
57
+ # Original method references and wrapped state flags
58
+ # =============================================================================
59
+
60
+ _ORIGINAL_MODEL_CALL = Model.call
61
+ _MODEL_CALL_WRAPPED = False
62
+ _ORIGINAL_MODEL_CALL_ASYNC = Model.call_async
63
+ _MODEL_CALL_ASYNC_WRAPPED = False
64
+ _ORIGINAL_MODEL_CONTEXT_CALL = Model.context_call
65
+ _MODEL_CONTEXT_CALL_WRAPPED = False
66
+ _ORIGINAL_MODEL_CONTEXT_CALL_ASYNC = Model.context_call_async
67
+ _MODEL_CONTEXT_CALL_ASYNC_WRAPPED = False
68
+ _ORIGINAL_MODEL_STREAM = Model.stream
69
+ _MODEL_STREAM_WRAPPED = False
70
+ _ORIGINAL_MODEL_STREAM_ASYNC = Model.stream_async
71
+ _MODEL_STREAM_ASYNC_WRAPPED = False
72
+ _ORIGINAL_MODEL_CONTEXT_STREAM = Model.context_stream
73
+ _MODEL_CONTEXT_STREAM_WRAPPED = False
74
+ _ORIGINAL_MODEL_CONTEXT_STREAM_ASYNC = Model.context_stream_async
75
+ _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED = False
76
+
77
+ # Resume method originals and flags
78
+ _ORIGINAL_MODEL_RESUME = Model.resume
79
+ _MODEL_RESUME_WRAPPED = False
80
+ _ORIGINAL_MODEL_RESUME_ASYNC = Model.resume_async
81
+ _MODEL_RESUME_ASYNC_WRAPPED = False
82
+ _ORIGINAL_MODEL_CONTEXT_RESUME = Model.context_resume
83
+ _MODEL_CONTEXT_RESUME_WRAPPED = False
84
+ _ORIGINAL_MODEL_CONTEXT_RESUME_ASYNC = Model.context_resume_async
85
+ _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED = False
86
+ _ORIGINAL_MODEL_RESUME_STREAM = Model.resume_stream
87
+ _MODEL_RESUME_STREAM_WRAPPED = False
88
+ _ORIGINAL_MODEL_RESUME_STREAM_ASYNC = Model.resume_stream_async
89
+ _MODEL_RESUME_STREAM_ASYNC_WRAPPED = False
90
+ _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM = Model.context_resume_stream
91
+ _MODEL_CONTEXT_RESUME_STREAM_WRAPPED = False
92
+ _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM_ASYNC = Model.context_resume_stream_async
93
+ _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED = False
94
+
95
+
96
+ # =============================================================================
97
+ # Model.call instrumentation
98
+ # =============================================================================
99
+
100
+
101
+ @overload
102
+ def _instrumented_model_call(
103
+ self: Model,
104
+ content: UserContent | Sequence[Message],
105
+ *,
106
+ tools: Tools | None = None,
107
+ format: None = None,
108
+ ) -> Response: ...
109
+
110
+
111
+ @overload
112
+ def _instrumented_model_call(
113
+ self: Model,
114
+ content: UserContent | Sequence[Message],
115
+ *,
116
+ tools: Tools | None = None,
117
+ format: FormatSpec[FormattableT],
118
+ ) -> Response[FormattableT]: ...
119
+
120
+
121
+ @overload
122
+ def _instrumented_model_call(
123
+ self: Model,
124
+ content: UserContent | Sequence[Message],
125
+ *,
126
+ tools: Tools | None = None,
127
+ format: FormatSpec[FormattableT] | None = None,
128
+ ) -> Response | Response[FormattableT]: ...
129
+
130
+
131
+ @wraps(_ORIGINAL_MODEL_CALL)
132
+ def _instrumented_model_call(
133
+ self: Model,
134
+ content: UserContent | Sequence[Message],
135
+ *,
136
+ tools: Tools | None = None,
137
+ format: FormatParam = None,
138
+ ) -> Response | Response[FormattableT]:
139
+ """Returns a GenAI-instrumented result of `Model.call`."""
140
+ messages = promote_to_messages(content)
141
+ with start_model_span(
142
+ self,
143
+ messages=messages,
144
+ tools=tools,
145
+ format=format,
146
+ ) as span_ctx:
147
+ response = _ORIGINAL_MODEL_CALL(
148
+ self,
149
+ content,
150
+ tools=tools,
151
+ format=format,
152
+ )
153
+ if span_ctx.span is not None:
154
+ attach_response(
155
+ span_ctx.span,
156
+ response,
157
+ request_messages=messages,
158
+ )
159
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
160
+ return response
161
+
162
+
163
+ def wrap_model_call() -> None:
164
+ """Returns None. Replaces `Model.call` with the instrumented wrapper."""
165
+ global _MODEL_CALL_WRAPPED
166
+ if _MODEL_CALL_WRAPPED:
167
+ return
168
+ Model.call = _instrumented_model_call
169
+ _MODEL_CALL_WRAPPED = True
170
+
171
+
172
+ def unwrap_model_call() -> None:
173
+ """Returns None. Restores the original `Model.call` implementation."""
174
+ global _MODEL_CALL_WRAPPED
175
+ if not _MODEL_CALL_WRAPPED:
176
+ return
177
+ Model.call = _ORIGINAL_MODEL_CALL
178
+ _MODEL_CALL_WRAPPED = False
179
+
180
+
181
+ # =============================================================================
182
+ # Model.call_async instrumentation
183
+ # =============================================================================
184
+
185
+
186
+ @overload
187
+ async def _instrumented_model_call_async(
188
+ self: Model,
189
+ content: UserContent | Sequence[Message],
190
+ *,
191
+ tools: AsyncTools | None = None,
192
+ format: None = None,
193
+ ) -> AsyncResponse: ...
194
+
195
+
196
+ @overload
197
+ async def _instrumented_model_call_async(
198
+ self: Model,
199
+ content: UserContent | Sequence[Message],
200
+ *,
201
+ tools: AsyncTools | None = None,
202
+ format: FormatSpec[FormattableT],
203
+ ) -> AsyncResponse[FormattableT]: ...
204
+
205
+
206
+ @overload
207
+ async def _instrumented_model_call_async(
208
+ self: Model,
209
+ content: UserContent | Sequence[Message],
210
+ *,
211
+ tools: AsyncTools | None = None,
212
+ format: FormatSpec[FormattableT] | None = None,
213
+ ) -> AsyncResponse | AsyncResponse[FormattableT]: ...
214
+
215
+
216
+ @wraps(_ORIGINAL_MODEL_CALL_ASYNC)
217
+ async def _instrumented_model_call_async(
218
+ self: Model,
219
+ content: UserContent | Sequence[Message],
220
+ *,
221
+ tools: AsyncTools | None = None,
222
+ format: FormatParam = None,
223
+ ) -> AsyncResponse | AsyncResponse[FormattableT]:
224
+ """Returns a GenAI-instrumented result of `Model.call_async`."""
225
+ messages = promote_to_messages(content)
226
+ with start_model_span(
227
+ self,
228
+ messages=messages,
229
+ tools=tools,
230
+ format=format,
231
+ activate=True,
232
+ ) as span_ctx:
233
+ response = await _ORIGINAL_MODEL_CALL_ASYNC(
234
+ self,
235
+ content,
236
+ tools=tools,
237
+ format=format,
238
+ )
239
+ if span_ctx.span is not None:
240
+ await attach_response_async(
241
+ span_ctx.span,
242
+ response,
243
+ request_messages=messages,
244
+ )
245
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
246
+ return response
247
+
248
+
249
+ def wrap_model_call_async() -> None:
250
+ """Returns None. Replaces `Model.call_async` with the instrumented wrapper."""
251
+ global _MODEL_CALL_ASYNC_WRAPPED
252
+ if _MODEL_CALL_ASYNC_WRAPPED:
253
+ return
254
+ Model.call_async = _instrumented_model_call_async
255
+ _MODEL_CALL_ASYNC_WRAPPED = True
256
+
257
+
258
+ def unwrap_model_call_async() -> None:
259
+ """Returns None. Restores the original `Model.call_async` implementation."""
260
+ global _MODEL_CALL_ASYNC_WRAPPED
261
+ if not _MODEL_CALL_ASYNC_WRAPPED:
262
+ return
263
+ Model.call_async = _ORIGINAL_MODEL_CALL_ASYNC
264
+ _MODEL_CALL_ASYNC_WRAPPED = False
265
+
266
+
267
+ # =============================================================================
268
+ # Model.context_call instrumentation
269
+ # =============================================================================
270
+
271
+
272
+ @overload
273
+ def _instrumented_model_context_call(
274
+ self: Model,
275
+ content: UserContent | Sequence[Message],
276
+ *,
277
+ ctx: Context[DepsT],
278
+ tools: ContextTools[DepsT] | None = None,
279
+ format: None = None,
280
+ ) -> ContextResponse[DepsT, None]: ...
281
+
282
+
283
+ @overload
284
+ def _instrumented_model_context_call(
285
+ self: Model,
286
+ content: UserContent | Sequence[Message],
287
+ *,
288
+ ctx: Context[DepsT],
289
+ tools: ContextTools[DepsT] | None = None,
290
+ format: FormatSpec[FormattableT],
291
+ ) -> ContextResponse[DepsT, FormattableT]: ...
292
+
293
+
294
+ @overload
295
+ def _instrumented_model_context_call(
296
+ self: Model,
297
+ content: UserContent | Sequence[Message],
298
+ *,
299
+ ctx: Context[DepsT],
300
+ tools: ContextTools[DepsT] | None = None,
301
+ format: FormatSpec[FormattableT] | None = None,
302
+ ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]: ...
303
+
304
+
305
+ @wraps(_ORIGINAL_MODEL_CONTEXT_CALL)
306
+ def _instrumented_model_context_call(
307
+ self: Model,
308
+ content: UserContent | Sequence[Message],
309
+ *,
310
+ ctx: Context[DepsT],
311
+ tools: ContextTools[DepsT] | None = None,
312
+ format: FormatParam = None,
313
+ ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
314
+ """Returns a GenAI-instrumented result of `Model.context_call`."""
315
+ messages = promote_to_messages(content)
316
+ with start_model_span(
317
+ self,
318
+ messages=messages,
319
+ tools=tools,
320
+ format=format,
321
+ activate=True,
322
+ ) as span_ctx:
323
+ response = _ORIGINAL_MODEL_CONTEXT_CALL(
324
+ self,
325
+ content,
326
+ ctx=ctx,
327
+ tools=tools,
328
+ format=format,
329
+ )
330
+ if span_ctx.span is not None:
331
+ attach_response(
332
+ span_ctx.span,
333
+ response,
334
+ request_messages=messages,
335
+ )
336
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
337
+ return response
338
+
339
+
340
+ def wrap_model_context_call() -> None:
341
+ """Returns None. Replaces `Model.context_call` with the instrumented wrapper."""
342
+ global _MODEL_CONTEXT_CALL_WRAPPED
343
+ if _MODEL_CONTEXT_CALL_WRAPPED:
344
+ return
345
+ Model.context_call = _instrumented_model_context_call
346
+ _MODEL_CONTEXT_CALL_WRAPPED = True
347
+
348
+
349
+ def unwrap_model_context_call() -> None:
350
+ """Returns None. Restores the original `Model.context_call` implementation."""
351
+ global _MODEL_CONTEXT_CALL_WRAPPED
352
+ if not _MODEL_CONTEXT_CALL_WRAPPED:
353
+ return
354
+ Model.context_call = _ORIGINAL_MODEL_CONTEXT_CALL
355
+ _MODEL_CONTEXT_CALL_WRAPPED = False
356
+
357
+
358
+ # =============================================================================
359
+ # Model.context_call_async instrumentation
360
+ # =============================================================================
361
+
362
+
363
+ @overload
364
+ async def _instrumented_model_context_call_async(
365
+ self: Model,
366
+ content: UserContent | Sequence[Message],
367
+ *,
368
+ ctx: Context[DepsT],
369
+ tools: AsyncContextTools[DepsT] | None = None,
370
+ format: None = None,
371
+ ) -> AsyncContextResponse[DepsT, None]: ...
372
+
373
+
374
+ @overload
375
+ async def _instrumented_model_context_call_async(
376
+ self: Model,
377
+ content: UserContent | Sequence[Message],
378
+ *,
379
+ ctx: Context[DepsT],
380
+ tools: AsyncContextTools[DepsT] | None = None,
381
+ format: FormatSpec[FormattableT],
382
+ ) -> AsyncContextResponse[DepsT, FormattableT]: ...
383
+
384
+
385
+ @overload
386
+ async def _instrumented_model_context_call_async(
387
+ self: Model,
388
+ content: UserContent | Sequence[Message],
389
+ *,
390
+ ctx: Context[DepsT],
391
+ tools: AsyncContextTools[DepsT] | None = None,
392
+ format: FormatSpec[FormattableT] | None = None,
393
+ ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]: ...
394
+
395
+
396
+ @wraps(_ORIGINAL_MODEL_CONTEXT_CALL_ASYNC)
397
+ async def _instrumented_model_context_call_async(
398
+ self: Model,
399
+ content: UserContent | Sequence[Message],
400
+ *,
401
+ ctx: Context[DepsT],
402
+ tools: AsyncContextTools[DepsT] | None = None,
403
+ format: FormatParam = None,
404
+ ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
405
+ """Returns a GenAI-instrumented result of `Model.context_call_async`."""
406
+ messages = promote_to_messages(content)
407
+ with start_model_span(
408
+ self,
409
+ messages=messages,
410
+ tools=tools,
411
+ format=format,
412
+ activate=True,
413
+ ) as span_ctx:
414
+ response = await _ORIGINAL_MODEL_CONTEXT_CALL_ASYNC(
415
+ self,
416
+ content,
417
+ ctx=ctx,
418
+ tools=tools,
419
+ format=format,
420
+ )
421
+ if span_ctx.span is not None:
422
+ await attach_response_async(
423
+ span_ctx.span,
424
+ response,
425
+ request_messages=messages,
426
+ )
427
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
428
+ return response
429
+
430
+
431
+ def wrap_model_context_call_async() -> None:
432
+ """Returns None. Replaces `Model.context_call_async` with the instrumented wrapper."""
433
+ global _MODEL_CONTEXT_CALL_ASYNC_WRAPPED
434
+ if _MODEL_CONTEXT_CALL_ASYNC_WRAPPED:
435
+ return
436
+ Model.context_call_async = _instrumented_model_context_call_async
437
+ _MODEL_CONTEXT_CALL_ASYNC_WRAPPED = True
438
+
439
+
440
+ def unwrap_model_context_call_async() -> None:
441
+ """Returns None. Restores the original `Model.context_call_async` implementation."""
442
+ global _MODEL_CONTEXT_CALL_ASYNC_WRAPPED
443
+ if not _MODEL_CONTEXT_CALL_ASYNC_WRAPPED:
444
+ return
445
+ Model.context_call_async = _ORIGINAL_MODEL_CONTEXT_CALL_ASYNC
446
+ _MODEL_CONTEXT_CALL_ASYNC_WRAPPED = False
447
+
448
+
449
+ # =============================================================================
450
+ # Stream span handler helpers
451
+ # =============================================================================
452
+
453
+
454
+ def _attach_stream_span_handlers(
455
+ *,
456
+ response: ContextStreamResponse[DepsT, FormattableT | None]
457
+ | StreamResponse[FormattableT | None],
458
+ span_cm: AbstractContextManager[SpanContext],
459
+ span: Span,
460
+ request_messages: Sequence[Message],
461
+ ) -> None:
462
+ """Returns None. Closes the span when streaming completes."""
463
+ chunk_iterator: Iterator[StreamResponseChunk] = response._chunk_iterator
464
+
465
+ response_ref = weakref.ref(response)
466
+ closed = False
467
+
468
+ def _close_span(
469
+ exc_type: type[BaseException] | None,
470
+ exc: BaseException | None,
471
+ tb: TracebackType | None,
472
+ ) -> None:
473
+ nonlocal closed
474
+ if closed:
475
+ return
476
+ closed = True
477
+ response_obj = response_ref()
478
+ if response_obj is not None:
479
+ attach_response(
480
+ span,
481
+ response_obj,
482
+ request_messages=request_messages,
483
+ )
484
+ span_cm.__exit__(exc_type, exc, tb)
485
+
486
+ def _wrapped_iterator() -> Iterator[StreamResponseChunk]:
487
+ with otel_trace.use_span(span, end_on_exit=False):
488
+ try:
489
+ yield from chunk_iterator
490
+ except Exception as exc: # noqa: BLE001
491
+ _close_span(type(exc), exc, exc.__traceback__)
492
+ raise
493
+ else:
494
+ _close_span(None, None, None)
495
+ finally:
496
+ _close_span(None, None, None)
497
+
498
+ response._chunk_iterator = _wrapped_iterator()
499
+
500
+
501
+ def _attach_async_stream_span_handlers(
502
+ *,
503
+ response: AsyncContextStreamResponse[DepsT, FormattableT | None],
504
+ span_cm: AbstractContextManager[SpanContext],
505
+ span: Span,
506
+ request_messages: Sequence[Message],
507
+ ) -> None:
508
+ """Returns None. Closes the span when async streaming completes."""
509
+ chunk_iterator: AsyncIterator[StreamResponseChunk] = response._chunk_iterator
510
+
511
+ response_ref = weakref.ref(response)
512
+ closed = False
513
+
514
+ def _close_span(
515
+ exc_type: type[BaseException] | None,
516
+ exc: BaseException | None,
517
+ tb: TracebackType | None,
518
+ ) -> None:
519
+ nonlocal closed
520
+ if closed:
521
+ return
522
+ closed = True
523
+ response_obj = response_ref()
524
+ if response_obj is not None:
525
+ attach_response(
526
+ span,
527
+ response_obj,
528
+ request_messages=request_messages,
529
+ )
530
+ span_cm.__exit__(exc_type, exc, tb)
531
+
532
+ async def _wrapped_iterator() -> AsyncIterator[StreamResponseChunk]:
533
+ try:
534
+ async for chunk in chunk_iterator:
535
+ yield chunk
536
+ except Exception as exc: # noqa: BLE001
537
+ _close_span(type(exc), exc, exc.__traceback__)
538
+ raise
539
+ else:
540
+ _close_span(None, None, None)
541
+ finally:
542
+ _close_span(None, None, None)
543
+
544
+ response._chunk_iterator = _wrapped_iterator()
545
+
546
+
547
+ # =============================================================================
548
+ # Model.stream instrumentation
549
+ # =============================================================================
550
+
551
+
552
+ @overload
553
+ def _instrumented_model_stream(
554
+ self: Model,
555
+ content: UserContent | Sequence[Message],
556
+ *,
557
+ tools: Tools | None = None,
558
+ format: None = None,
559
+ ) -> StreamResponse: ...
560
+
561
+
562
+ @overload
563
+ def _instrumented_model_stream(
564
+ self: Model,
565
+ content: UserContent | Sequence[Message],
566
+ *,
567
+ tools: Tools | None = None,
568
+ format: FormatSpec[FormattableT],
569
+ ) -> StreamResponse[FormattableT]: ...
570
+
571
+
572
+ @overload
573
+ def _instrumented_model_stream(
574
+ self: Model,
575
+ content: UserContent | Sequence[Message],
576
+ *,
577
+ tools: Tools | None = None,
578
+ format: FormatSpec[FormattableT] | None = None,
579
+ ) -> StreamResponse | StreamResponse[FormattableT]: ...
580
+
581
+
582
+ @wraps(_ORIGINAL_MODEL_STREAM)
583
+ def _instrumented_model_stream(
584
+ self: Model,
585
+ content: UserContent | Sequence[Message],
586
+ *,
587
+ tools: Tools | None = None,
588
+ format: FormatParam = None,
589
+ ) -> StreamResponse | StreamResponse[FormattableT]:
590
+ """Returns a GenAI-instrumented result of `Model.stream`."""
591
+ messages = promote_to_messages(content)
592
+ span_cm = start_model_span(
593
+ self,
594
+ messages=messages,
595
+ tools=tools,
596
+ format=format,
597
+ activate=False,
598
+ )
599
+ span_ctx = span_cm.__enter__()
600
+ if span_ctx.span is None:
601
+ response = _ORIGINAL_MODEL_STREAM(
602
+ self,
603
+ content,
604
+ tools=tools,
605
+ format=format,
606
+ )
607
+ span_cm.__exit__(None, None, None)
608
+ return response
609
+
610
+ try:
611
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
612
+ response = _ORIGINAL_MODEL_STREAM(
613
+ self,
614
+ content,
615
+ tools=tools,
616
+ format=format,
617
+ )
618
+ except Exception as exc:
619
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
620
+ raise
621
+
622
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
623
+
624
+ try:
625
+ _attach_stream_span_handlers(
626
+ response=response,
627
+ span_cm=span_cm,
628
+ span=span_ctx.span,
629
+ request_messages=messages,
630
+ )
631
+ except Exception as exc: # pragma: no cover
632
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
633
+ raise
634
+
635
+ return response
636
+
637
+
638
+ def wrap_model_stream() -> None:
639
+ """Returns None. Replaces `Model.stream` with the instrumented wrapper."""
640
+ global _MODEL_STREAM_WRAPPED
641
+ if _MODEL_STREAM_WRAPPED:
642
+ return
643
+ Model.stream = _instrumented_model_stream
644
+ _MODEL_STREAM_WRAPPED = True
645
+
646
+
647
+ def unwrap_model_stream() -> None:
648
+ """Returns None. Restores the original `Model.stream` implementation."""
649
+ global _MODEL_STREAM_WRAPPED
650
+ if not _MODEL_STREAM_WRAPPED:
651
+ return
652
+ Model.stream = _ORIGINAL_MODEL_STREAM
653
+ _MODEL_STREAM_WRAPPED = False
654
+
655
+
656
+ # =============================================================================
657
+ # Model.stream_async instrumentation
658
+ # =============================================================================
659
+
660
+
661
+ @overload
662
+ async def _instrumented_model_stream_async(
663
+ self: Model,
664
+ content: UserContent | Sequence[Message],
665
+ *,
666
+ tools: AsyncTools | None = None,
667
+ format: None = None,
668
+ ) -> AsyncStreamResponse: ...
669
+
670
+
671
+ @overload
672
+ async def _instrumented_model_stream_async(
673
+ self: Model,
674
+ content: UserContent | Sequence[Message],
675
+ *,
676
+ tools: AsyncTools | None = None,
677
+ format: FormatSpec[FormattableT],
678
+ ) -> AsyncStreamResponse[FormattableT]: ...
679
+
680
+
681
+ @overload
682
+ async def _instrumented_model_stream_async(
683
+ self: Model,
684
+ content: UserContent | Sequence[Message],
685
+ *,
686
+ tools: AsyncTools | None = None,
687
+ format: FormatSpec[FormattableT] | None = None,
688
+ ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]: ...
689
+
690
+
691
+ @wraps(_ORIGINAL_MODEL_STREAM_ASYNC)
692
+ async def _instrumented_model_stream_async(
693
+ self: Model,
694
+ content: UserContent | Sequence[Message],
695
+ *,
696
+ tools: AsyncTools | None = None,
697
+ format: FormatParam = None,
698
+ ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
699
+ """Returns a GenAI-instrumented result of `Model.stream_async`."""
700
+ messages = promote_to_messages(content)
701
+ span_cm = start_model_span(
702
+ self,
703
+ messages=messages,
704
+ tools=tools,
705
+ format=format,
706
+ activate=False,
707
+ )
708
+ span_ctx = span_cm.__enter__()
709
+ if span_ctx.span is None:
710
+ response = await _ORIGINAL_MODEL_STREAM_ASYNC(
711
+ self,
712
+ content,
713
+ tools=tools,
714
+ format=format,
715
+ )
716
+ span_cm.__exit__(None, None, None)
717
+ return response
718
+
719
+ try:
720
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
721
+ response = await _ORIGINAL_MODEL_STREAM_ASYNC(
722
+ self,
723
+ content,
724
+ tools=tools,
725
+ format=format,
726
+ )
727
+ except Exception as exc:
728
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
729
+ raise
730
+
731
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
732
+
733
+ try:
734
+ _attach_async_stream_span_handlers(
735
+ response=cast(
736
+ "AsyncContextStreamResponse[Any, FormattableT | None]", response
737
+ ),
738
+ span_cm=span_cm,
739
+ span=span_ctx.span,
740
+ request_messages=messages,
741
+ )
742
+ except Exception as exc: # pragma: no cover
743
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
744
+ raise
745
+
746
+ return response
747
+
748
+
749
+ def wrap_model_stream_async() -> None:
750
+ """Returns None. Replaces `Model.stream_async` with the instrumented wrapper."""
751
+ global _MODEL_STREAM_ASYNC_WRAPPED
752
+ if _MODEL_STREAM_ASYNC_WRAPPED:
753
+ return
754
+ Model.stream_async = _instrumented_model_stream_async
755
+ _MODEL_STREAM_ASYNC_WRAPPED = True
756
+
757
+
758
+ def unwrap_model_stream_async() -> None:
759
+ """Returns None. Restores the original `Model.stream_async` implementation."""
760
+ global _MODEL_STREAM_ASYNC_WRAPPED
761
+ if not _MODEL_STREAM_ASYNC_WRAPPED:
762
+ return
763
+ Model.stream_async = _ORIGINAL_MODEL_STREAM_ASYNC
764
+ _MODEL_STREAM_ASYNC_WRAPPED = False
765
+
766
+
767
+ # =============================================================================
768
+ # Model.context_stream instrumentation
769
+ # =============================================================================
770
+
771
+
772
+ @overload
773
+ def _instrumented_model_context_stream(
774
+ self: Model,
775
+ content: UserContent | Sequence[Message],
776
+ *,
777
+ ctx: Context[DepsT],
778
+ tools: ContextTools[DepsT] | None = None,
779
+ format: None = None,
780
+ ) -> ContextStreamResponse[DepsT, None]: ...
781
+
782
+
783
+ @overload
784
+ def _instrumented_model_context_stream(
785
+ self: Model,
786
+ content: UserContent | Sequence[Message],
787
+ *,
788
+ ctx: Context[DepsT],
789
+ tools: ContextTools[DepsT] | None = None,
790
+ format: FormatSpec[FormattableT],
791
+ ) -> ContextStreamResponse[DepsT, FormattableT]: ...
792
+
793
+
794
+ @overload
795
+ def _instrumented_model_context_stream(
796
+ self: Model,
797
+ content: UserContent | Sequence[Message],
798
+ *,
799
+ ctx: Context[DepsT],
800
+ tools: ContextTools[DepsT] | None = None,
801
+ format: FormatSpec[FormattableT] | None = None,
802
+ ) -> (
803
+ ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]
804
+ ): ...
805
+
806
+
807
+ @wraps(_ORIGINAL_MODEL_CONTEXT_STREAM)
808
+ def _instrumented_model_context_stream(
809
+ self: Model,
810
+ content: UserContent | Sequence[Message],
811
+ *,
812
+ ctx: Context[DepsT],
813
+ tools: ContextTools[DepsT] | None = None,
814
+ format: FormatParam = None,
815
+ ) -> ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]:
816
+ """Returns a GenAI-instrumented result of `Model.context_stream`."""
817
+ messages = promote_to_messages(content)
818
+ span_cm = start_model_span(
819
+ self,
820
+ messages=messages,
821
+ tools=tools,
822
+ format=format,
823
+ activate=False,
824
+ )
825
+ span_ctx = span_cm.__enter__()
826
+ if span_ctx.span is None:
827
+ response = _ORIGINAL_MODEL_CONTEXT_STREAM(
828
+ self,
829
+ content,
830
+ ctx=ctx,
831
+ tools=tools,
832
+ format=format,
833
+ )
834
+ span_cm.__exit__(None, None, None)
835
+ return response
836
+
837
+ try:
838
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
839
+ response = _ORIGINAL_MODEL_CONTEXT_STREAM(
840
+ self,
841
+ content,
842
+ ctx=ctx,
843
+ tools=tools,
844
+ format=format,
845
+ )
846
+ except Exception as exc:
847
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
848
+ raise
849
+
850
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
851
+
852
+ try:
853
+ _attach_stream_span_handlers(
854
+ response=response,
855
+ span_cm=span_cm,
856
+ span=span_ctx.span,
857
+ request_messages=messages,
858
+ )
859
+ except Exception as exc: # pragma: no cover
860
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
861
+ raise
862
+
863
+ return response
864
+
865
+
866
+ def wrap_model_context_stream() -> None:
867
+ """Returns None. Replaces `Model.context_stream` with the instrumented wrapper."""
868
+ global _MODEL_CONTEXT_STREAM_WRAPPED
869
+ if _MODEL_CONTEXT_STREAM_WRAPPED:
870
+ return
871
+ Model.context_stream = _instrumented_model_context_stream
872
+ _MODEL_CONTEXT_STREAM_WRAPPED = True
873
+
874
+
875
+ def unwrap_model_context_stream() -> None:
876
+ """Returns None. Restores the original `Model.context_stream` implementation."""
877
+ global _MODEL_CONTEXT_STREAM_WRAPPED
878
+ if not _MODEL_CONTEXT_STREAM_WRAPPED:
879
+ return
880
+ Model.context_stream = _ORIGINAL_MODEL_CONTEXT_STREAM
881
+ _MODEL_CONTEXT_STREAM_WRAPPED = False
882
+
883
+
884
+ # =============================================================================
885
+ # Model.context_stream_async instrumentation
886
+ # =============================================================================
887
+
888
+
889
+ @overload
890
+ async def _instrumented_model_context_stream_async(
891
+ self: Model,
892
+ content: UserContent | Sequence[Message],
893
+ *,
894
+ ctx: Context[DepsT],
895
+ tools: AsyncContextTools[DepsT] | None = None,
896
+ format: None = None,
897
+ ) -> AsyncContextStreamResponse[DepsT, None]: ...
898
+
899
+
900
+ @overload
901
+ async def _instrumented_model_context_stream_async(
902
+ self: Model,
903
+ content: UserContent | Sequence[Message],
904
+ *,
905
+ ctx: Context[DepsT],
906
+ tools: AsyncContextTools[DepsT] | None = None,
907
+ format: FormatSpec[FormattableT],
908
+ ) -> AsyncContextStreamResponse[DepsT, FormattableT]: ...
909
+
910
+
911
+ @overload
912
+ async def _instrumented_model_context_stream_async(
913
+ self: Model,
914
+ content: UserContent | Sequence[Message],
915
+ *,
916
+ ctx: Context[DepsT],
917
+ tools: AsyncContextTools[DepsT] | None = None,
918
+ format: FormatSpec[FormattableT] | None = None,
919
+ ) -> (
920
+ AsyncContextStreamResponse[DepsT, None]
921
+ | AsyncContextStreamResponse[DepsT, FormattableT]
922
+ ): ...
923
+
924
+
925
+ @wraps(_ORIGINAL_MODEL_CONTEXT_STREAM_ASYNC)
926
+ async def _instrumented_model_context_stream_async(
927
+ self: Model,
928
+ content: UserContent | Sequence[Message],
929
+ *,
930
+ ctx: Context[DepsT],
931
+ tools: AsyncContextTools[DepsT] | None = None,
932
+ format: FormatParam = None,
933
+ ) -> (
934
+ AsyncContextStreamResponse[DepsT, None]
935
+ | AsyncContextStreamResponse[DepsT, FormattableT]
936
+ ):
937
+ """Returns a GenAI-instrumented result of `Model.context_stream_async`."""
938
+ messages = promote_to_messages(content)
939
+ span_cm = start_model_span(
940
+ self,
941
+ messages=messages,
942
+ tools=tools,
943
+ format=format,
944
+ activate=False,
945
+ )
946
+ span_ctx = span_cm.__enter__()
947
+ if span_ctx.span is None:
948
+ response = await _ORIGINAL_MODEL_CONTEXT_STREAM_ASYNC(
949
+ self,
950
+ content,
951
+ ctx=ctx,
952
+ tools=tools,
953
+ format=format,
954
+ )
955
+ span_cm.__exit__(None, None, None)
956
+ return response
957
+
958
+ try:
959
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
960
+ response = await _ORIGINAL_MODEL_CONTEXT_STREAM_ASYNC(
961
+ self,
962
+ content,
963
+ ctx=ctx,
964
+ tools=tools,
965
+ format=format,
966
+ )
967
+ except Exception as exc:
968
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
969
+ raise
970
+
971
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
972
+
973
+ try:
974
+ _attach_async_stream_span_handlers(
975
+ response=response,
976
+ span_cm=span_cm,
977
+ span=span_ctx.span,
978
+ request_messages=messages,
979
+ )
980
+ except Exception as exc: # pragma: no cover
981
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
982
+ raise
983
+
984
+ return response
985
+
986
+
987
+ def wrap_model_context_stream_async() -> None:
988
+ """Returns None. Replaces `Model.context_stream_async` with the instrumented wrapper."""
989
+ global _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED
990
+ if _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED:
991
+ return
992
+ Model.context_stream_async = _instrumented_model_context_stream_async
993
+ _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED = True
994
+
995
+
996
+ def unwrap_model_context_stream_async() -> None:
997
+ """Returns None. Restores the original `Model.context_stream_async` implementation."""
998
+ global _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED
999
+ if not _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED:
1000
+ return
1001
+ Model.context_stream_async = _ORIGINAL_MODEL_CONTEXT_STREAM_ASYNC
1002
+ _MODEL_CONTEXT_STREAM_ASYNC_WRAPPED = False
1003
+
1004
+
1005
+ # =============================================================================
1006
+ # Model.resume instrumentation
1007
+ # =============================================================================
1008
+
1009
+
1010
+ @overload
1011
+ def _instrumented_model_resume(
1012
+ self: Model,
1013
+ *,
1014
+ response: Response,
1015
+ content: UserContent,
1016
+ ) -> Response: ...
1017
+
1018
+
1019
+ @overload
1020
+ def _instrumented_model_resume(
1021
+ self: Model,
1022
+ *,
1023
+ response: Response[FormattableT],
1024
+ content: UserContent,
1025
+ ) -> Response[FormattableT]: ...
1026
+
1027
+
1028
+ @overload
1029
+ def _instrumented_model_resume(
1030
+ self: Model,
1031
+ *,
1032
+ response: Response | Response[FormattableT],
1033
+ content: UserContent,
1034
+ ) -> Response | Response[FormattableT]: ...
1035
+
1036
+
1037
+ @wraps(_ORIGINAL_MODEL_RESUME)
1038
+ def _instrumented_model_resume(
1039
+ self: Model,
1040
+ *,
1041
+ response: Response | Response[FormattableT],
1042
+ content: UserContent,
1043
+ ) -> Response | Response[FormattableT]:
1044
+ """Returns a GenAI-instrumented result of `Model.resume`."""
1045
+ messages = list(response.messages) + [user(content)]
1046
+ with start_model_span(
1047
+ self,
1048
+ messages=messages,
1049
+ tools=response.toolkit,
1050
+ format=cast(FormatParam, response.format),
1051
+ ) as span_ctx:
1052
+ result = _ORIGINAL_MODEL_RESUME(
1053
+ self,
1054
+ response=response,
1055
+ content=content,
1056
+ )
1057
+ if span_ctx.span is not None:
1058
+ attach_response(
1059
+ span_ctx.span,
1060
+ cast("RootResponse[Any, FormattableT | None]", result),
1061
+ request_messages=messages,
1062
+ )
1063
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1064
+ return result
1065
+
1066
+
1067
+ def wrap_model_resume() -> None:
1068
+ """Returns None. Replaces `Model.resume` with the instrumented wrapper."""
1069
+ global _MODEL_RESUME_WRAPPED
1070
+ if _MODEL_RESUME_WRAPPED:
1071
+ return
1072
+ Model.resume = _instrumented_model_resume
1073
+ _MODEL_RESUME_WRAPPED = True
1074
+
1075
+
1076
+ def unwrap_model_resume() -> None:
1077
+ """Returns None. Restores the original `Model.resume` implementation."""
1078
+ global _MODEL_RESUME_WRAPPED
1079
+ if not _MODEL_RESUME_WRAPPED:
1080
+ return
1081
+ Model.resume = _ORIGINAL_MODEL_RESUME
1082
+ _MODEL_RESUME_WRAPPED = False
1083
+
1084
+
1085
+ # =============================================================================
1086
+ # Model.resume_async instrumentation
1087
+ # =============================================================================
1088
+
1089
+
1090
+ @overload
1091
+ async def _instrumented_model_resume_async(
1092
+ self: Model,
1093
+ *,
1094
+ response: AsyncResponse,
1095
+ content: UserContent,
1096
+ ) -> AsyncResponse: ...
1097
+
1098
+
1099
+ @overload
1100
+ async def _instrumented_model_resume_async(
1101
+ self: Model,
1102
+ *,
1103
+ response: AsyncResponse[FormattableT],
1104
+ content: UserContent,
1105
+ ) -> AsyncResponse[FormattableT]: ...
1106
+
1107
+
1108
+ @overload
1109
+ async def _instrumented_model_resume_async(
1110
+ self: Model,
1111
+ *,
1112
+ response: AsyncResponse | AsyncResponse[FormattableT],
1113
+ content: UserContent,
1114
+ ) -> AsyncResponse | AsyncResponse[FormattableT]: ...
1115
+
1116
+
1117
+ @wraps(_ORIGINAL_MODEL_RESUME_ASYNC)
1118
+ async def _instrumented_model_resume_async(
1119
+ self: Model,
1120
+ *,
1121
+ response: AsyncResponse | AsyncResponse[FormattableT],
1122
+ content: UserContent,
1123
+ ) -> AsyncResponse | AsyncResponse[FormattableT]:
1124
+ """Returns a GenAI-instrumented result of `Model.resume_async`."""
1125
+ messages = list(response.messages) + [user(content)]
1126
+ with start_model_span(
1127
+ self,
1128
+ messages=messages,
1129
+ tools=response.toolkit,
1130
+ format=cast(FormatParam, response.format),
1131
+ activate=True,
1132
+ ) as span_ctx:
1133
+ result = await _ORIGINAL_MODEL_RESUME_ASYNC(
1134
+ self,
1135
+ response=response,
1136
+ content=content,
1137
+ )
1138
+ if span_ctx.span is not None:
1139
+ await attach_response_async(
1140
+ span_ctx.span,
1141
+ cast("RootResponse[Any, FormattableT | None]", result),
1142
+ request_messages=messages,
1143
+ )
1144
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1145
+ return result
1146
+
1147
+
1148
+ def wrap_model_resume_async() -> None:
1149
+ """Returns None. Replaces `Model.resume_async` with the instrumented wrapper."""
1150
+ global _MODEL_RESUME_ASYNC_WRAPPED
1151
+ if _MODEL_RESUME_ASYNC_WRAPPED:
1152
+ return
1153
+ Model.resume_async = _instrumented_model_resume_async
1154
+ _MODEL_RESUME_ASYNC_WRAPPED = True
1155
+
1156
+
1157
+ def unwrap_model_resume_async() -> None:
1158
+ """Returns None. Restores the original `Model.resume_async` implementation."""
1159
+ global _MODEL_RESUME_ASYNC_WRAPPED
1160
+ if not _MODEL_RESUME_ASYNC_WRAPPED:
1161
+ return
1162
+ Model.resume_async = _ORIGINAL_MODEL_RESUME_ASYNC
1163
+ _MODEL_RESUME_ASYNC_WRAPPED = False
1164
+
1165
+
1166
+ # =============================================================================
1167
+ # Model.context_resume instrumentation
1168
+ # =============================================================================
1169
+
1170
+
1171
+ @overload
1172
+ def _instrumented_model_context_resume(
1173
+ self: Model,
1174
+ *,
1175
+ ctx: Context[DepsT],
1176
+ response: ContextResponse[DepsT, None],
1177
+ content: UserContent,
1178
+ ) -> ContextResponse[DepsT, None]: ...
1179
+
1180
+
1181
+ @overload
1182
+ def _instrumented_model_context_resume(
1183
+ self: Model,
1184
+ *,
1185
+ ctx: Context[DepsT],
1186
+ response: ContextResponse[DepsT, FormattableT],
1187
+ content: UserContent,
1188
+ ) -> ContextResponse[DepsT, FormattableT]: ...
1189
+
1190
+
1191
+ @overload
1192
+ def _instrumented_model_context_resume(
1193
+ self: Model,
1194
+ *,
1195
+ ctx: Context[DepsT],
1196
+ response: ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT],
1197
+ content: UserContent,
1198
+ ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]: ...
1199
+
1200
+
1201
+ @wraps(_ORIGINAL_MODEL_CONTEXT_RESUME)
1202
+ def _instrumented_model_context_resume(
1203
+ self: Model,
1204
+ *,
1205
+ ctx: Context[DepsT],
1206
+ response: ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT],
1207
+ content: UserContent,
1208
+ ) -> ContextResponse[DepsT, None] | ContextResponse[DepsT, FormattableT]:
1209
+ """Returns a GenAI-instrumented result of `Model.context_resume`."""
1210
+ messages = list(response.messages) + [user(content)]
1211
+ with start_model_span(
1212
+ self,
1213
+ messages=messages,
1214
+ tools=response.toolkit,
1215
+ format=cast(FormatParam, response.format),
1216
+ activate=True,
1217
+ ) as span_ctx:
1218
+ result = _ORIGINAL_MODEL_CONTEXT_RESUME(
1219
+ self,
1220
+ ctx=ctx,
1221
+ response=response,
1222
+ content=content,
1223
+ )
1224
+ if span_ctx.span is not None:
1225
+ attach_response(
1226
+ span_ctx.span,
1227
+ cast("RootResponse[Any, FormattableT | None]", result),
1228
+ request_messages=messages,
1229
+ )
1230
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1231
+ return result
1232
+
1233
+
1234
+ def wrap_model_context_resume() -> None:
1235
+ """Returns None. Replaces `Model.context_resume` with the instrumented wrapper."""
1236
+ global _MODEL_CONTEXT_RESUME_WRAPPED
1237
+ if _MODEL_CONTEXT_RESUME_WRAPPED:
1238
+ return
1239
+ Model.context_resume = _instrumented_model_context_resume
1240
+ _MODEL_CONTEXT_RESUME_WRAPPED = True
1241
+
1242
+
1243
+ def unwrap_model_context_resume() -> None:
1244
+ """Returns None. Restores the original `Model.context_resume` implementation."""
1245
+ global _MODEL_CONTEXT_RESUME_WRAPPED
1246
+ if not _MODEL_CONTEXT_RESUME_WRAPPED:
1247
+ return
1248
+ Model.context_resume = _ORIGINAL_MODEL_CONTEXT_RESUME
1249
+ _MODEL_CONTEXT_RESUME_WRAPPED = False
1250
+
1251
+
1252
+ # =============================================================================
1253
+ # Model.context_resume_async instrumentation
1254
+ # =============================================================================
1255
+
1256
+
1257
+ @overload
1258
+ async def _instrumented_model_context_resume_async(
1259
+ self: Model,
1260
+ *,
1261
+ ctx: Context[DepsT],
1262
+ response: AsyncContextResponse[DepsT, None],
1263
+ content: UserContent,
1264
+ ) -> AsyncContextResponse[DepsT, None]: ...
1265
+
1266
+
1267
+ @overload
1268
+ async def _instrumented_model_context_resume_async(
1269
+ self: Model,
1270
+ *,
1271
+ ctx: Context[DepsT],
1272
+ response: AsyncContextResponse[DepsT, FormattableT],
1273
+ content: UserContent,
1274
+ ) -> AsyncContextResponse[DepsT, FormattableT]: ...
1275
+
1276
+
1277
+ @overload
1278
+ async def _instrumented_model_context_resume_async(
1279
+ self: Model,
1280
+ *,
1281
+ ctx: Context[DepsT],
1282
+ response: AsyncContextResponse[DepsT, None]
1283
+ | AsyncContextResponse[DepsT, FormattableT],
1284
+ content: UserContent,
1285
+ ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]: ...
1286
+
1287
+
1288
+ @wraps(_ORIGINAL_MODEL_CONTEXT_RESUME_ASYNC)
1289
+ async def _instrumented_model_context_resume_async(
1290
+ self: Model,
1291
+ *,
1292
+ ctx: Context[DepsT],
1293
+ response: AsyncContextResponse[DepsT, None]
1294
+ | AsyncContextResponse[DepsT, FormattableT],
1295
+ content: UserContent,
1296
+ ) -> AsyncContextResponse[DepsT, None] | AsyncContextResponse[DepsT, FormattableT]:
1297
+ """Returns a GenAI-instrumented result of `Model.context_resume_async`."""
1298
+ messages = list(response.messages) + [user(content)]
1299
+ with start_model_span(
1300
+ self,
1301
+ messages=messages,
1302
+ tools=response.toolkit,
1303
+ format=cast(FormatParam, response.format),
1304
+ activate=True,
1305
+ ) as span_ctx:
1306
+ result = await _ORIGINAL_MODEL_CONTEXT_RESUME_ASYNC(
1307
+ self,
1308
+ ctx=ctx,
1309
+ response=response,
1310
+ content=content,
1311
+ )
1312
+ if span_ctx.span is not None:
1313
+ await attach_response_async(
1314
+ span_ctx.span,
1315
+ cast("RootResponse[Any, FormattableT | None]", result),
1316
+ request_messages=messages,
1317
+ )
1318
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1319
+ return result
1320
+
1321
+
1322
+ def wrap_model_context_resume_async() -> None:
1323
+ """Returns None. Replaces `Model.context_resume_async` with the instrumented wrapper."""
1324
+ global _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED
1325
+ if _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED:
1326
+ return
1327
+ Model.context_resume_async = _instrumented_model_context_resume_async
1328
+ _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED = True
1329
+
1330
+
1331
+ def unwrap_model_context_resume_async() -> None:
1332
+ """Returns None. Restores the original `Model.context_resume_async` implementation."""
1333
+ global _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED
1334
+ if not _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED:
1335
+ return
1336
+ Model.context_resume_async = _ORIGINAL_MODEL_CONTEXT_RESUME_ASYNC
1337
+ _MODEL_CONTEXT_RESUME_ASYNC_WRAPPED = False
1338
+
1339
+
1340
+ # =============================================================================
1341
+ # Model.resume_stream instrumentation
1342
+ # =============================================================================
1343
+
1344
+
1345
+ @overload
1346
+ def _instrumented_model_resume_stream(
1347
+ self: Model,
1348
+ *,
1349
+ response: StreamResponse,
1350
+ content: UserContent,
1351
+ ) -> StreamResponse: ...
1352
+
1353
+
1354
+ @overload
1355
+ def _instrumented_model_resume_stream(
1356
+ self: Model,
1357
+ *,
1358
+ response: StreamResponse[FormattableT],
1359
+ content: UserContent,
1360
+ ) -> StreamResponse[FormattableT]: ...
1361
+
1362
+
1363
+ @overload
1364
+ def _instrumented_model_resume_stream(
1365
+ self: Model,
1366
+ *,
1367
+ response: StreamResponse | StreamResponse[FormattableT],
1368
+ content: UserContent,
1369
+ ) -> StreamResponse | StreamResponse[FormattableT]: ...
1370
+
1371
+
1372
+ @wraps(_ORIGINAL_MODEL_RESUME_STREAM)
1373
+ def _instrumented_model_resume_stream(
1374
+ self: Model,
1375
+ *,
1376
+ response: StreamResponse | StreamResponse[FormattableT],
1377
+ content: UserContent,
1378
+ ) -> StreamResponse | StreamResponse[FormattableT]:
1379
+ """Returns a GenAI-instrumented result of `Model.resume_stream`."""
1380
+ messages = list(response.messages) + [user(content)]
1381
+ span_cm = start_model_span(
1382
+ self,
1383
+ messages=messages,
1384
+ tools=response.toolkit,
1385
+ format=cast(FormatParam, response.format),
1386
+ activate=False,
1387
+ )
1388
+ span_ctx = span_cm.__enter__()
1389
+ if span_ctx.span is None:
1390
+ result = _ORIGINAL_MODEL_RESUME_STREAM(
1391
+ self,
1392
+ response=response,
1393
+ content=content,
1394
+ )
1395
+ span_cm.__exit__(None, None, None)
1396
+ return result
1397
+
1398
+ try:
1399
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
1400
+ result = _ORIGINAL_MODEL_RESUME_STREAM(
1401
+ self,
1402
+ response=response,
1403
+ content=content,
1404
+ )
1405
+ except Exception as exc:
1406
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1407
+ raise
1408
+
1409
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1410
+
1411
+ try:
1412
+ _attach_stream_span_handlers(
1413
+ response=cast(StreamResponse[FormattableT | None], result),
1414
+ span_cm=span_cm,
1415
+ span=span_ctx.span,
1416
+ request_messages=messages,
1417
+ )
1418
+ except Exception as exc: # pragma: no cover
1419
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1420
+ raise
1421
+
1422
+ return result
1423
+
1424
+
1425
+ def wrap_model_resume_stream() -> None:
1426
+ """Returns None. Replaces `Model.resume_stream` with the instrumented wrapper."""
1427
+ global _MODEL_RESUME_STREAM_WRAPPED
1428
+ if _MODEL_RESUME_STREAM_WRAPPED:
1429
+ return
1430
+ Model.resume_stream = _instrumented_model_resume_stream
1431
+ _MODEL_RESUME_STREAM_WRAPPED = True
1432
+
1433
+
1434
+ def unwrap_model_resume_stream() -> None:
1435
+ """Returns None. Restores the original `Model.resume_stream` implementation."""
1436
+ global _MODEL_RESUME_STREAM_WRAPPED
1437
+ if not _MODEL_RESUME_STREAM_WRAPPED:
1438
+ return
1439
+ Model.resume_stream = _ORIGINAL_MODEL_RESUME_STREAM
1440
+ _MODEL_RESUME_STREAM_WRAPPED = False
1441
+
1442
+
1443
+ # =============================================================================
1444
+ # Model.resume_stream_async instrumentation
1445
+ # =============================================================================
1446
+
1447
+
1448
+ @overload
1449
+ async def _instrumented_model_resume_stream_async(
1450
+ self: Model,
1451
+ *,
1452
+ response: AsyncStreamResponse,
1453
+ content: UserContent,
1454
+ ) -> AsyncStreamResponse: ...
1455
+
1456
+
1457
+ @overload
1458
+ async def _instrumented_model_resume_stream_async(
1459
+ self: Model,
1460
+ *,
1461
+ response: AsyncStreamResponse[FormattableT],
1462
+ content: UserContent,
1463
+ ) -> AsyncStreamResponse[FormattableT]: ...
1464
+
1465
+
1466
+ @overload
1467
+ async def _instrumented_model_resume_stream_async(
1468
+ self: Model,
1469
+ *,
1470
+ response: AsyncStreamResponse | AsyncStreamResponse[FormattableT],
1471
+ content: UserContent,
1472
+ ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]: ...
1473
+
1474
+
1475
+ @wraps(_ORIGINAL_MODEL_RESUME_STREAM_ASYNC)
1476
+ async def _instrumented_model_resume_stream_async(
1477
+ self: Model,
1478
+ *,
1479
+ response: AsyncStreamResponse | AsyncStreamResponse[FormattableT],
1480
+ content: UserContent,
1481
+ ) -> AsyncStreamResponse | AsyncStreamResponse[FormattableT]:
1482
+ """Returns a GenAI-instrumented result of `Model.resume_stream_async`."""
1483
+ messages = list(response.messages) + [user(content)]
1484
+ span_cm = start_model_span(
1485
+ self,
1486
+ messages=messages,
1487
+ tools=response.toolkit,
1488
+ format=cast(FormatParam, response.format),
1489
+ activate=False,
1490
+ )
1491
+ span_ctx = span_cm.__enter__()
1492
+ if span_ctx.span is None:
1493
+ result = await _ORIGINAL_MODEL_RESUME_STREAM_ASYNC(
1494
+ self,
1495
+ response=response,
1496
+ content=content,
1497
+ )
1498
+ span_cm.__exit__(None, None, None)
1499
+ return result
1500
+
1501
+ try:
1502
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
1503
+ result = await _ORIGINAL_MODEL_RESUME_STREAM_ASYNC(
1504
+ self,
1505
+ response=response,
1506
+ content=content,
1507
+ )
1508
+ except Exception as exc:
1509
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1510
+ raise
1511
+
1512
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1513
+
1514
+ try:
1515
+ _attach_async_stream_span_handlers(
1516
+ response=cast(
1517
+ "AsyncContextStreamResponse[Any, FormattableT | None]", result
1518
+ ),
1519
+ span_cm=span_cm,
1520
+ span=span_ctx.span,
1521
+ request_messages=messages,
1522
+ )
1523
+ except Exception as exc: # pragma: no cover
1524
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1525
+ raise
1526
+
1527
+ return result
1528
+
1529
+
1530
+ def wrap_model_resume_stream_async() -> None:
1531
+ """Returns None. Replaces `Model.resume_stream_async` with the instrumented wrapper."""
1532
+ global _MODEL_RESUME_STREAM_ASYNC_WRAPPED
1533
+ if _MODEL_RESUME_STREAM_ASYNC_WRAPPED:
1534
+ return
1535
+ Model.resume_stream_async = _instrumented_model_resume_stream_async
1536
+ _MODEL_RESUME_STREAM_ASYNC_WRAPPED = True
1537
+
1538
+
1539
+ def unwrap_model_resume_stream_async() -> None:
1540
+ """Returns None. Restores the original `Model.resume_stream_async` implementation."""
1541
+ global _MODEL_RESUME_STREAM_ASYNC_WRAPPED
1542
+ if not _MODEL_RESUME_STREAM_ASYNC_WRAPPED:
1543
+ return
1544
+ Model.resume_stream_async = _ORIGINAL_MODEL_RESUME_STREAM_ASYNC
1545
+ _MODEL_RESUME_STREAM_ASYNC_WRAPPED = False
1546
+
1547
+
1548
+ # =============================================================================
1549
+ # Model.context_resume_stream instrumentation
1550
+ # =============================================================================
1551
+
1552
+
1553
+ @overload
1554
+ def _instrumented_model_context_resume_stream(
1555
+ self: Model,
1556
+ *,
1557
+ ctx: Context[DepsT],
1558
+ response: ContextStreamResponse[DepsT, None],
1559
+ content: UserContent,
1560
+ ) -> ContextStreamResponse[DepsT, None]: ...
1561
+
1562
+
1563
+ @overload
1564
+ def _instrumented_model_context_resume_stream(
1565
+ self: Model,
1566
+ *,
1567
+ ctx: Context[DepsT],
1568
+ response: ContextStreamResponse[DepsT, FormattableT],
1569
+ content: UserContent,
1570
+ ) -> ContextStreamResponse[DepsT, FormattableT]: ...
1571
+
1572
+
1573
+ @overload
1574
+ def _instrumented_model_context_resume_stream(
1575
+ self: Model,
1576
+ *,
1577
+ ctx: Context[DepsT],
1578
+ response: ContextStreamResponse[DepsT, None]
1579
+ | ContextStreamResponse[DepsT, FormattableT],
1580
+ content: UserContent,
1581
+ ) -> (
1582
+ ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]
1583
+ ): ...
1584
+
1585
+
1586
+ @wraps(_ORIGINAL_MODEL_CONTEXT_RESUME_STREAM)
1587
+ def _instrumented_model_context_resume_stream(
1588
+ self: Model,
1589
+ *,
1590
+ ctx: Context[DepsT],
1591
+ response: ContextStreamResponse[DepsT, None]
1592
+ | ContextStreamResponse[DepsT, FormattableT],
1593
+ content: UserContent,
1594
+ ) -> ContextStreamResponse[DepsT, None] | ContextStreamResponse[DepsT, FormattableT]:
1595
+ """Returns a GenAI-instrumented result of `Model.context_resume_stream`."""
1596
+ messages = list(response.messages) + [user(content)]
1597
+ span_cm = start_model_span(
1598
+ self,
1599
+ messages=messages,
1600
+ tools=response.toolkit,
1601
+ format=cast(FormatParam, response.format),
1602
+ activate=False,
1603
+ )
1604
+ span_ctx = span_cm.__enter__()
1605
+ if span_ctx.span is None:
1606
+ result = _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM(
1607
+ self,
1608
+ ctx=ctx,
1609
+ response=response,
1610
+ content=content,
1611
+ )
1612
+ span_cm.__exit__(None, None, None)
1613
+ return result
1614
+
1615
+ try:
1616
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
1617
+ result = _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM(
1618
+ self,
1619
+ ctx=ctx,
1620
+ response=response,
1621
+ content=content,
1622
+ )
1623
+ except Exception as exc:
1624
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1625
+ raise
1626
+
1627
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1628
+
1629
+ try:
1630
+ _attach_stream_span_handlers(
1631
+ response=cast("ContextStreamResponse[Any, FormattableT | None]", result),
1632
+ span_cm=span_cm,
1633
+ span=span_ctx.span,
1634
+ request_messages=messages,
1635
+ )
1636
+ except Exception as exc: # pragma: no cover
1637
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1638
+ raise
1639
+
1640
+ return result
1641
+
1642
+
1643
+ def wrap_model_context_resume_stream() -> None:
1644
+ """Returns None. Replaces `Model.context_resume_stream` with the instrumented wrapper."""
1645
+ global _MODEL_CONTEXT_RESUME_STREAM_WRAPPED
1646
+ if _MODEL_CONTEXT_RESUME_STREAM_WRAPPED:
1647
+ return
1648
+ Model.context_resume_stream = _instrumented_model_context_resume_stream
1649
+ _MODEL_CONTEXT_RESUME_STREAM_WRAPPED = True
1650
+
1651
+
1652
+ def unwrap_model_context_resume_stream() -> None:
1653
+ """Returns None. Restores the original `Model.context_resume_stream` implementation."""
1654
+ global _MODEL_CONTEXT_RESUME_STREAM_WRAPPED
1655
+ if not _MODEL_CONTEXT_RESUME_STREAM_WRAPPED:
1656
+ return
1657
+ Model.context_resume_stream = _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM
1658
+ _MODEL_CONTEXT_RESUME_STREAM_WRAPPED = False
1659
+
1660
+
1661
+ # =============================================================================
1662
+ # Model.context_resume_stream_async instrumentation
1663
+ # =============================================================================
1664
+
1665
+
1666
+ @overload
1667
+ async def _instrumented_model_context_resume_stream_async(
1668
+ self: Model,
1669
+ *,
1670
+ ctx: Context[DepsT],
1671
+ response: AsyncContextStreamResponse[DepsT, None],
1672
+ content: UserContent,
1673
+ ) -> AsyncContextStreamResponse[DepsT, None]: ...
1674
+
1675
+
1676
+ @overload
1677
+ async def _instrumented_model_context_resume_stream_async(
1678
+ self: Model,
1679
+ *,
1680
+ ctx: Context[DepsT],
1681
+ response: AsyncContextStreamResponse[DepsT, FormattableT],
1682
+ content: UserContent,
1683
+ ) -> AsyncContextStreamResponse[DepsT, FormattableT]: ...
1684
+
1685
+
1686
+ @overload
1687
+ async def _instrumented_model_context_resume_stream_async(
1688
+ self: Model,
1689
+ *,
1690
+ ctx: Context[DepsT],
1691
+ response: AsyncContextStreamResponse[DepsT, None]
1692
+ | AsyncContextStreamResponse[DepsT, FormattableT],
1693
+ content: UserContent,
1694
+ ) -> (
1695
+ AsyncContextStreamResponse[DepsT, None]
1696
+ | AsyncContextStreamResponse[DepsT, FormattableT]
1697
+ ): ...
1698
+
1699
+
1700
+ @wraps(_ORIGINAL_MODEL_CONTEXT_RESUME_STREAM_ASYNC)
1701
+ async def _instrumented_model_context_resume_stream_async(
1702
+ self: Model,
1703
+ *,
1704
+ ctx: Context[DepsT],
1705
+ response: AsyncContextStreamResponse[DepsT, None]
1706
+ | AsyncContextStreamResponse[DepsT, FormattableT],
1707
+ content: UserContent,
1708
+ ) -> (
1709
+ AsyncContextStreamResponse[DepsT, None]
1710
+ | AsyncContextStreamResponse[DepsT, FormattableT]
1711
+ ):
1712
+ """Returns a GenAI-instrumented result of `Model.context_resume_stream_async`."""
1713
+ messages = list(response.messages) + [user(content)]
1714
+ span_cm = start_model_span(
1715
+ self,
1716
+ messages=messages,
1717
+ tools=response.toolkit,
1718
+ format=cast(FormatParam, response.format),
1719
+ activate=False,
1720
+ )
1721
+ span_ctx = span_cm.__enter__()
1722
+ if span_ctx.span is None:
1723
+ result = await _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM_ASYNC(
1724
+ self,
1725
+ ctx=ctx,
1726
+ response=response,
1727
+ content=content,
1728
+ )
1729
+ span_cm.__exit__(None, None, None)
1730
+ return result
1731
+
1732
+ try:
1733
+ with otel_trace.use_span(span_ctx.span, end_on_exit=False):
1734
+ result = await _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM_ASYNC(
1735
+ self,
1736
+ ctx=ctx,
1737
+ response=response,
1738
+ content=content,
1739
+ )
1740
+ except Exception as exc:
1741
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1742
+ raise
1743
+
1744
+ record_dropped_params(span_ctx.span, span_ctx.dropped_params)
1745
+
1746
+ try:
1747
+ _attach_async_stream_span_handlers(
1748
+ response=cast(
1749
+ "AsyncContextStreamResponse[Any, FormattableT | None]", result
1750
+ ),
1751
+ span_cm=span_cm,
1752
+ span=span_ctx.span,
1753
+ request_messages=messages,
1754
+ )
1755
+ except Exception as exc: # pragma: no cover
1756
+ span_cm.__exit__(type(exc), exc, exc.__traceback__)
1757
+ raise
1758
+
1759
+ return result
1760
+
1761
+
1762
+ def wrap_model_context_resume_stream_async() -> None:
1763
+ """Returns None. Replaces `Model.context_resume_stream_async` with the instrumented wrapper."""
1764
+ global _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED
1765
+ if _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED:
1766
+ return
1767
+ Model.context_resume_stream_async = _instrumented_model_context_resume_stream_async
1768
+ _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED = True
1769
+
1770
+
1771
+ def unwrap_model_context_resume_stream_async() -> None:
1772
+ """Returns None. Restores the original `Model.context_resume_stream_async` implementation."""
1773
+ global _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED
1774
+ if not _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED:
1775
+ return
1776
+ Model.context_resume_stream_async = _ORIGINAL_MODEL_CONTEXT_RESUME_STREAM_ASYNC
1777
+ _MODEL_CONTEXT_RESUME_STREAM_ASYNC_WRAPPED = False