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,289 @@
1
+ """OpenAI Responses response decoding."""
2
+
3
+ from typing import Any, Literal
4
+
5
+ from openai import AsyncStream, Stream
6
+ from openai.types import responses as openai_types
7
+ from openai.types.responses.response_stream_event import ResponseStreamEvent
8
+
9
+ from .....content import (
10
+ AssistantContentPart,
11
+ Text,
12
+ TextChunk,
13
+ TextEndChunk,
14
+ TextStartChunk,
15
+ Thought,
16
+ ThoughtChunk,
17
+ ThoughtEndChunk,
18
+ ThoughtStartChunk,
19
+ ToolCall,
20
+ ToolCallChunk,
21
+ ToolCallEndChunk,
22
+ ToolCallStartChunk,
23
+ )
24
+ from .....messages import AssistantMessage
25
+ from .....responses import (
26
+ AsyncChunkIterator,
27
+ ChunkIterator,
28
+ FinishReason,
29
+ FinishReasonChunk,
30
+ ProviderToolUsage,
31
+ RawMessageChunk,
32
+ RawStreamEventChunk,
33
+ Usage,
34
+ UsageDeltaChunk,
35
+ )
36
+ from ...model_id import OpenAIModelId, model_name
37
+
38
+ INCOMPLETE_DETAILS_TO_FINISH_REASON = {
39
+ "max_output_tokens": FinishReason.MAX_TOKENS,
40
+ "content_filter": FinishReason.REFUSAL,
41
+ }
42
+
43
+
44
+ def _extract_tool_usage(
45
+ output: list[openai_types.ResponseOutputItem],
46
+ ) -> list[ProviderToolUsage] | None:
47
+ """Extract provider tool usage from OpenAI Responses output."""
48
+ web_search_count = sum(1 for item in output if item.type == "web_search_call")
49
+
50
+ if web_search_count == 0:
51
+ return None
52
+
53
+ return [ProviderToolUsage(name="web_search", call_count=web_search_count)]
54
+
55
+
56
+ def _decode_usage(
57
+ usage: openai_types.ResponseUsage | None,
58
+ output: list[openai_types.ResponseOutputItem] | None = None,
59
+ ) -> Usage | None:
60
+ """Convert OpenAI ResponseUsage to Mirascope Usage."""
61
+ if usage is None: # pragma: no cover
62
+ return None
63
+
64
+ return Usage(
65
+ input_tokens=usage.input_tokens,
66
+ output_tokens=usage.output_tokens,
67
+ cache_read_tokens=(
68
+ usage.input_tokens_details.cached_tokens
69
+ if usage.input_tokens_details
70
+ else None
71
+ )
72
+ or 0,
73
+ cache_write_tokens=0,
74
+ reasoning_tokens=(
75
+ usage.output_tokens_details.reasoning_tokens
76
+ if usage.output_tokens_details
77
+ else None
78
+ )
79
+ or 0,
80
+ provider_tool_usage=_extract_tool_usage(output) if output else None,
81
+ raw=usage,
82
+ )
83
+
84
+
85
+ def _serialize_output_item(
86
+ item: openai_types.ResponseOutputItem,
87
+ ) -> dict[str, Any]:
88
+ """Returns the item serialized as a dictionary."""
89
+ return {key: value for key, value in item.model_dump().items() if value is not None}
90
+
91
+
92
+ def decode_response(
93
+ response: openai_types.Response,
94
+ model_id: OpenAIModelId,
95
+ provider_id: str,
96
+ *,
97
+ include_thoughts: bool,
98
+ ) -> tuple[AssistantMessage, FinishReason | None, Usage | None]:
99
+ """Convert OpenAI Responses Response to mirascope AssistantMessage and usage."""
100
+ parts: list[AssistantContentPart] = []
101
+ finish_reason: FinishReason | None = None
102
+ refused = False
103
+
104
+ for output_item in response.output:
105
+ if output_item.type == "message":
106
+ for content in output_item.content:
107
+ if content.type == "output_text":
108
+ parts.append(Text(text=content.text))
109
+ elif content.type == "refusal":
110
+ parts.append(Text(text=content.refusal))
111
+ refused = True
112
+ elif output_item.type == "function_call":
113
+ parts.append(
114
+ ToolCall(
115
+ id=output_item.call_id,
116
+ name=output_item.name,
117
+ args=output_item.arguments,
118
+ )
119
+ )
120
+ elif output_item.type == "reasoning":
121
+ for summary_part in output_item.summary:
122
+ if summary_part.type == "summary_text":
123
+ parts.append(Thought(thought=summary_part.text))
124
+ if output_item.content: # pragma: no cover
125
+ # TODO: Add test case covering this
126
+ # (Likely their open-source models output reasoning_text rather than summaries)
127
+ for reasoning_content in output_item.content:
128
+ if reasoning_content.type == "reasoning_text":
129
+ parts.append(Thought(thought=reasoning_content.text))
130
+ elif output_item.type == "web_search_call":
131
+ pass # Skip, preserved in raw_message
132
+ else:
133
+ raise NotImplementedError(f"Unsupported output item: {output_item.type}")
134
+
135
+ if not include_thoughts:
136
+ parts = [part for part in parts if part.type != "thought"]
137
+
138
+ if refused:
139
+ finish_reason = FinishReason.REFUSAL
140
+ elif details := response.incomplete_details:
141
+ finish_reason = INCOMPLETE_DETAILS_TO_FINISH_REASON.get(details.reason or "")
142
+
143
+ assistant_message = AssistantMessage(
144
+ content=parts,
145
+ provider_id=provider_id,
146
+ model_id=model_id,
147
+ provider_model_name=model_name(model_id, "responses"),
148
+ raw_message=[
149
+ _serialize_output_item(output_item) for output_item in response.output
150
+ ],
151
+ )
152
+
153
+ usage = _decode_usage(response.usage, response.output)
154
+ return assistant_message, finish_reason, usage
155
+
156
+
157
+ class _OpenAIResponsesChunkProcessor:
158
+ """Processes OpenAI Responses streaming events and maintains state across chunks."""
159
+
160
+ def __init__(self, *, include_thoughts: bool) -> None:
161
+ self.current_content_type: Literal["text", "tool_call", "thought"] | None = None
162
+ self.refusal_encountered = False
163
+ self.include_thoughts = include_thoughts
164
+ self.web_search_count = 0
165
+
166
+ def process_chunk(self, event: ResponseStreamEvent) -> ChunkIterator:
167
+ """Process a single OpenAI Responses stream event and yield the appropriate content chunks."""
168
+ yield RawStreamEventChunk(raw_stream_event=event)
169
+
170
+ if hasattr(event, "type"):
171
+ if event.type == "response.output_text.delta":
172
+ if not self.current_content_type:
173
+ yield TextStartChunk()
174
+ self.current_content_type = "text"
175
+ yield TextChunk(delta=event.delta)
176
+ elif event.type == "response.output_text.done":
177
+ yield TextEndChunk()
178
+ self.current_content_type = None
179
+ if event.type == "response.refusal.delta":
180
+ if not self.current_content_type:
181
+ yield TextStartChunk()
182
+ self.current_content_type = "text"
183
+ yield TextChunk(delta=event.delta)
184
+ elif event.type == "response.refusal.done":
185
+ yield TextEndChunk()
186
+ self.refusal_encountered = True
187
+ self.current_content_type = None
188
+ elif event.type == "response.output_item.added":
189
+ item = event.item
190
+ if item.type == "function_call":
191
+ self.current_tool_call_id = item.call_id
192
+ self.current_tool_call_name = item.name
193
+ yield ToolCallStartChunk(
194
+ id=item.call_id,
195
+ name=item.name,
196
+ )
197
+ self.current_content_type = "tool_call"
198
+ elif item.type == "web_search_call":
199
+ self.web_search_count += 1
200
+ elif event.type == "response.function_call_arguments.delta":
201
+ yield ToolCallChunk(id=self.current_tool_call_id, delta=event.delta)
202
+ elif event.type == "response.function_call_arguments.done":
203
+ yield ToolCallEndChunk(id=self.current_tool_call_id)
204
+ self.current_content_type = None
205
+ elif (
206
+ event.type == "response.reasoning_text.delta"
207
+ or event.type == "response.reasoning_summary_text.delta"
208
+ ):
209
+ if not self.current_content_type:
210
+ if self.include_thoughts:
211
+ yield ThoughtStartChunk()
212
+ self.current_content_type = "thought"
213
+ if self.include_thoughts:
214
+ yield ThoughtChunk(delta=event.delta)
215
+ elif (
216
+ event.type == "response.reasoning_summary_text.done"
217
+ or event.type == "response.reasoning_text.done"
218
+ ):
219
+ if self.include_thoughts:
220
+ yield ThoughtEndChunk()
221
+ self.current_content_type = None
222
+ elif event.type == "response.incomplete":
223
+ details = event.response.incomplete_details
224
+ reason = (details and details.reason) or ""
225
+ finish_reason = INCOMPLETE_DETAILS_TO_FINISH_REASON.get(reason)
226
+ if finish_reason:
227
+ yield FinishReasonChunk(finish_reason=finish_reason)
228
+ elif event.type == "response.completed":
229
+ yield RawMessageChunk(
230
+ raw_message=[
231
+ _serialize_output_item(item) for item in event.response.output
232
+ ]
233
+ )
234
+ if self.refusal_encountered:
235
+ yield FinishReasonChunk(finish_reason=FinishReason.REFUSAL)
236
+
237
+ # Emit usage delta if present
238
+ if event.response.usage:
239
+ usage = event.response.usage
240
+ provider_tool_usage = (
241
+ [
242
+ ProviderToolUsage(
243
+ name="web_search", call_count=self.web_search_count
244
+ )
245
+ ]
246
+ if self.web_search_count > 0
247
+ else None
248
+ )
249
+ yield UsageDeltaChunk(
250
+ input_tokens=usage.input_tokens,
251
+ output_tokens=usage.output_tokens,
252
+ cache_read_tokens=(
253
+ usage.input_tokens_details.cached_tokens
254
+ if usage.input_tokens_details
255
+ else None
256
+ )
257
+ or 0,
258
+ cache_write_tokens=0,
259
+ reasoning_tokens=(
260
+ usage.output_tokens_details.reasoning_tokens
261
+ if usage.output_tokens_details
262
+ else None
263
+ )
264
+ or 0,
265
+ provider_tool_usage=provider_tool_usage,
266
+ )
267
+
268
+
269
+ def decode_stream(
270
+ openai_stream: Stream[ResponseStreamEvent],
271
+ *,
272
+ include_thoughts: bool,
273
+ ) -> ChunkIterator:
274
+ """Returns a ChunkIterator converted from an OpenAI Stream[ResponseStreamEvent]"""
275
+ processor = _OpenAIResponsesChunkProcessor(include_thoughts=include_thoughts)
276
+ for event in openai_stream:
277
+ yield from processor.process_chunk(event)
278
+
279
+
280
+ async def decode_async_stream(
281
+ openai_stream: AsyncStream[ResponseStreamEvent],
282
+ *,
283
+ include_thoughts: bool,
284
+ ) -> AsyncChunkIterator:
285
+ """Returns an AsyncChunkIterator converted from an OpenAI AsyncStream[ResponseStreamEvent]"""
286
+ processor = _OpenAIResponsesChunkProcessor(include_thoughts=include_thoughts)
287
+ async for event in openai_stream:
288
+ for item in processor.process_chunk(event):
289
+ yield item
@@ -0,0 +1,399 @@
1
+ """OpenAI Responses message encoding and request preparation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+ from typing import TYPE_CHECKING, TypedDict, cast
7
+
8
+ from openai import Omit
9
+ from openai.types.responses import (
10
+ FunctionToolParam,
11
+ ResponseFormatTextJSONSchemaConfigParam,
12
+ ResponseFunctionToolCallParam,
13
+ ResponseInputContentParam,
14
+ ResponseInputItemParam,
15
+ ResponseInputParam,
16
+ ResponseInputTextParam,
17
+ ResponseTextConfigParam,
18
+ ToolChoiceAllowedParam,
19
+ ToolChoiceFunctionParam,
20
+ ToolParam,
21
+ WebSearchToolParam,
22
+ response_create_params,
23
+ )
24
+ from openai.types.responses.easy_input_message_param import EasyInputMessageParam
25
+ from openai.types.responses.response_input_image_param import ResponseInputImageParam
26
+ from openai.types.responses.response_input_param import (
27
+ FunctionCallOutput,
28
+ Message as ResponseInputMessageParam,
29
+ )
30
+ from openai.types.shared_params import Reasoning, ReasoningEffort
31
+ from openai.types.shared_params.response_format_json_object import (
32
+ ResponseFormatJSONObject,
33
+ )
34
+ from openai.types.shared_params.responses_model import ResponsesModel
35
+
36
+ from .....exceptions import FeatureNotSupportedError
37
+ from .....formatting import (
38
+ Format,
39
+ FormatSpec,
40
+ FormattableT,
41
+ resolve_format,
42
+ )
43
+ from .....messages import AssistantMessage, Message, UserMessage
44
+ from .....tools import (
45
+ FORMAT_TOOL_NAME,
46
+ AnyToolSchema,
47
+ BaseToolkit,
48
+ ProviderTool,
49
+ WebSearchTool,
50
+ )
51
+ from ....base import _utils as _base_utils
52
+ from ...model_id import OpenAIModelId, model_name
53
+ from ...model_info import (
54
+ MODELS_WITHOUT_JSON_OBJECT_SUPPORT,
55
+ MODELS_WITHOUT_JSON_SCHEMA_SUPPORT,
56
+ NON_REASONING_MODELS,
57
+ )
58
+
59
+ if TYPE_CHECKING:
60
+ from .....models import Params, ThinkingLevel
61
+
62
+ # Thinking level to a float multiplier % of max tokens
63
+ THINKING_LEVEL_TO_EFFORT: dict[ThinkingLevel, ReasoningEffort] = {
64
+ "default": "medium",
65
+ "none": "none",
66
+ "minimal": "minimal",
67
+ "low": "low",
68
+ "medium": "medium",
69
+ "high": "high",
70
+ "max": "xhigh",
71
+ }
72
+
73
+
74
+ class ResponseCreateKwargs(TypedDict, total=False):
75
+ """Kwargs to the OpenAI `client.responses.create` method."""
76
+
77
+ model: ResponsesModel
78
+ input: str | ResponseInputParam
79
+ instructions: str
80
+ temperature: float
81
+ max_output_tokens: int
82
+ top_p: float
83
+ tools: list[ToolParam] | Omit
84
+ tool_choice: response_create_params.ToolChoice | Omit
85
+ text: ResponseTextConfigParam
86
+ reasoning: Reasoning | Omit
87
+
88
+
89
+ def _encode_user_message(
90
+ message: UserMessage,
91
+ ) -> ResponseInputParam:
92
+ if len(message.content) == 1 and (first := message.content[0]).type == "text":
93
+ return [EasyInputMessageParam(content=first.text, role="user")]
94
+
95
+ current_content: list[ResponseInputContentParam] = []
96
+ result: ResponseInputParam = []
97
+
98
+ def flush_message_content() -> None:
99
+ nonlocal current_content
100
+ if current_content:
101
+ result.append(
102
+ ResponseInputMessageParam(
103
+ content=current_content, role="user", type="message"
104
+ )
105
+ )
106
+ current_content = []
107
+
108
+ for part in message.content:
109
+ if part.type == "text":
110
+ current_content.append(
111
+ ResponseInputTextParam(text=part.text, type="input_text")
112
+ )
113
+ elif part.type == "image":
114
+ image_url = (
115
+ part.source.url
116
+ if part.source.type == "url_image_source"
117
+ else f"data:{part.source.mime_type};base64,{part.source.data}"
118
+ )
119
+
120
+ current_content.append(
121
+ ResponseInputImageParam(
122
+ image_url=image_url, detail="auto", type="input_image"
123
+ )
124
+ )
125
+ elif part.type == "tool_output":
126
+ flush_message_content()
127
+ result.append(
128
+ FunctionCallOutput(
129
+ call_id=part.id,
130
+ output=str(part.result),
131
+ type="function_call_output",
132
+ )
133
+ )
134
+ elif part.type == "audio":
135
+ raise FeatureNotSupportedError(
136
+ "audio input",
137
+ "openai",
138
+ message='provider "openai" does not support audio inputs when using :responses api. Try appending :completions to your model instead.',
139
+ )
140
+ else:
141
+ raise NotImplementedError(
142
+ f"Unsupported user content part type: {part.type}"
143
+ )
144
+ flush_message_content()
145
+
146
+ return result
147
+
148
+
149
+ def _encode_assistant_message(
150
+ message: AssistantMessage, encode_thoughts: bool
151
+ ) -> ResponseInputParam:
152
+ result: ResponseInputParam = []
153
+
154
+ # Note: OpenAI does not provide any way to encode multiplie pieces of assistant-generated
155
+ # text as adjacent content within the same Message, except as part of
156
+ # ResponseOutputMessageParam which requires OpenAI-provided `id` and `status` on the message,
157
+ # and `annotations` and `logprobs` on the output text.
158
+ # Rather than generating a fake or nonexistent fields and triggering potentially undefined
159
+ # server-side behavior, we use `EasyInputMessageParam` for assistant generated text,
160
+ # with the caveat that assistant messages containing multiple text parts will be encoded
161
+ # as though they are separate messages.
162
+ # (It would seem as though the `Message` class in `response_input_param.py` would be suitable,
163
+ # especially as it supports the "assistant" role; however attempting to use it triggers a server
164
+ # error when text of type input_text is passed as part of an assistant message.)
165
+ for part in message.content:
166
+ if part.type == "text":
167
+ result.append(EasyInputMessageParam(content=part.text, role="assistant"))
168
+ elif part.type == "thought":
169
+ if encode_thoughts:
170
+ result.append(
171
+ EasyInputMessageParam(
172
+ content="**Thinking:** " + part.thought, role="assistant"
173
+ )
174
+ )
175
+ elif part.type == "tool_call":
176
+ result.append(
177
+ ResponseFunctionToolCallParam(
178
+ call_id=part.id,
179
+ name=part.name,
180
+ arguments=part.args,
181
+ type="function_call",
182
+ )
183
+ )
184
+ else:
185
+ raise NotImplementedError(
186
+ f"Unsupported assistant content part type: {part.type}"
187
+ )
188
+
189
+ return result
190
+
191
+
192
+ def _encode_message(
193
+ message: Message, model_id: OpenAIModelId, encode_thoughts: bool
194
+ ) -> ResponseInputParam:
195
+ """Convert a Mirascope Message to OpenAI Responses input items.
196
+
197
+ Returns a list because tool calls and tool outputs become separate input items
198
+ in the Responses API, not part of message content.
199
+ """
200
+
201
+ if message.role == "system":
202
+ # Responses API allows multiple "developer" messages, so rather than using the
203
+ # instructions field, we convert system messages as we find them.
204
+ # Unlike other LLM APIs, the system message does not need to be the first message.
205
+ return [EasyInputMessageParam(role="developer", content=message.content.text)]
206
+
207
+ if (
208
+ message.role == "assistant"
209
+ and message.provider_id in ("openai", "openai:responses")
210
+ and message.provider_model_name
211
+ == model_name(model_id=model_id, api_mode="responses")
212
+ and message.raw_message
213
+ and not encode_thoughts
214
+ ):
215
+ return cast(ResponseInputParam, message.raw_message)
216
+
217
+ if message.role == "assistant":
218
+ return _encode_assistant_message(message, encode_thoughts)
219
+ else:
220
+ return _encode_user_message(message)
221
+
222
+
223
+ def _convert_tool_to_tool_param(
224
+ tool: AnyToolSchema | ProviderTool,
225
+ ) -> ToolParam:
226
+ """Convert a Mirascope ToolSchema to OpenAI Responses ToolParam."""
227
+ if isinstance(tool, WebSearchTool):
228
+ return WebSearchToolParam(type="web_search")
229
+ if isinstance(tool, ProviderTool):
230
+ raise FeatureNotSupportedError(
231
+ f"Provider tool {tool.name}", provider_id="openai:responses"
232
+ )
233
+ schema_dict = tool.parameters.model_dump(by_alias=True, exclude_none=True)
234
+ schema_dict["type"] = "object"
235
+ _base_utils.ensure_additional_properties_false(schema_dict)
236
+ strict = True if tool.strict is None else tool.strict
237
+ if strict:
238
+ _base_utils.ensure_all_properties_required(schema_dict)
239
+
240
+ return FunctionToolParam(
241
+ type="function",
242
+ name=tool.name,
243
+ description=tool.description,
244
+ parameters=schema_dict,
245
+ strict=strict,
246
+ )
247
+
248
+
249
+ def _create_strict_response_format(
250
+ format: Format[FormattableT],
251
+ ) -> ResponseFormatTextJSONSchemaConfigParam:
252
+ """Create OpenAI Responses strict response format from a Mirascope Format.
253
+
254
+ Args:
255
+ format: The `Format` instance containing schema and metadata
256
+
257
+ Returns:
258
+ ResponseFormatTextJSONSchemaConfigParam for strict structured outputs
259
+ """
260
+ schema = format.schema.copy()
261
+ _base_utils.ensure_additional_properties_false(schema)
262
+
263
+ response_format: ResponseFormatTextJSONSchemaConfigParam = {
264
+ "type": "json_schema",
265
+ "name": format.name,
266
+ "schema": schema,
267
+ }
268
+ if format.description:
269
+ response_format["description"] = format.description
270
+ response_format["strict"] = True
271
+
272
+ return response_format
273
+
274
+
275
+ def _compute_reasoning(
276
+ level: ThinkingLevel,
277
+ include_thoughts: bool,
278
+ ) -> Reasoning:
279
+ """Compute the OpenAI `Reasoning` config based on ThinkingConfig.
280
+
281
+ Args:
282
+ level: The thinking level
283
+ include_thoughts: Whether to include summary (True/False for auto)
284
+
285
+ Returns:
286
+ OpenAI Reasoning configuration
287
+ """
288
+ reasoning: Reasoning = {"effort": THINKING_LEVEL_TO_EFFORT.get(level) or "medium"}
289
+
290
+ if include_thoughts:
291
+ reasoning["summary"] = "auto"
292
+
293
+ return reasoning
294
+
295
+
296
+ def encode_request(
297
+ *,
298
+ model_id: OpenAIModelId,
299
+ messages: Sequence[Message],
300
+ tools: BaseToolkit[AnyToolSchema],
301
+ format: FormatSpec[FormattableT] | None,
302
+ params: Params,
303
+ ) -> tuple[Sequence[Message], Format[FormattableT] | None, ResponseCreateKwargs]:
304
+ """Prepares a request for the `OpenAI.responses.create` method."""
305
+ if model_id.endswith(":completions"):
306
+ raise FeatureNotSupportedError(
307
+ feature="completions API",
308
+ provider_id="openai:responses",
309
+ model_id=model_id,
310
+ message=f"Cannot use completions model with responses client: {model_id}",
311
+ )
312
+
313
+ base_model_name = model_name(model_id, None)
314
+
315
+ kwargs: ResponseCreateKwargs = ResponseCreateKwargs(
316
+ {
317
+ "model": base_model_name,
318
+ }
319
+ )
320
+ encode_thoughts = False
321
+
322
+ with _base_utils.ensure_all_params_accessed(
323
+ params=params,
324
+ provider_id="openai",
325
+ unsupported_params=["top_k", "seed", "stop_sequences"],
326
+ ) as param_accessor:
327
+ if param_accessor.temperature is not None:
328
+ kwargs["temperature"] = param_accessor.temperature
329
+ if param_accessor.max_tokens is not None:
330
+ kwargs["max_output_tokens"] = param_accessor.max_tokens
331
+ if param_accessor.top_p is not None:
332
+ kwargs["top_p"] = param_accessor.top_p
333
+ if param_accessor.thinking is not None:
334
+ thinking_config = param_accessor.thinking
335
+ if base_model_name in NON_REASONING_MODELS:
336
+ param_accessor.emit_warning_for_unused_param(
337
+ "thinking", thinking_config, "openai", model_id
338
+ )
339
+ else:
340
+ # Assume model supports reasoning unless explicitly listed as non-reasoning
341
+ # This ensures new reasoning models work immediately without code updates
342
+ level = thinking_config.get("level")
343
+ include_thoughts = thinking_config.get("include_thoughts", False)
344
+ kwargs["reasoning"] = _compute_reasoning(level, include_thoughts)
345
+
346
+ # Handle encode_thoughts_as_text from ThinkingConfig
347
+ if thinking_config.get("encode_thoughts_as_text"):
348
+ encode_thoughts = True
349
+
350
+ openai_tools = [_convert_tool_to_tool_param(tool) for tool in tools.tools]
351
+
352
+ model_supports_strict = model_id not in MODELS_WITHOUT_JSON_SCHEMA_SUPPORT
353
+ default_mode = "strict" if model_supports_strict else "tool"
354
+
355
+ format = resolve_format(format, default_mode=default_mode)
356
+ if format is not None:
357
+ if format.mode == "strict":
358
+ kwargs["text"] = {"format": _create_strict_response_format(format)}
359
+ elif format.mode == "tool":
360
+ format_tool_schema = format.create_tool_schema()
361
+ openai_tools.append(_convert_tool_to_tool_param(format_tool_schema))
362
+ if tools.tools:
363
+ # Only include function tools in tool_choice (filter out web search, etc.)
364
+ function_tools = cast(
365
+ list[FunctionToolParam],
366
+ [t for t in openai_tools if t.get("type") == "function"],
367
+ )
368
+ kwargs["tool_choice"] = ToolChoiceAllowedParam(
369
+ type="allowed_tools",
370
+ mode="required",
371
+ tools=[
372
+ {"type": "function", "name": tool["name"]}
373
+ for tool in function_tools
374
+ ],
375
+ )
376
+ else:
377
+ kwargs["tool_choice"] = ToolChoiceFunctionParam(
378
+ type="function",
379
+ name=FORMAT_TOOL_NAME,
380
+ )
381
+ elif (
382
+ format.mode == "json" and model_id not in MODELS_WITHOUT_JSON_OBJECT_SUPPORT
383
+ ):
384
+ kwargs["text"] = {"format": ResponseFormatJSONObject(type="json_object")}
385
+
386
+ if format.formatting_instructions:
387
+ messages = _base_utils.add_system_instructions(
388
+ messages, format.formatting_instructions
389
+ )
390
+
391
+ encoded_messages: list[ResponseInputItemParam] = []
392
+ for message in messages:
393
+ encoded_messages.extend(_encode_message(message, model_id, encode_thoughts))
394
+ kwargs["input"] = encoded_messages
395
+
396
+ if openai_tools:
397
+ kwargs["tools"] = openai_tools
398
+
399
+ return messages, format, kwargs