mirascope 1.25.7__py3-none-any.whl → 2.0.0a0__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 (474) hide show
  1. mirascope/__init__.py +3 -59
  2. mirascope/graphs/__init__.py +22 -0
  3. mirascope/{experimental/graphs → graphs}/finite_state_machine.py +70 -159
  4. mirascope/llm/__init__.py +206 -16
  5. mirascope/llm/agents/__init__.py +15 -0
  6. mirascope/llm/agents/agent.py +97 -0
  7. mirascope/llm/agents/agent_template.py +45 -0
  8. mirascope/llm/agents/decorator.py +176 -0
  9. mirascope/llm/calls/__init__.py +16 -0
  10. mirascope/llm/calls/base_call.py +33 -0
  11. mirascope/llm/calls/calls.py +315 -0
  12. mirascope/llm/calls/decorator.py +255 -0
  13. mirascope/llm/clients/__init__.py +34 -0
  14. mirascope/llm/clients/anthropic/__init__.py +11 -0
  15. mirascope/llm/clients/anthropic/_utils/__init__.py +13 -0
  16. mirascope/llm/clients/anthropic/_utils/decode.py +244 -0
  17. mirascope/llm/clients/anthropic/_utils/encode.py +243 -0
  18. mirascope/llm/clients/anthropic/clients.py +819 -0
  19. mirascope/llm/clients/anthropic/model_ids.py +8 -0
  20. mirascope/llm/clients/base/__init__.py +15 -0
  21. mirascope/llm/clients/base/_utils.py +192 -0
  22. mirascope/llm/clients/base/client.py +1256 -0
  23. mirascope/llm/clients/base/kwargs.py +12 -0
  24. mirascope/llm/clients/base/params.py +93 -0
  25. mirascope/llm/clients/google/__init__.py +6 -0
  26. mirascope/llm/clients/google/_utils/__init__.py +13 -0
  27. mirascope/llm/clients/google/_utils/decode.py +231 -0
  28. mirascope/llm/clients/google/_utils/encode.py +279 -0
  29. mirascope/llm/clients/google/clients.py +853 -0
  30. mirascope/llm/clients/google/message.py +7 -0
  31. mirascope/llm/clients/google/model_ids.py +15 -0
  32. mirascope/llm/clients/openai/__init__.py +25 -0
  33. mirascope/llm/clients/openai/completions/__init__.py +9 -0
  34. mirascope/llm/clients/openai/completions/_utils/__init__.py +13 -0
  35. mirascope/llm/clients/openai/completions/_utils/decode.py +187 -0
  36. mirascope/llm/clients/openai/completions/_utils/encode.py +358 -0
  37. mirascope/llm/clients/openai/completions/_utils/model_features.py +81 -0
  38. mirascope/llm/clients/openai/completions/clients.py +833 -0
  39. mirascope/llm/clients/openai/completions/model_ids.py +8 -0
  40. mirascope/llm/clients/openai/responses/__init__.py +9 -0
  41. mirascope/llm/clients/openai/responses/_utils/__init__.py +13 -0
  42. mirascope/llm/clients/openai/responses/_utils/decode.py +194 -0
  43. mirascope/llm/clients/openai/responses/_utils/encode.py +333 -0
  44. mirascope/llm/clients/openai/responses/_utils/model_features.py +87 -0
  45. mirascope/llm/clients/openai/responses/clients.py +832 -0
  46. mirascope/llm/clients/openai/responses/model_ids.py +8 -0
  47. mirascope/llm/clients/openai/shared/__init__.py +7 -0
  48. mirascope/llm/clients/openai/shared/_utils.py +55 -0
  49. mirascope/llm/clients/providers.py +175 -0
  50. mirascope/llm/content/__init__.py +70 -0
  51. mirascope/llm/content/audio.py +173 -0
  52. mirascope/llm/content/document.py +94 -0
  53. mirascope/llm/content/image.py +206 -0
  54. mirascope/llm/content/text.py +47 -0
  55. mirascope/llm/content/thought.py +58 -0
  56. mirascope/llm/content/tool_call.py +63 -0
  57. mirascope/llm/content/tool_output.py +26 -0
  58. mirascope/llm/context/__init__.py +6 -0
  59. mirascope/llm/context/_utils.py +28 -0
  60. mirascope/llm/context/context.py +24 -0
  61. mirascope/llm/exceptions.py +105 -0
  62. mirascope/llm/formatting/__init__.py +22 -0
  63. mirascope/llm/formatting/_utils.py +74 -0
  64. mirascope/llm/formatting/format.py +104 -0
  65. mirascope/llm/formatting/from_call_args.py +30 -0
  66. mirascope/llm/formatting/partial.py +58 -0
  67. mirascope/llm/formatting/types.py +109 -0
  68. mirascope/llm/mcp/__init__.py +5 -0
  69. mirascope/llm/mcp/client.py +118 -0
  70. mirascope/llm/messages/__init__.py +32 -0
  71. mirascope/llm/messages/message.py +182 -0
  72. mirascope/llm/models/__init__.py +16 -0
  73. mirascope/llm/models/models.py +1243 -0
  74. mirascope/llm/prompts/__init__.py +33 -0
  75. mirascope/llm/prompts/_utils.py +60 -0
  76. mirascope/llm/prompts/decorator.py +286 -0
  77. mirascope/llm/prompts/protocols.py +99 -0
  78. mirascope/llm/responses/__init__.py +57 -0
  79. mirascope/llm/responses/_utils.py +56 -0
  80. mirascope/llm/responses/base_response.py +91 -0
  81. mirascope/llm/responses/base_stream_response.py +697 -0
  82. mirascope/llm/responses/finish_reason.py +27 -0
  83. mirascope/llm/responses/response.py +345 -0
  84. mirascope/llm/responses/root_response.py +177 -0
  85. mirascope/llm/responses/stream_response.py +572 -0
  86. mirascope/llm/responses/streams.py +363 -0
  87. mirascope/llm/tools/__init__.py +40 -0
  88. mirascope/llm/tools/_utils.py +25 -0
  89. mirascope/llm/tools/decorator.py +175 -0
  90. mirascope/llm/tools/protocols.py +96 -0
  91. mirascope/llm/tools/tool_schema.py +246 -0
  92. mirascope/llm/tools/toolkit.py +152 -0
  93. mirascope/llm/tools/tools.py +169 -0
  94. mirascope/llm/types/__init__.py +22 -0
  95. mirascope/llm/types/dataclass.py +9 -0
  96. mirascope/llm/types/jsonable.py +44 -0
  97. mirascope/llm/types/type_vars.py +19 -0
  98. mirascope-2.0.0a0.dist-info/METADATA +117 -0
  99. mirascope-2.0.0a0.dist-info/RECORD +101 -0
  100. mirascope/beta/__init__.py +0 -3
  101. mirascope/beta/openai/__init__.py +0 -17
  102. mirascope/beta/openai/realtime/__init__.py +0 -13
  103. mirascope/beta/openai/realtime/_utils/__init__.py +0 -3
  104. mirascope/beta/openai/realtime/_utils/_audio.py +0 -74
  105. mirascope/beta/openai/realtime/_utils/_protocols.py +0 -50
  106. mirascope/beta/openai/realtime/realtime.py +0 -500
  107. mirascope/beta/openai/realtime/recording.py +0 -98
  108. mirascope/beta/openai/realtime/tool.py +0 -113
  109. mirascope/beta/rag/__init__.py +0 -24
  110. mirascope/beta/rag/base/__init__.py +0 -22
  111. mirascope/beta/rag/base/chunkers/__init__.py +0 -2
  112. mirascope/beta/rag/base/chunkers/base_chunker.py +0 -37
  113. mirascope/beta/rag/base/chunkers/text_chunker.py +0 -33
  114. mirascope/beta/rag/base/config.py +0 -8
  115. mirascope/beta/rag/base/document.py +0 -11
  116. mirascope/beta/rag/base/embedders.py +0 -35
  117. mirascope/beta/rag/base/embedding_params.py +0 -18
  118. mirascope/beta/rag/base/embedding_response.py +0 -30
  119. mirascope/beta/rag/base/query_results.py +0 -7
  120. mirascope/beta/rag/base/vectorstore_params.py +0 -18
  121. mirascope/beta/rag/base/vectorstores.py +0 -37
  122. mirascope/beta/rag/chroma/__init__.py +0 -11
  123. mirascope/beta/rag/chroma/types.py +0 -62
  124. mirascope/beta/rag/chroma/vectorstores.py +0 -121
  125. mirascope/beta/rag/cohere/__init__.py +0 -11
  126. mirascope/beta/rag/cohere/embedders.py +0 -87
  127. mirascope/beta/rag/cohere/embedding_params.py +0 -29
  128. mirascope/beta/rag/cohere/embedding_response.py +0 -29
  129. mirascope/beta/rag/cohere/py.typed +0 -0
  130. mirascope/beta/rag/openai/__init__.py +0 -11
  131. mirascope/beta/rag/openai/embedders.py +0 -144
  132. mirascope/beta/rag/openai/embedding_params.py +0 -18
  133. mirascope/beta/rag/openai/embedding_response.py +0 -14
  134. mirascope/beta/rag/openai/py.typed +0 -0
  135. mirascope/beta/rag/pinecone/__init__.py +0 -19
  136. mirascope/beta/rag/pinecone/types.py +0 -143
  137. mirascope/beta/rag/pinecone/vectorstores.py +0 -148
  138. mirascope/beta/rag/weaviate/__init__.py +0 -6
  139. mirascope/beta/rag/weaviate/types.py +0 -92
  140. mirascope/beta/rag/weaviate/vectorstores.py +0 -103
  141. mirascope/core/__init__.py +0 -109
  142. mirascope/core/anthropic/__init__.py +0 -31
  143. mirascope/core/anthropic/_call.py +0 -67
  144. mirascope/core/anthropic/_call_kwargs.py +0 -13
  145. mirascope/core/anthropic/_thinking.py +0 -70
  146. mirascope/core/anthropic/_utils/__init__.py +0 -16
  147. mirascope/core/anthropic/_utils/_convert_common_call_params.py +0 -25
  148. mirascope/core/anthropic/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -21
  149. mirascope/core/anthropic/_utils/_convert_message_params.py +0 -102
  150. mirascope/core/anthropic/_utils/_get_json_output.py +0 -31
  151. mirascope/core/anthropic/_utils/_handle_stream.py +0 -113
  152. mirascope/core/anthropic/_utils/_message_param_converter.py +0 -154
  153. mirascope/core/anthropic/_utils/_setup_call.py +0 -146
  154. mirascope/core/anthropic/call_params.py +0 -44
  155. mirascope/core/anthropic/call_response.py +0 -226
  156. mirascope/core/anthropic/call_response_chunk.py +0 -152
  157. mirascope/core/anthropic/dynamic_config.py +0 -40
  158. mirascope/core/anthropic/py.typed +0 -0
  159. mirascope/core/anthropic/stream.py +0 -204
  160. mirascope/core/anthropic/tool.py +0 -101
  161. mirascope/core/azure/__init__.py +0 -31
  162. mirascope/core/azure/_call.py +0 -67
  163. mirascope/core/azure/_call_kwargs.py +0 -13
  164. mirascope/core/azure/_utils/__init__.py +0 -14
  165. mirascope/core/azure/_utils/_convert_common_call_params.py +0 -26
  166. mirascope/core/azure/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -21
  167. mirascope/core/azure/_utils/_convert_message_params.py +0 -121
  168. mirascope/core/azure/_utils/_get_credential.py +0 -33
  169. mirascope/core/azure/_utils/_get_json_output.py +0 -27
  170. mirascope/core/azure/_utils/_handle_stream.py +0 -130
  171. mirascope/core/azure/_utils/_message_param_converter.py +0 -117
  172. mirascope/core/azure/_utils/_setup_call.py +0 -183
  173. mirascope/core/azure/call_params.py +0 -59
  174. mirascope/core/azure/call_response.py +0 -215
  175. mirascope/core/azure/call_response_chunk.py +0 -105
  176. mirascope/core/azure/dynamic_config.py +0 -30
  177. mirascope/core/azure/py.typed +0 -0
  178. mirascope/core/azure/stream.py +0 -147
  179. mirascope/core/azure/tool.py +0 -93
  180. mirascope/core/base/__init__.py +0 -86
  181. mirascope/core/base/_call_factory.py +0 -256
  182. mirascope/core/base/_create.py +0 -253
  183. mirascope/core/base/_extract.py +0 -175
  184. mirascope/core/base/_extract_with_tools.py +0 -189
  185. mirascope/core/base/_partial.py +0 -95
  186. mirascope/core/base/_utils/__init__.py +0 -92
  187. mirascope/core/base/_utils/_base_message_param_converter.py +0 -22
  188. mirascope/core/base/_utils/_base_type.py +0 -26
  189. mirascope/core/base/_utils/_convert_base_model_to_base_tool.py +0 -48
  190. mirascope/core/base/_utils/_convert_base_type_to_base_tool.py +0 -24
  191. mirascope/core/base/_utils/_convert_function_to_base_tool.py +0 -139
  192. mirascope/core/base/_utils/_convert_messages_to_message_params.py +0 -178
  193. mirascope/core/base/_utils/_convert_provider_finish_reason_to_finish_reason.py +0 -20
  194. mirascope/core/base/_utils/_default_tool_docstring.py +0 -6
  195. mirascope/core/base/_utils/_extract_tool_return.py +0 -42
  196. mirascope/core/base/_utils/_fn_is_async.py +0 -24
  197. mirascope/core/base/_utils/_format_template.py +0 -32
  198. mirascope/core/base/_utils/_get_audio_type.py +0 -18
  199. mirascope/core/base/_utils/_get_common_usage.py +0 -20
  200. mirascope/core/base/_utils/_get_create_fn_or_async_create_fn.py +0 -137
  201. mirascope/core/base/_utils/_get_document_type.py +0 -7
  202. mirascope/core/base/_utils/_get_dynamic_configuration.py +0 -69
  203. mirascope/core/base/_utils/_get_fields_from_call_args.py +0 -34
  204. mirascope/core/base/_utils/_get_fn_args.py +0 -23
  205. mirascope/core/base/_utils/_get_image_dimensions.py +0 -39
  206. mirascope/core/base/_utils/_get_image_type.py +0 -26
  207. mirascope/core/base/_utils/_get_metadata.py +0 -17
  208. mirascope/core/base/_utils/_get_possible_user_message_param.py +0 -21
  209. mirascope/core/base/_utils/_get_prompt_template.py +0 -28
  210. mirascope/core/base/_utils/_get_template_values.py +0 -51
  211. mirascope/core/base/_utils/_get_template_variables.py +0 -38
  212. mirascope/core/base/_utils/_get_unsupported_tool_config_keys.py +0 -10
  213. mirascope/core/base/_utils/_is_prompt_template.py +0 -24
  214. mirascope/core/base/_utils/_json_mode_content.py +0 -17
  215. mirascope/core/base/_utils/_messages_decorator.py +0 -121
  216. mirascope/core/base/_utils/_parse_content_template.py +0 -323
  217. mirascope/core/base/_utils/_parse_prompt_messages.py +0 -63
  218. mirascope/core/base/_utils/_pil_image_to_bytes.py +0 -13
  219. mirascope/core/base/_utils/_protocols.py +0 -901
  220. mirascope/core/base/_utils/_setup_call.py +0 -79
  221. mirascope/core/base/_utils/_setup_extract_tool.py +0 -30
  222. mirascope/core/base/call_kwargs.py +0 -13
  223. mirascope/core/base/call_params.py +0 -36
  224. mirascope/core/base/call_response.py +0 -338
  225. mirascope/core/base/call_response_chunk.py +0 -130
  226. mirascope/core/base/dynamic_config.py +0 -82
  227. mirascope/core/base/from_call_args.py +0 -30
  228. mirascope/core/base/merge_decorators.py +0 -59
  229. mirascope/core/base/message_param.py +0 -175
  230. mirascope/core/base/messages.py +0 -116
  231. mirascope/core/base/metadata.py +0 -13
  232. mirascope/core/base/prompt.py +0 -497
  233. mirascope/core/base/response_model_config_dict.py +0 -9
  234. mirascope/core/base/stream.py +0 -479
  235. mirascope/core/base/stream_config.py +0 -11
  236. mirascope/core/base/structured_stream.py +0 -296
  237. mirascope/core/base/tool.py +0 -214
  238. mirascope/core/base/toolkit.py +0 -176
  239. mirascope/core/base/types.py +0 -344
  240. mirascope/core/bedrock/__init__.py +0 -34
  241. mirascope/core/bedrock/_call.py +0 -68
  242. mirascope/core/bedrock/_call_kwargs.py +0 -12
  243. mirascope/core/bedrock/_types.py +0 -104
  244. mirascope/core/bedrock/_utils/__init__.py +0 -14
  245. mirascope/core/bedrock/_utils/_convert_common_call_params.py +0 -39
  246. mirascope/core/bedrock/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
  247. mirascope/core/bedrock/_utils/_convert_message_params.py +0 -111
  248. mirascope/core/bedrock/_utils/_get_json_output.py +0 -30
  249. mirascope/core/bedrock/_utils/_handle_stream.py +0 -104
  250. mirascope/core/bedrock/_utils/_message_param_converter.py +0 -172
  251. mirascope/core/bedrock/_utils/_setup_call.py +0 -258
  252. mirascope/core/bedrock/call_params.py +0 -38
  253. mirascope/core/bedrock/call_response.py +0 -248
  254. mirascope/core/bedrock/call_response_chunk.py +0 -111
  255. mirascope/core/bedrock/dynamic_config.py +0 -37
  256. mirascope/core/bedrock/py.typed +0 -0
  257. mirascope/core/bedrock/stream.py +0 -154
  258. mirascope/core/bedrock/tool.py +0 -100
  259. mirascope/core/cohere/__init__.py +0 -30
  260. mirascope/core/cohere/_call.py +0 -67
  261. mirascope/core/cohere/_call_kwargs.py +0 -11
  262. mirascope/core/cohere/_types.py +0 -20
  263. mirascope/core/cohere/_utils/__init__.py +0 -14
  264. mirascope/core/cohere/_utils/_convert_common_call_params.py +0 -26
  265. mirascope/core/cohere/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -24
  266. mirascope/core/cohere/_utils/_convert_message_params.py +0 -32
  267. mirascope/core/cohere/_utils/_get_json_output.py +0 -30
  268. mirascope/core/cohere/_utils/_handle_stream.py +0 -35
  269. mirascope/core/cohere/_utils/_message_param_converter.py +0 -54
  270. mirascope/core/cohere/_utils/_setup_call.py +0 -150
  271. mirascope/core/cohere/call_params.py +0 -62
  272. mirascope/core/cohere/call_response.py +0 -205
  273. mirascope/core/cohere/call_response_chunk.py +0 -125
  274. mirascope/core/cohere/dynamic_config.py +0 -32
  275. mirascope/core/cohere/py.typed +0 -0
  276. mirascope/core/cohere/stream.py +0 -113
  277. mirascope/core/cohere/tool.py +0 -93
  278. mirascope/core/costs/__init__.py +0 -5
  279. mirascope/core/costs/_anthropic_calculate_cost.py +0 -219
  280. mirascope/core/costs/_azure_calculate_cost.py +0 -11
  281. mirascope/core/costs/_bedrock_calculate_cost.py +0 -15
  282. mirascope/core/costs/_cohere_calculate_cost.py +0 -44
  283. mirascope/core/costs/_gemini_calculate_cost.py +0 -67
  284. mirascope/core/costs/_google_calculate_cost.py +0 -427
  285. mirascope/core/costs/_groq_calculate_cost.py +0 -156
  286. mirascope/core/costs/_litellm_calculate_cost.py +0 -11
  287. mirascope/core/costs/_mistral_calculate_cost.py +0 -64
  288. mirascope/core/costs/_openai_calculate_cost.py +0 -416
  289. mirascope/core/costs/_vertex_calculate_cost.py +0 -67
  290. mirascope/core/costs/_xai_calculate_cost.py +0 -104
  291. mirascope/core/costs/calculate_cost.py +0 -86
  292. mirascope/core/gemini/__init__.py +0 -40
  293. mirascope/core/gemini/_call.py +0 -67
  294. mirascope/core/gemini/_call_kwargs.py +0 -12
  295. mirascope/core/gemini/_utils/__init__.py +0 -14
  296. mirascope/core/gemini/_utils/_convert_common_call_params.py +0 -39
  297. mirascope/core/gemini/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
  298. mirascope/core/gemini/_utils/_convert_message_params.py +0 -156
  299. mirascope/core/gemini/_utils/_get_json_output.py +0 -35
  300. mirascope/core/gemini/_utils/_handle_stream.py +0 -33
  301. mirascope/core/gemini/_utils/_message_param_converter.py +0 -209
  302. mirascope/core/gemini/_utils/_setup_call.py +0 -149
  303. mirascope/core/gemini/call_params.py +0 -52
  304. mirascope/core/gemini/call_response.py +0 -216
  305. mirascope/core/gemini/call_response_chunk.py +0 -100
  306. mirascope/core/gemini/dynamic_config.py +0 -26
  307. mirascope/core/gemini/stream.py +0 -120
  308. mirascope/core/gemini/tool.py +0 -104
  309. mirascope/core/google/__init__.py +0 -29
  310. mirascope/core/google/_call.py +0 -67
  311. mirascope/core/google/_call_kwargs.py +0 -13
  312. mirascope/core/google/_utils/__init__.py +0 -14
  313. mirascope/core/google/_utils/_convert_common_call_params.py +0 -38
  314. mirascope/core/google/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -27
  315. mirascope/core/google/_utils/_convert_message_params.py +0 -297
  316. mirascope/core/google/_utils/_get_json_output.py +0 -37
  317. mirascope/core/google/_utils/_handle_stream.py +0 -58
  318. mirascope/core/google/_utils/_message_param_converter.py +0 -200
  319. mirascope/core/google/_utils/_setup_call.py +0 -201
  320. mirascope/core/google/_utils/_validate_media_type.py +0 -58
  321. mirascope/core/google/call_params.py +0 -22
  322. mirascope/core/google/call_response.py +0 -255
  323. mirascope/core/google/call_response_chunk.py +0 -135
  324. mirascope/core/google/dynamic_config.py +0 -26
  325. mirascope/core/google/stream.py +0 -199
  326. mirascope/core/google/tool.py +0 -146
  327. mirascope/core/groq/__init__.py +0 -30
  328. mirascope/core/groq/_call.py +0 -67
  329. mirascope/core/groq/_call_kwargs.py +0 -13
  330. mirascope/core/groq/_utils/__init__.py +0 -14
  331. mirascope/core/groq/_utils/_convert_common_call_params.py +0 -26
  332. mirascope/core/groq/_utils/_convert_message_params.py +0 -112
  333. mirascope/core/groq/_utils/_get_json_output.py +0 -27
  334. mirascope/core/groq/_utils/_handle_stream.py +0 -123
  335. mirascope/core/groq/_utils/_message_param_converter.py +0 -89
  336. mirascope/core/groq/_utils/_setup_call.py +0 -132
  337. mirascope/core/groq/call_params.py +0 -52
  338. mirascope/core/groq/call_response.py +0 -213
  339. mirascope/core/groq/call_response_chunk.py +0 -104
  340. mirascope/core/groq/dynamic_config.py +0 -29
  341. mirascope/core/groq/py.typed +0 -0
  342. mirascope/core/groq/stream.py +0 -135
  343. mirascope/core/groq/tool.py +0 -80
  344. mirascope/core/litellm/__init__.py +0 -28
  345. mirascope/core/litellm/_call.py +0 -67
  346. mirascope/core/litellm/_utils/__init__.py +0 -5
  347. mirascope/core/litellm/_utils/_setup_call.py +0 -109
  348. mirascope/core/litellm/call_params.py +0 -10
  349. mirascope/core/litellm/call_response.py +0 -24
  350. mirascope/core/litellm/call_response_chunk.py +0 -14
  351. mirascope/core/litellm/dynamic_config.py +0 -8
  352. mirascope/core/litellm/py.typed +0 -0
  353. mirascope/core/litellm/stream.py +0 -86
  354. mirascope/core/litellm/tool.py +0 -13
  355. mirascope/core/mistral/__init__.py +0 -36
  356. mirascope/core/mistral/_call.py +0 -65
  357. mirascope/core/mistral/_call_kwargs.py +0 -19
  358. mirascope/core/mistral/_utils/__init__.py +0 -14
  359. mirascope/core/mistral/_utils/_convert_common_call_params.py +0 -24
  360. mirascope/core/mistral/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -22
  361. mirascope/core/mistral/_utils/_convert_message_params.py +0 -122
  362. mirascope/core/mistral/_utils/_get_json_output.py +0 -34
  363. mirascope/core/mistral/_utils/_handle_stream.py +0 -139
  364. mirascope/core/mistral/_utils/_message_param_converter.py +0 -176
  365. mirascope/core/mistral/_utils/_setup_call.py +0 -164
  366. mirascope/core/mistral/call_params.py +0 -36
  367. mirascope/core/mistral/call_response.py +0 -205
  368. mirascope/core/mistral/call_response_chunk.py +0 -105
  369. mirascope/core/mistral/dynamic_config.py +0 -33
  370. mirascope/core/mistral/py.typed +0 -0
  371. mirascope/core/mistral/stream.py +0 -120
  372. mirascope/core/mistral/tool.py +0 -81
  373. mirascope/core/openai/__init__.py +0 -31
  374. mirascope/core/openai/_call.py +0 -67
  375. mirascope/core/openai/_call_kwargs.py +0 -13
  376. mirascope/core/openai/_utils/__init__.py +0 -14
  377. mirascope/core/openai/_utils/_convert_common_call_params.py +0 -26
  378. mirascope/core/openai/_utils/_convert_message_params.py +0 -148
  379. mirascope/core/openai/_utils/_get_json_output.py +0 -31
  380. mirascope/core/openai/_utils/_handle_stream.py +0 -138
  381. mirascope/core/openai/_utils/_message_param_converter.py +0 -105
  382. mirascope/core/openai/_utils/_setup_call.py +0 -155
  383. mirascope/core/openai/call_params.py +0 -92
  384. mirascope/core/openai/call_response.py +0 -273
  385. mirascope/core/openai/call_response_chunk.py +0 -139
  386. mirascope/core/openai/dynamic_config.py +0 -34
  387. mirascope/core/openai/py.typed +0 -0
  388. mirascope/core/openai/stream.py +0 -185
  389. mirascope/core/openai/tool.py +0 -101
  390. mirascope/core/py.typed +0 -0
  391. mirascope/core/vertex/__init__.py +0 -45
  392. mirascope/core/vertex/_call.py +0 -62
  393. mirascope/core/vertex/_call_kwargs.py +0 -12
  394. mirascope/core/vertex/_utils/__init__.py +0 -14
  395. mirascope/core/vertex/_utils/_convert_common_call_params.py +0 -37
  396. mirascope/core/vertex/_utils/_convert_finish_reason_to_common_finish_reasons.py +0 -23
  397. mirascope/core/vertex/_utils/_convert_message_params.py +0 -171
  398. mirascope/core/vertex/_utils/_get_json_output.py +0 -36
  399. mirascope/core/vertex/_utils/_handle_stream.py +0 -33
  400. mirascope/core/vertex/_utils/_message_param_converter.py +0 -133
  401. mirascope/core/vertex/_utils/_setup_call.py +0 -160
  402. mirascope/core/vertex/call_params.py +0 -24
  403. mirascope/core/vertex/call_response.py +0 -206
  404. mirascope/core/vertex/call_response_chunk.py +0 -99
  405. mirascope/core/vertex/dynamic_config.py +0 -28
  406. mirascope/core/vertex/stream.py +0 -119
  407. mirascope/core/vertex/tool.py +0 -101
  408. mirascope/core/xai/__init__.py +0 -28
  409. mirascope/core/xai/_call.py +0 -67
  410. mirascope/core/xai/_utils/__init__.py +0 -5
  411. mirascope/core/xai/_utils/_setup_call.py +0 -113
  412. mirascope/core/xai/call_params.py +0 -10
  413. mirascope/core/xai/call_response.py +0 -16
  414. mirascope/core/xai/call_response_chunk.py +0 -14
  415. mirascope/core/xai/dynamic_config.py +0 -8
  416. mirascope/core/xai/py.typed +0 -0
  417. mirascope/core/xai/stream.py +0 -57
  418. mirascope/core/xai/tool.py +0 -13
  419. mirascope/experimental/graphs/__init__.py +0 -5
  420. mirascope/integrations/__init__.py +0 -16
  421. mirascope/integrations/_middleware_factory.py +0 -403
  422. mirascope/integrations/langfuse/__init__.py +0 -3
  423. mirascope/integrations/langfuse/_utils.py +0 -114
  424. mirascope/integrations/langfuse/_with_langfuse.py +0 -70
  425. mirascope/integrations/logfire/__init__.py +0 -3
  426. mirascope/integrations/logfire/_utils.py +0 -225
  427. mirascope/integrations/logfire/_with_logfire.py +0 -63
  428. mirascope/integrations/otel/__init__.py +0 -10
  429. mirascope/integrations/otel/_utils.py +0 -270
  430. mirascope/integrations/otel/_with_hyperdx.py +0 -60
  431. mirascope/integrations/otel/_with_otel.py +0 -59
  432. mirascope/integrations/tenacity.py +0 -14
  433. mirascope/llm/_call.py +0 -401
  434. mirascope/llm/_context.py +0 -384
  435. mirascope/llm/_override.py +0 -3639
  436. mirascope/llm/_protocols.py +0 -500
  437. mirascope/llm/_response_metaclass.py +0 -31
  438. mirascope/llm/call_response.py +0 -158
  439. mirascope/llm/call_response_chunk.py +0 -66
  440. mirascope/llm/stream.py +0 -162
  441. mirascope/llm/tool.py +0 -64
  442. mirascope/mcp/__init__.py +0 -7
  443. mirascope/mcp/_utils.py +0 -288
  444. mirascope/mcp/client.py +0 -167
  445. mirascope/mcp/server.py +0 -356
  446. mirascope/mcp/tools.py +0 -110
  447. mirascope/py.typed +0 -0
  448. mirascope/retries/__init__.py +0 -11
  449. mirascope/retries/fallback.py +0 -131
  450. mirascope/retries/tenacity.py +0 -50
  451. mirascope/tools/__init__.py +0 -37
  452. mirascope/tools/base.py +0 -98
  453. mirascope/tools/system/__init__.py +0 -0
  454. mirascope/tools/system/_docker_operation.py +0 -166
  455. mirascope/tools/system/_file_system.py +0 -267
  456. mirascope/tools/web/__init__.py +0 -0
  457. mirascope/tools/web/_duckduckgo.py +0 -111
  458. mirascope/tools/web/_httpx.py +0 -125
  459. mirascope/tools/web/_parse_url_content.py +0 -94
  460. mirascope/tools/web/_requests.py +0 -54
  461. mirascope/v0/__init__.py +0 -43
  462. mirascope/v0/anthropic.py +0 -54
  463. mirascope/v0/base/__init__.py +0 -12
  464. mirascope/v0/base/calls.py +0 -118
  465. mirascope/v0/base/extractors.py +0 -122
  466. mirascope/v0/base/ops_utils.py +0 -207
  467. mirascope/v0/base/prompts.py +0 -48
  468. mirascope/v0/base/types.py +0 -14
  469. mirascope/v0/base/utils.py +0 -21
  470. mirascope/v0/openai.py +0 -54
  471. mirascope-1.25.7.dist-info/METADATA +0 -169
  472. mirascope-1.25.7.dist-info/RECORD +0 -378
  473. {mirascope-1.25.7.dist-info → mirascope-2.0.0a0.dist-info}/WHEEL +0 -0
  474. {mirascope-1.25.7.dist-info → mirascope-2.0.0a0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,246 @@
1
+ """The `ToolSchema` class for defining tools that LLMs can request be called."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ from collections import namedtuple
7
+ from dataclasses import dataclass
8
+ from typing import (
9
+ Annotated,
10
+ Any,
11
+ Generic,
12
+ TypeVar,
13
+ get_args,
14
+ get_origin,
15
+ get_type_hints,
16
+ )
17
+
18
+ from docstring_parser import parse
19
+ from pydantic import BaseModel, Field, create_model
20
+ from pydantic.fields import FieldInfo
21
+
22
+ from ..content import ToolCall
23
+ from .protocols import AsyncContextToolFn, AsyncToolFn, ContextToolFn, ToolFn
24
+
25
+ ToolFnT = TypeVar(
26
+ "ToolFnT",
27
+ bound=ToolFn | AsyncToolFn | ContextToolFn | AsyncContextToolFn,
28
+ covariant=True,
29
+ )
30
+ ToolSchemaT = TypeVar("ToolSchemaT", bound="ToolSchema")
31
+
32
+ DocstringArg = namedtuple("DocstringArg", ["name", "description"])
33
+
34
+ FORMAT_TOOL_NAME = "__mirascope_formatted_output_tool__"
35
+ """Reserved name of the formatted output tool.
36
+
37
+ Any call to a tool with this name is NOT considered a regular tool call, but will instead
38
+ be converted into textual output containing the arguments to the tool call.
39
+ """
40
+ # TODO: Investigate whether using this hardcoded tool name has any adverse impact
41
+ # on model performance, compared to a tool name that references the name of the formatted
42
+ # class.
43
+
44
+
45
+ @dataclass
46
+ class ParsedDocstring:
47
+ args: list[DocstringArg]
48
+
49
+
50
+ def _parse_docstring_params(docstring: str | None) -> ParsedDocstring:
51
+ """Parse parameter descriptions from a docstring.
52
+
53
+ Uses docstring-parser library which supports ReST, Google, Numpydoc-style and
54
+ Epydoc docstrings
55
+
56
+ Args:
57
+ docstring: The function's docstring
58
+
59
+ Returns:
60
+ ParsedDocstring containing parameter descriptions
61
+ """
62
+ if not docstring:
63
+ return ParsedDocstring(args=[])
64
+
65
+ parsed = parse(docstring)
66
+ args = []
67
+
68
+ for param in parsed.params:
69
+ if param.description:
70
+ args.append(
71
+ DocstringArg(name=param.arg_name, description=param.description)
72
+ )
73
+
74
+ return ParsedDocstring(args=args)
75
+
76
+
77
+ class ToolParameterSchema(BaseModel):
78
+ """JSON Schema for tool parameters (always an object with properties).
79
+
80
+ This contains real JSON Schema as generated by Pydantic, with full support
81
+ for complex schemas like anyOf, nested objects, validation constraints, etc.
82
+ Including $defs for complex type references.
83
+ """
84
+
85
+ properties: dict[str, dict[str, Any]] = Field(default_factory=dict)
86
+ """Dictionary mapping parameter names to their JSON Schema definitions."""
87
+
88
+ required: list[str] = Field(default_factory=list)
89
+ """List of required parameter names."""
90
+
91
+ additionalProperties: bool = False
92
+ """Whether additional properties beyond those defined are allowed."""
93
+
94
+ defs: dict[str, dict[str, Any]] | None = Field(default=None, alias="$defs")
95
+ """JSON Schema definitions for complex types referenced via $ref."""
96
+
97
+
98
+ @dataclass
99
+ class ToolSchema(Generic[ToolFnT]):
100
+ """Underlying schema defining a tool that can be used by LLMs.
101
+
102
+ A ToolSchema represents a function that can be called by an LLM during a call.
103
+ It includes metadata like name, description, and parameter schema.
104
+
105
+ This class is not instantiated directly but created by the `@tool()` decorator.
106
+ """
107
+
108
+ fn: ToolFnT
109
+ """The function that implements the tool's functionality."""
110
+
111
+ name: str
112
+ """The name of the tool, used by the LLM to identify which tool to call."""
113
+
114
+ description: str
115
+ """Description of what the tool does, extracted from the function's docstring."""
116
+
117
+ parameters: ToolParameterSchema
118
+ """JSON Schema describing the parameters accepted by the tool.
119
+
120
+ The serialized parameters table is cached for efficient hash lookups (e.g. when
121
+ caching provider-encoded tool representations in a LRU cache). Therefore,
122
+ it should **not be modified** after the ToolSchema is created.
123
+ """
124
+
125
+ strict: bool
126
+ """Whether the tool should use strict mode when supported by the model."""
127
+
128
+ def __hash__(self) -> int:
129
+ if not hasattr(self, "_hash"):
130
+ self._hash = hash(
131
+ (
132
+ self.name,
133
+ self.description,
134
+ self.strict,
135
+ self.parameters.model_dump_json(),
136
+ )
137
+ )
138
+ return self._hash
139
+
140
+ def __init__(
141
+ self,
142
+ fn: ToolFnT,
143
+ *,
144
+ strict: bool = False,
145
+ is_context_tool: bool = False,
146
+ ) -> None:
147
+ """Create a `ToolSchema` by inspecting a function and its docstring.
148
+
149
+ Uses Pydantic's create_model to dynamically build a model from the function
150
+ signature, then extracts the JSON schema from it. This leverages Pydantic's
151
+ robust type conversion and union handling.
152
+
153
+ Args:
154
+ fn: The function to extract schema from
155
+ strict: Whether the tool should use strict mode when supported
156
+ is_context_tool: Whether this is a context tool (skips the context parameter)
157
+
158
+ Returns:
159
+ a `ToolSchema` representing the function
160
+
161
+ Raises:
162
+ ValueError: If the tool has a reserved name.
163
+ """
164
+ name = fn.__name__
165
+ if name.startswith(FORMAT_TOOL_NAME):
166
+ raise ValueError(
167
+ f"Cannot use reserved name {FORMAT_TOOL_NAME} as tool name."
168
+ )
169
+ description = inspect.cleandoc(fn.__doc__) if fn.__doc__ else name
170
+
171
+ param_descriptions = _parse_docstring_params(fn.__doc__)
172
+
173
+ field_definitions = {}
174
+ hints = get_type_hints(fn, include_extras=True)
175
+
176
+ context_param_skipped = False
177
+ for param in inspect.signature(fn).parameters.values():
178
+ # Skip args that are provided by Python or Mirascope, not LLM-generated.
179
+ # TODO: Handling of FromCallArgs
180
+ if param.name in ("self", "cls"):
181
+ continue
182
+
183
+ # For context tools, skip the first non-self/cls parameter (the context parameter)
184
+ if is_context_tool and not context_param_skipped:
185
+ context_param_skipped = True
186
+ continue
187
+
188
+ param_type = hints.get(param.name, Any)
189
+ default = ... if param.default is inspect.Parameter.empty else param.default
190
+ field_info = None
191
+
192
+ if get_origin(param_type) is Annotated:
193
+ args = get_args(param_type)
194
+ param_type = args[0]
195
+ for annotation in args[1:]:
196
+ if isinstance(annotation, FieldInfo):
197
+ field_info = annotation
198
+ break
199
+
200
+ if field_info is not None:
201
+ field_value = Field(
202
+ default=default,
203
+ description=field_info.description,
204
+ )
205
+ else:
206
+ docstring_description = None
207
+ for arg in param_descriptions.args:
208
+ if arg.name == param.name:
209
+ docstring_description = arg.description
210
+ break
211
+ if docstring_description:
212
+ field_value = Field(
213
+ default=default, description=docstring_description
214
+ )
215
+ else:
216
+ field_value = default
217
+
218
+ field_definitions[param.name] = (param_type, field_value)
219
+
220
+ TempModel = create_model("TempModel", **field_definitions)
221
+
222
+ schema = TempModel.model_json_schema()
223
+
224
+ parameters = ToolParameterSchema(
225
+ properties=schema.get("properties", {}),
226
+ required=schema.get("required", []),
227
+ additionalProperties=False,
228
+ )
229
+ if "$defs" in schema:
230
+ parameters.defs = schema["$defs"]
231
+
232
+ self.fn = fn
233
+ self.name = name
234
+ self.description = description
235
+ self.parameters = parameters
236
+ self.strict = strict
237
+
238
+ def can_execute(self, tool_call: ToolCall) -> bool:
239
+ """Check if a `ToolCall` can be executed by tools with this `ToolSchema`.
240
+
241
+ This method is a convenient way to determine if a `ToolCall` is likely intended
242
+ to be executed by a tool with this `ToolSchema`. It does so by checking
243
+ whether the name on the call matches the name on the schema. No other validation
244
+ is performed.
245
+ """
246
+ return tool_call.name == self.name
@@ -0,0 +1,152 @@
1
+ from collections.abc import Sequence
2
+ from dataclasses import dataclass
3
+ from typing import Any, Generic, TypeVar
4
+
5
+ from ..content import ToolCall, ToolOutput
6
+ from ..context import Context, DepsT
7
+ from ..exceptions import ToolNotFoundError
8
+ from ..types import Jsonable
9
+ from .tool_schema import ToolSchemaT
10
+ from .tools import AsyncContextTool, AsyncTool, ContextTool, Tool
11
+
12
+ ToolkitT = TypeVar(
13
+ "ToolkitT",
14
+ bound="Toolkit | AsyncToolkit | ContextToolkit[Any] | AsyncContextToolkit[Any]",
15
+ covariant=True,
16
+ )
17
+
18
+
19
+ @dataclass
20
+ class BaseToolkit(Generic[ToolSchemaT]):
21
+ """Base class for tool collections.
22
+
23
+ Provides common functionality for managing collections of tools,
24
+ including name validation and tool lookup.
25
+ """
26
+
27
+ tools: Sequence[ToolSchemaT]
28
+ """The tools included in the toolkit."""
29
+
30
+ tools_dict: dict[str, ToolSchemaT]
31
+ """A mapping from tool names to tools in the toolkit."""
32
+
33
+ def __init__(self, tools: Sequence[ToolSchemaT] | None) -> None:
34
+ """Initialize the toolkit with a collection of tools.
35
+
36
+ Args:
37
+ tools: Sequence of tools to include in the toolkit.
38
+
39
+ Raises:
40
+ ValueError: If multiple tools have the same name.
41
+ """
42
+ self.tools = tools or []
43
+ self.tools_dict = {}
44
+ for tool in self.tools:
45
+ if tool.name in self.tools_dict:
46
+ raise ValueError(f"Multiple tools with name: {tool.name}")
47
+ self.tools_dict[tool.name] = tool
48
+
49
+ def get(self, tool_call: ToolCall) -> ToolSchemaT:
50
+ """Get a tool that can execute a specific tool call.
51
+
52
+ Args:
53
+ tool_call: The tool call containing the tool name to lookup.
54
+
55
+ Returns:
56
+ The tool whose name matches the tool call.
57
+
58
+ Raises:
59
+ ToolNotFoundError: If no tool with the given name exists.
60
+ """
61
+ tool = self.tools_dict.get(tool_call.name, None)
62
+ if not tool:
63
+ raise ToolNotFoundError(f"Tool not found in toolkit: {tool_call.name}")
64
+ return tool
65
+
66
+
67
+ class Toolkit(BaseToolkit[Tool]):
68
+ """A collection of `Tool`s, with helpers for getting and executing specific tools."""
69
+
70
+ def execute(self, tool_call: ToolCall) -> ToolOutput[Jsonable]:
71
+ """Execute a `Tool` using the provided tool call.
72
+
73
+ Args:
74
+ tool_call: The tool call to execute.
75
+
76
+ Returns:
77
+ The output from executing the `Tool`.
78
+
79
+ Raises:
80
+ ToolNotFoundError: If the requested tool is not found.
81
+ """
82
+ tool = self.get(tool_call)
83
+ return tool.execute(tool_call)
84
+
85
+
86
+ class AsyncToolkit(BaseToolkit[AsyncTool]):
87
+ """A collection of `AsyncTool`s, with helpers for getting and executing specific tools."""
88
+
89
+ async def execute(self, tool_call: ToolCall) -> ToolOutput[Jsonable]:
90
+ """Execute an `AsyncTool` using the provided tool call.
91
+
92
+ Args:
93
+ tool_call: The tool call to execute.
94
+
95
+ Returns:
96
+ The output from executing the `AsyncTool`.
97
+
98
+ Raises:
99
+ ToolNotFoundError: If the requested tool is not found.
100
+ """
101
+ tool = self.get(tool_call)
102
+ return await tool.execute(tool_call)
103
+
104
+
105
+ class ContextToolkit(BaseToolkit[Tool | ContextTool[DepsT]], Generic[DepsT]):
106
+ """A collection of `ContextTool`s, with helpers for getting and executing specific tools."""
107
+
108
+ def execute(self, ctx: Context[DepsT], tool_call: ToolCall) -> ToolOutput[Jsonable]:
109
+ """Execute a `ContextTool` using the provided tool call.
110
+
111
+ Args:
112
+ ctx: The context containing dependencies that match the tool.
113
+ tool_call: The tool call to execute.
114
+
115
+ Returns:
116
+ The output from executing the `ContextTool`.
117
+
118
+ Raises:
119
+ ToolNotFoundError: If the requested tool is not found.
120
+ """
121
+ tool = self.get(tool_call)
122
+ if isinstance(tool, ContextTool):
123
+ return tool.execute(ctx, tool_call)
124
+ else:
125
+ return tool.execute(tool_call)
126
+
127
+
128
+ class AsyncContextToolkit(
129
+ BaseToolkit[AsyncTool | AsyncContextTool[DepsT]], Generic[DepsT]
130
+ ):
131
+ """A collection of `AsyncContextTool`s, with helpers for getting and executing specific tools."""
132
+
133
+ async def execute(
134
+ self, ctx: Context[DepsT], tool_call: ToolCall
135
+ ) -> ToolOutput[Jsonable]:
136
+ """Execute an `AsyncContextTool` using the provided tool call.
137
+
138
+ Args:
139
+ ctx: The context containing dependencies that match the tool.
140
+ tool_call: The tool call to execute.
141
+
142
+ Returns:
143
+ The output from executing the `AsyncContextTool`.
144
+
145
+ Raises:
146
+ ToolNotFoundError: If the requested tool is not found.
147
+ """
148
+ tool = self.get(tool_call)
149
+ if isinstance(tool, AsyncContextTool):
150
+ return await tool.execute(ctx, tool_call)
151
+ else:
152
+ return await tool.execute(tool_call)
@@ -0,0 +1,169 @@
1
+ """The `Tool` class for defining tools that LLMs can request be called."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from collections.abc import Awaitable
7
+ from typing import Any, Generic, TypeVar, cast
8
+
9
+ from ..content import ToolCall, ToolOutput
10
+ from ..context import Context, DepsT
11
+ from ..types import AnyP, JsonableCovariantT
12
+ from .protocols import (
13
+ AsyncContextToolFn,
14
+ AsyncToolFn,
15
+ ContextToolFn,
16
+ ToolFn,
17
+ _AsyncJsonKwargsCallable,
18
+ _AsyncKwargsCallable,
19
+ _ContextKwargsCallable,
20
+ _KwargsCallable,
21
+ )
22
+ from .tool_schema import ToolSchema
23
+
24
+ ToolT = TypeVar(
25
+ "ToolT",
26
+ bound="Tool | AsyncTool | ContextTool[Any] | AsyncContextTool[Any]",
27
+ covariant=True,
28
+ )
29
+
30
+
31
+ class Tool(
32
+ ToolSchema[ToolFn[AnyP, JsonableCovariantT]], Generic[AnyP, JsonableCovariantT]
33
+ ):
34
+ """A tool that can be used by LLMs.
35
+
36
+ A `Tool` represents a function that can be called by an LLM during a call.
37
+ It includes metadata like name, description, and parameter schema.
38
+
39
+ This class is not instantiated directly but created by the `@tool()` decorator.
40
+ """
41
+
42
+ def __init__(
43
+ self, fn: ToolFn[AnyP, JsonableCovariantT], *, strict: bool = False
44
+ ) -> None:
45
+ super().__init__(fn, strict=strict, is_context_tool=False)
46
+
47
+ def __call__(self, *args: AnyP.args, **kwargs: AnyP.kwargs) -> JsonableCovariantT:
48
+ """Call the underlying function directly."""
49
+ return self.fn(*args, **kwargs)
50
+
51
+ def execute(self, tool_call: ToolCall) -> ToolOutput[JsonableCovariantT]:
52
+ """Execute the tool using an LLM-provided `ToolCall`."""
53
+ kwargs_from_json = json.loads(tool_call.args)
54
+ kwargs_callable = cast(_KwargsCallable[JsonableCovariantT], self.fn)
55
+ result = kwargs_callable(**kwargs_from_json)
56
+ return ToolOutput(id=tool_call.id, value=result, name=self.name)
57
+
58
+
59
+ class AsyncTool(
60
+ ToolSchema[AsyncToolFn[AnyP, JsonableCovariantT]],
61
+ Generic[AnyP, JsonableCovariantT],
62
+ ):
63
+ """An async tool that can be used by LLMs.
64
+
65
+ An `AsyncTool` represents an async function that can be called by an LLM during a call.
66
+ It includes metadata like name, description, and parameter schema.
67
+
68
+ This class is not instantiated directly but created by the `@tool()` decorator.
69
+ """
70
+
71
+ def __init__(
72
+ self, fn: AsyncToolFn[AnyP, JsonableCovariantT], *, strict: bool = False
73
+ ) -> None:
74
+ super().__init__(fn, strict=strict, is_context_tool=False)
75
+
76
+ def __call__(
77
+ self, *args: AnyP.args, **kwargs: AnyP.kwargs
78
+ ) -> Awaitable[JsonableCovariantT]:
79
+ """Call the underlying async function directly."""
80
+ return self.fn(*args, **kwargs)
81
+
82
+ async def execute(self, tool_call: ToolCall) -> ToolOutput[JsonableCovariantT]:
83
+ """Execute the async tool using an LLM-provided `ToolCall`."""
84
+ kwargs_from_json = json.loads(tool_call.args)
85
+ kwargs_callable = cast(_AsyncKwargsCallable[JsonableCovariantT], self.fn)
86
+ result = await kwargs_callable(**kwargs_from_json)
87
+ return ToolOutput(id=tool_call.id, value=result, name=self.name)
88
+
89
+
90
+ class ContextTool(
91
+ ToolSchema[ContextToolFn[DepsT, AnyP, JsonableCovariantT]],
92
+ Generic[DepsT, AnyP, JsonableCovariantT],
93
+ ):
94
+ """Protocol defining a tool that can be used by LLMs.
95
+
96
+ A `ContextTool` represents a function that can be called by an LLM during a call.
97
+ It includes metadata like name, description, and parameter schema.
98
+
99
+ This class is not instantiated directly but created by the `@tool()` decorator.
100
+ """
101
+
102
+ def __init__(
103
+ self,
104
+ fn: ContextToolFn[DepsT, AnyP, JsonableCovariantT],
105
+ *,
106
+ strict: bool = False,
107
+ ) -> None:
108
+ super().__init__(fn, strict=strict, is_context_tool=True)
109
+
110
+ def __call__(
111
+ self,
112
+ ctx: Context[DepsT],
113
+ *args: AnyP.args,
114
+ **kwargs: AnyP.kwargs,
115
+ ) -> JsonableCovariantT:
116
+ """Call the underlying function directly with context."""
117
+ return self.fn(ctx, *args, **kwargs)
118
+
119
+ def execute(
120
+ self, ctx: Context[DepsT], tool_call: ToolCall
121
+ ) -> ToolOutput[JsonableCovariantT]:
122
+ """Execute the context tool using an LLM-provided `ToolCall`."""
123
+ kwargs_from_json = json.loads(tool_call.args)
124
+ kwargs_callable = cast(
125
+ _ContextKwargsCallable[DepsT, JsonableCovariantT], self.fn
126
+ )
127
+ result = kwargs_callable(ctx, **kwargs_from_json)
128
+ return ToolOutput(id=tool_call.id, value=result, name=self.name)
129
+
130
+
131
+ class AsyncContextTool(
132
+ ToolSchema[AsyncContextToolFn[DepsT, AnyP, JsonableCovariantT]],
133
+ Generic[DepsT, AnyP, JsonableCovariantT],
134
+ ):
135
+ """Protocol defining an async tool that can be used by LLMs with context.
136
+
137
+ An `AsyncContextTool` represents an async function that can be called by an LLM during a call.
138
+ It includes metadata like name, description, and parameter schema.
139
+
140
+ This class is not instantiated directly but created by the `@tool()` decorator.
141
+ """
142
+
143
+ def __init__(
144
+ self,
145
+ fn: AsyncContextToolFn[DepsT, AnyP, JsonableCovariantT],
146
+ *,
147
+ strict: bool = False,
148
+ ) -> None:
149
+ super().__init__(fn, strict=strict, is_context_tool=True)
150
+
151
+ def __call__(
152
+ self,
153
+ ctx: Context[DepsT],
154
+ *args: AnyP.args,
155
+ **kwargs: AnyP.kwargs,
156
+ ) -> Awaitable[JsonableCovariantT]:
157
+ """Call the underlying async function directly with context."""
158
+ return self.fn(ctx, *args, **kwargs)
159
+
160
+ async def execute(
161
+ self, ctx: Context[DepsT], tool_call: ToolCall
162
+ ) -> ToolOutput[JsonableCovariantT]:
163
+ """Execute the async context tool using an LLM-provided `ToolCall`."""
164
+ kwargs_from_json = json.loads(tool_call.args)
165
+ kwargs_callable = cast(
166
+ _AsyncJsonKwargsCallable[DepsT, JsonableCovariantT], self.fn
167
+ )
168
+ result = await kwargs_callable(ctx, **kwargs_from_json)
169
+ return ToolOutput(id=tool_call.id, value=result, name=self.name)
@@ -0,0 +1,22 @@
1
+ """Types for the LLM module."""
2
+
3
+ from .dataclass import Dataclass
4
+ from .jsonable import (
5
+ Jsonable,
6
+ JsonableCovariantT,
7
+ JsonableT,
8
+ )
9
+ from .type_vars import AnyP, CovariantT, P
10
+
11
+ NoneType = type(None)
12
+
13
+ __all__ = [
14
+ "AnyP",
15
+ "CovariantT",
16
+ "Dataclass",
17
+ "Jsonable",
18
+ "JsonableCovariantT",
19
+ "JsonableT",
20
+ "NoneType",
21
+ "P",
22
+ ]
@@ -0,0 +1,9 @@
1
+ """A protocol for defining a dataclass type."""
2
+
3
+ from dataclasses import Field
4
+ from typing import Any, ClassVar, Protocol, runtime_checkable
5
+
6
+
7
+ @runtime_checkable
8
+ class Dataclass(Protocol):
9
+ __dataclass_fields__: ClassVar[dict[str, Field[Any]]]
@@ -0,0 +1,44 @@
1
+ """Typing for JSON serializable objects."""
2
+
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Protocol, TypeAlias
5
+ from typing_extensions import TypeVar
6
+
7
+
8
+ class JsonableObject(Protocol):
9
+ """Protocol for JSON-serializable objects.
10
+
11
+ This protocol defines the interface for objects that can be serialized to
12
+ JSON. It is used to annotate the `JsonableType` type alias.
13
+ """
14
+
15
+ def json(self) -> str:
16
+ """Serialize the object as a JSON string."""
17
+ ...
18
+
19
+
20
+ Jsonable: TypeAlias = (
21
+ None
22
+ | str
23
+ | int
24
+ | float
25
+ | bool
26
+ | Sequence["Jsonable"]
27
+ | Mapping[str, "Jsonable"]
28
+ | JsonableObject
29
+ )
30
+ """Simple type alias for JSON-serializable types."""
31
+
32
+
33
+ JsonableT = TypeVar("JsonableT", bound=Jsonable)
34
+ """Type variable for tool output types.
35
+
36
+ This TypeVar represents the return type of tool functions, which must be
37
+ serializable to JSON (bound to Jsonable) for LLM consumption.
38
+ """
39
+
40
+
41
+ JsonableCovariantT = TypeVar(
42
+ "JsonableCovariantT", covariant=True, bound=Jsonable, default=Jsonable
43
+ )
44
+ """Type variable for covariant types that are Jsonable."""
@@ -0,0 +1,19 @@
1
+ """Common TypeVar definitions for the LLM module."""
2
+
3
+ from typing import TypeVar
4
+ from typing_extensions import ParamSpec
5
+
6
+ P = ParamSpec("P")
7
+ """Parameter specification for function signatures.
8
+
9
+ This ParamSpec is used to preserve function parameter types and signatures
10
+ when wrapping functions with decorators or creating generic callable types.
11
+ It captures both positional and keyword arguments (*args, **kwargs) while
12
+ maintaining their original types.
13
+ """
14
+
15
+ AnyP = ParamSpec("AnyP", default=...)
16
+ """A parameter specification that defaults to ..."""
17
+
18
+ CovariantT = TypeVar("CovariantT", covariant=True)
19
+ """Type variable for covariant types."""