pydantic-ai 0.2.18__tar.gz → 0.2.20__tar.gz

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.

Potentially problematic release.


This version of pydantic-ai might be problematic. Click here for more details.

Files changed (264) hide show
  1. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/PKG-INFO +3 -3
  2. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/mcp_server.py +18 -0
  3. pydantic_ai-0.2.20/tests/models/cassettes/test_gemini/test_gemini_tool_config_any_with_tool_without_args.yaml +182 -0
  4. pydantic_ai-0.2.20/tests/models/cassettes/test_google/test_google_timeout.yaml +64 -0
  5. pydantic_ai-0.2.20/tests/models/cassettes/test_google/test_google_tool_config_any_with_tool_without_args.yaml +180 -0
  6. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_gemini.py +81 -0
  7. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_google.py +92 -1
  8. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_provider_names.py +7 -0
  9. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_agent.py +8 -1
  10. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_examples.py +3 -3
  11. pydantic_ai-0.2.20/tests/test_history_processor.py +303 -0
  12. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_mcp.py +49 -5
  13. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_streaming.py +120 -1
  14. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_utils.py +25 -1
  15. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/.gitignore +0 -0
  16. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/LICENSE +0 -0
  17. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/Makefile +0 -0
  18. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/README.md +0 -0
  19. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/pyproject.toml +0 -0
  20. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/__init__.py +0 -0
  21. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/dummy.pdf +0 -0
  22. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/kiwi.png +0 -0
  23. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/marcelo.mp3 +0 -0
  24. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/small_video.mp4 +0 -0
  25. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_agent_with_stdio_server.yaml +0 -0
  26. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_audio_resource.yaml +0 -0
  27. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_dict.yaml +0 -0
  28. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_error.yaml +0 -0
  29. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_image.yaml +0 -0
  30. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_image_resource.yaml +0 -0
  31. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_multiple_items.yaml +0 -0
  32. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_none.yaml +0 -0
  33. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_str.yaml +0 -0
  34. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_text_resource.yaml +0 -0
  35. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[anthropic].yaml +0 -0
  36. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[bedrock].yaml +0 -0
  37. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[cohere].yaml +0 -0
  38. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[gemini].yaml +0 -0
  39. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[google].yaml +0 -0
  40. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[groq].yaml +0 -0
  41. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[mistral].yaml +0 -0
  42. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[openai].yaml +0 -0
  43. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/conftest.py +0 -0
  44. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/__init__.py +0 -0
  45. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_dataset.py +0 -0
  46. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_base.py +0 -0
  47. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_common.py +0 -0
  48. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_context.py +0 -0
  49. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_spec.py +0 -0
  50. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluators.py +0 -0
  51. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_llm_as_a_judge.py +0 -0
  52. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_otel.py +0 -0
  53. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_render_numbers.py +0 -0
  54. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_reporting.py +0 -0
  55. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_reports.py +0 -0
  56. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_utils.py +0 -0
  57. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/utils.py +0 -0
  58. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/README.md +0 -0
  59. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/bank_database.py +0 -0
  60. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/fake_database.py +0 -0
  61. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/weather_service.py +0 -0
  62. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/ext/__init__.py +0 -0
  63. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/ext/test_langchain.py +0 -0
  64. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/fasta2a/__init__.py +0 -0
  65. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/fasta2a/test_applications.py +0 -0
  66. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/__init__.py +0 -0
  67. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_file_persistence.py +0 -0
  68. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_graph.py +0 -0
  69. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_mermaid.py +0 -0
  70. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_persistence.py +0 -0
  71. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_state.py +0 -0
  72. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_utils.py +0 -0
  73. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/import_examples.py +0 -0
  74. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/json_body_serializer.py +0 -0
  75. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/__init__.py +0 -0
  76. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_anthropic_model_empty_message_on_history.yaml +0 -0
  77. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_anthropic_model_instructions.yaml +0 -0
  78. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_document_binary_content_input.yaml +0 -0
  79. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_document_url_input.yaml +0 -0
  80. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_extra_headers.yaml +0 -0
  81. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_image_as_binary_content_tool_response.yaml +0 -0
  82. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_image_url_input.yaml +0 -0
  83. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_image_url_input_invalid_mime_type.yaml +0 -0
  84. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_multiple_parallel_tool_calls.yaml +0 -0
  85. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_text_document_url_input.yaml +0 -0
  86. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_empty_system_prompt.yaml +0 -0
  87. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model.yaml +0 -0
  88. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_anthropic_model_without_tools.yaml +0 -0
  89. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_guardrail_config.yaml +0 -0
  90. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_instructions.yaml +0 -0
  91. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_iter_stream.yaml +0 -0
  92. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_max_tokens.yaml +0 -0
  93. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_other_parameters.yaml +0 -0
  94. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_performance_config.yaml +0 -0
  95. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_retry.yaml +0 -0
  96. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_stream.yaml +0 -0
  97. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_structured_response.yaml +0 -0
  98. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_top_p.yaml +0 -0
  99. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_multiple_documents_in_history.yaml +0 -0
  100. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_document_url_input.yaml +0 -0
  101. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_image_as_binary_content_input.yaml +0 -0
  102. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_image_url_input.yaml +0 -0
  103. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_text_as_binary_content_input.yaml +0 -0
  104. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_text_document_url_input.yaml +0 -0
  105. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_video_as_binary_content_input.yaml +0 -0
  106. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_video_url_input.yaml +0 -0
  107. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_cohere/test_cohere_model_instructions.yaml +0 -0
  108. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_cohere/test_request_simple_success_with_vcr.yaml +0 -0
  109. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_download_item/test_download_item_application_octet_stream.yaml +0 -0
  110. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_download_item/test_download_item_no_content_type.yaml +0 -0
  111. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_document_url_input.yaml +0 -0
  112. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_false.yaml +0 -0
  113. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_true.yaml +0 -0
  114. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_drop_exclusive_maximum.yaml +0 -0
  115. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_exclusive_minimum_and_maximum.yaml +0 -0
  116. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_model_instructions.yaml +0 -0
  117. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_youtube_video_url_input.yaml +0 -0
  118. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_image_as_binary_content_input.yaml +0 -0
  119. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_image_as_binary_content_tool_response.yaml +0 -0
  120. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_image_url_input.yaml +0 -0
  121. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_labels_are_ignored_with_gla_provider.yaml +0 -0
  122. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_video_as_binary_content_input.yaml +0 -0
  123. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_video_url_input.yaml +0 -0
  124. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_labels.yaml +0 -0
  125. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[AudioUrl (gs)].yaml +0 -0
  126. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[AudioUrl].yaml +0 -0
  127. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[DocumentUrl (gs)].yaml +0 -0
  128. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[DocumentUrl].yaml +0 -0
  129. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[ImageUrl (gs)].yaml +0 -0
  130. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[ImageUrl].yaml +0 -0
  131. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl (YouTube)].yaml +0 -0
  132. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl (gs)].yaml +0 -0
  133. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl].yaml +0 -0
  134. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input_force_download.yaml +0 -0
  135. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model.yaml +0 -0
  136. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_document_url_input.yaml +0 -0
  137. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_empty_user_prompt.yaml +0 -0
  138. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_image_as_binary_content_input.yaml +0 -0
  139. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_image_url_input.yaml +0 -0
  140. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_instructions.yaml +0 -0
  141. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_iter_stream.yaml +0 -0
  142. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_max_tokens.yaml +0 -0
  143. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_multiple_documents_in_history.yaml +0 -0
  144. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_retry.yaml +0 -0
  145. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_safety_settings.yaml +0 -0
  146. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_stream.yaml +0 -0
  147. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_structured_response.yaml +0 -0
  148. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_text_as_binary_content_input.yaml +0 -0
  149. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_text_document_url_input.yaml +0 -0
  150. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_thinking_config.yaml +0 -0
  151. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_top_p.yaml +0 -0
  152. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_vertex_labels.yaml +0 -0
  153. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_vertex_provider.yaml +0 -0
  154. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_video_as_binary_content_input.yaml +0 -0
  155. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_video_url_input.yaml +0 -0
  156. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[AudioUrl (gs)].yaml +0 -0
  157. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[AudioUrl].yaml +0 -0
  158. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[DocumentUrl (gs)].yaml +0 -0
  159. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[DocumentUrl].yaml +0 -0
  160. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[ImageUrl (gs)].yaml +0 -0
  161. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[ImageUrl].yaml +0 -0
  162. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl (YouTube)].yaml +0 -0
  163. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl (gs)].yaml +0 -0
  164. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl].yaml +0 -0
  165. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input_force_download.yaml +0 -0
  166. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_extra_headers.yaml +0 -0
  167. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_groq_model_instructions.yaml +0 -0
  168. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_image_as_binary_content_input.yaml +0 -0
  169. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_image_as_binary_content_tool_response.yaml +0 -0
  170. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_image_url_input.yaml +0 -0
  171. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml +0 -0
  172. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_mistral/test_mistral_model_instructions.yaml +0 -0
  173. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_model_names/test_known_model_names.yaml +0 -0
  174. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_audio_as_binary_content_input.yaml +0 -0
  175. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_compatible_api_with_tool_calls_without_id.yaml +0 -0
  176. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_document_as_binary_content_input.yaml +0 -0
  177. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_document_url_input.yaml +0 -0
  178. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_extra_headers.yaml +0 -0
  179. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_image_as_binary_content_input.yaml +0 -0
  180. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_image_as_binary_content_tool_response.yaml +0 -0
  181. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_image_url_tool_response.yaml +0 -0
  182. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4.5-preview].yaml +0 -0
  183. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4o-mini].yaml +0 -0
  184. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_max_completion_tokens[o3-mini].yaml +0 -0
  185. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_multiple_agent_tool_calls.yaml +0 -0
  186. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_audio_url_input.yaml +0 -0
  187. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_instructions.yaml +0 -0
  188. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_instructions_with_tool_calls_keep_instructions.yaml +0 -0
  189. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_model_without_system_prompt.yaml +0 -0
  190. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[developer].yaml +0 -0
  191. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[system].yaml +0 -0
  192. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_reasoning_model_with_temperature.yaml +0 -0
  193. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_user_id.yaml +0 -0
  194. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_audio_as_binary_content_input.yaml +0 -0
  195. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_image_as_binary_content_input.yaml +0 -0
  196. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_image_as_binary_content_tool_response.yaml +0 -0
  197. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_as_binary_content_input.yaml +0 -0
  198. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_url_input.yaml +0 -0
  199. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_image_url_input.yaml +0 -0
  200. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_builtin_tools.yaml +0 -0
  201. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_http_error.yaml +0 -0
  202. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_instructions.yaml +0 -0
  203. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_retry.yaml +0 -0
  204. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response.yaml +0 -0
  205. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response_with_tool_call.yaml +0 -0
  206. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_output_type.yaml +0 -0
  207. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_effort.yaml +0 -0
  208. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_generate_summary.yaml +0 -0
  209. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_stream.yaml +0 -0
  210. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_system_prompt.yaml +0 -0
  211. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_text_document_url_input.yaml +0 -0
  212. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_reasoning_model_with_temperature.yaml +0 -0
  213. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/mock_async_stream.py +0 -0
  214. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_anthropic.py +0 -0
  215. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_bedrock.py +0 -0
  216. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_cohere.py +0 -0
  217. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_download_item.py +0 -0
  218. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_fallback.py +0 -0
  219. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_gemini_vertex.py +0 -0
  220. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_groq.py +0 -0
  221. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_instrumented.py +0 -0
  222. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_mistral.py +0 -0
  223. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model.py +0 -0
  224. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_function.py +0 -0
  225. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_names.py +0 -0
  226. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_request_parameters.py +0 -0
  227. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_test.py +0 -0
  228. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_openai.py +0 -0
  229. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_openai_responses.py +0 -0
  230. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/__init__.py +0 -0
  231. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_azure/test_azure_provider_call.yaml +0 -0
  232. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_google_vertex/test_vertexai_provider.yaml +0 -0
  233. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_heroku/test_heroku_model_provider_claude_3_7_sonnet.yaml +0 -0
  234. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_openrouter/test_openrouter_with_google_model.yaml +0 -0
  235. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_anthropic.py +0 -0
  236. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_azure.py +0 -0
  237. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_bedrock.py +0 -0
  238. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_cohere.py +0 -0
  239. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_deepseek.py +0 -0
  240. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_fireworks.py +0 -0
  241. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_google_gla.py +0 -0
  242. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_google_vertex.py +0 -0
  243. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_grok.py +0 -0
  244. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_groq.py +0 -0
  245. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_heroku.py +0 -0
  246. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_mistral.py +0 -0
  247. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_openai.py +0 -0
  248. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_openrouter.py +0 -0
  249. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_together.py +0 -0
  250. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_a2a.py +0 -0
  251. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_cli.py +0 -0
  252. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_deps.py +0 -0
  253. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_direct.py +0 -0
  254. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_format_as_xml.py +0 -0
  255. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_json_body_serializer.py +0 -0
  256. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_live.py +0 -0
  257. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_logfire.py +0 -0
  258. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_messages.py +0 -0
  259. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_parts_manager.py +0 -0
  260. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_settings.py +0 -0
  261. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_tools.py +0 -0
  262. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_usage_limits.py +0 -0
  263. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/typed_agent.py +0 -0
  264. {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/typed_graph.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai
3
- Version: 0.2.18
3
+ Version: 0.2.20
4
4
  Summary: Agent Framework / shim to use Pydantic with LLMs
5
5
  Project-URL: Homepage, https://ai.pydantic.dev
6
6
  Project-URL: Source, https://github.com/pydantic/pydantic-ai
@@ -28,9 +28,9 @@ Classifier: Topic :: Internet
28
28
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
29
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
30
30
  Requires-Python: >=3.9
31
- Requires-Dist: pydantic-ai-slim[a2a,anthropic,bedrock,cli,cohere,evals,google,groq,mcp,mistral,openai,vertexai]==0.2.18
31
+ Requires-Dist: pydantic-ai-slim[a2a,anthropic,bedrock,cli,cohere,evals,google,groq,mcp,mistral,openai,vertexai]==0.2.20
32
32
  Provides-Extra: examples
33
- Requires-Dist: pydantic-ai-examples==0.2.18; extra == 'examples'
33
+ Requires-Dist: pydantic-ai-examples==0.2.20; extra == 'examples'
34
34
  Provides-Extra: logfire
35
35
  Requires-Dist: logfire>=3.11.0; extra == 'logfire'
36
36
  Description-Content-Type: text/markdown
@@ -3,6 +3,8 @@ from pathlib import Path
3
3
  from typing import Any
4
4
 
5
5
  from mcp.server.fastmcp import Context, FastMCP, Image
6
+ from mcp.server.session import ServerSessionT
7
+ from mcp.shared.context import LifespanContextT, RequestT
6
8
  from mcp.types import BlobResourceContents, EmbeddedResource, TextResourceContents
7
9
  from pydantic import AnyUrl
8
10
 
@@ -118,6 +120,22 @@ async def get_log_level(ctx: Context) -> str: # type: ignore
118
120
  return log_level
119
121
 
120
122
 
123
+ @mcp.tool()
124
+ async def echo_deps(ctx: Context[ServerSessionT, LifespanContextT, RequestT]) -> dict[str, Any]:
125
+ """Echo the run context.
126
+
127
+ Args:
128
+ ctx: Context object containing request and session information.
129
+
130
+ Returns:
131
+ Dictionary with an echo message and the deps.
132
+ """
133
+ await ctx.info('This is an info message')
134
+
135
+ deps: Any = getattr(ctx.request_context.meta, 'deps')
136
+ return {'echo': 'This is an echo message', 'deps': deps}
137
+
138
+
121
139
  @mcp._mcp_server.set_logging_level() # pyright: ignore[reportPrivateUsage]
122
140
  async def set_logging_level(level: str) -> None:
123
141
  global log_level
@@ -0,0 +1,182 @@
1
+ interactions:
2
+ - request:
3
+ headers:
4
+ accept:
5
+ - '*/*'
6
+ accept-encoding:
7
+ - gzip, deflate
8
+ connection:
9
+ - keep-alive
10
+ content-length:
11
+ - '468'
12
+ content-type:
13
+ - application/json
14
+ host:
15
+ - generativelanguage.googleapis.com
16
+ method: POST
17
+ parsed_body:
18
+ contents:
19
+ - parts:
20
+ - text: run bar for me please
21
+ role: user
22
+ toolConfig:
23
+ function_calling_config:
24
+ allowed_function_names:
25
+ - bar
26
+ - final_result
27
+ mode: ANY
28
+ tools:
29
+ functionDeclarations:
30
+ - description: ''
31
+ name: bar
32
+ parameters:
33
+ properties: {}
34
+ type: object
35
+ - description: The final response which ends this conversation
36
+ name: final_result
37
+ parameters:
38
+ properties:
39
+ bar:
40
+ type: string
41
+ required:
42
+ - bar
43
+ type: object
44
+ uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
45
+ response:
46
+ headers:
47
+ alt-svc:
48
+ - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
49
+ content-length:
50
+ - '721'
51
+ content-type:
52
+ - application/json; charset=UTF-8
53
+ server-timing:
54
+ - gfet4t7; dur=618
55
+ transfer-encoding:
56
+ - chunked
57
+ vary:
58
+ - Origin
59
+ - X-Origin
60
+ - Referer
61
+ parsed_body:
62
+ candidates:
63
+ - avgLogprobs: 2.094004230457358e-05
64
+ content:
65
+ parts:
66
+ - functionCall:
67
+ args: {}
68
+ name: bar
69
+ role: model
70
+ finishReason: STOP
71
+ modelVersion: gemini-2.0-flash
72
+ responseId: t61QaPKoBZSF_NUPqYHxmAg
73
+ usageMetadata:
74
+ candidatesTokenCount: 1
75
+ candidatesTokensDetails:
76
+ - modality: TEXT
77
+ tokenCount: 1
78
+ promptTokenCount: 21
79
+ promptTokensDetails:
80
+ - modality: TEXT
81
+ tokenCount: 21
82
+ totalTokenCount: 22
83
+ status:
84
+ code: 200
85
+ message: OK
86
+ - request:
87
+ headers:
88
+ accept:
89
+ - '*/*'
90
+ accept-encoding:
91
+ - gzip, deflate
92
+ connection:
93
+ - keep-alive
94
+ content-length:
95
+ - '635'
96
+ content-type:
97
+ - application/json
98
+ host:
99
+ - generativelanguage.googleapis.com
100
+ method: POST
101
+ parsed_body:
102
+ contents:
103
+ - parts:
104
+ - text: run bar for me please
105
+ role: user
106
+ - parts:
107
+ - functionCall:
108
+ args: {}
109
+ name: bar
110
+ role: model
111
+ - parts:
112
+ - functionResponse:
113
+ name: bar
114
+ response:
115
+ return_value: hello
116
+ role: user
117
+ toolConfig:
118
+ function_calling_config:
119
+ allowed_function_names:
120
+ - bar
121
+ - final_result
122
+ mode: ANY
123
+ tools:
124
+ functionDeclarations:
125
+ - description: ''
126
+ name: bar
127
+ parameters:
128
+ properties: {}
129
+ type: object
130
+ - description: The final response which ends this conversation
131
+ name: final_result
132
+ parameters:
133
+ properties:
134
+ bar:
135
+ type: string
136
+ required:
137
+ - bar
138
+ type: object
139
+ uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
140
+ response:
141
+ headers:
142
+ alt-svc:
143
+ - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
144
+ content-length:
145
+ - '776'
146
+ content-type:
147
+ - application/json; charset=UTF-8
148
+ server-timing:
149
+ - gfet4t7; dur=674
150
+ transfer-encoding:
151
+ - chunked
152
+ vary:
153
+ - Origin
154
+ - X-Origin
155
+ - Referer
156
+ parsed_body:
157
+ candidates:
158
+ - avgLogprobs: -0.002446441538631916
159
+ content:
160
+ parts:
161
+ - functionCall:
162
+ args:
163
+ bar: hello
164
+ name: final_result
165
+ role: model
166
+ finishReason: STOP
167
+ modelVersion: gemini-2.0-flash
168
+ responseId: t61QaMaQJ-qm1PIPwJSz4AI
169
+ usageMetadata:
170
+ candidatesTokenCount: 5
171
+ candidatesTokensDetails:
172
+ - modality: TEXT
173
+ tokenCount: 5
174
+ promptTokenCount: 27
175
+ promptTokensDetails:
176
+ - modality: TEXT
177
+ tokenCount: 27
178
+ totalTokenCount: 32
179
+ status:
180
+ code: 200
181
+ message: OK
182
+ version: 1
@@ -0,0 +1,64 @@
1
+ interactions:
2
+ - request:
3
+ headers:
4
+ accept:
5
+ - '*/*'
6
+ accept-encoding:
7
+ - gzip, deflate
8
+ connection:
9
+ - keep-alive
10
+ content-length:
11
+ - '87'
12
+ content-type:
13
+ - application/json
14
+ host:
15
+ - generativelanguage.googleapis.com
16
+ method: POST
17
+ parsed_body:
18
+ contents:
19
+ - parts:
20
+ - text: Hello!
21
+ role: user
22
+ generationConfig: {}
23
+ uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent
24
+ response:
25
+ headers:
26
+ alt-svc:
27
+ - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
28
+ content-length:
29
+ - '687'
30
+ content-type:
31
+ - application/json; charset=UTF-8
32
+ server-timing:
33
+ - gfet4t7; dur=304
34
+ transfer-encoding:
35
+ - chunked
36
+ vary:
37
+ - Origin
38
+ - X-Origin
39
+ - Referer
40
+ parsed_body:
41
+ candidates:
42
+ - avgLogprobs: -0.0009780019860376012
43
+ content:
44
+ parts:
45
+ - text: |
46
+ Hello there! How can I help you today?
47
+ role: model
48
+ finishReason: STOP
49
+ modelVersion: gemini-1.5-flash
50
+ responseId: KKRRaJyZNJiFm9IPzMfNiAk
51
+ usageMetadata:
52
+ candidatesTokenCount: 11
53
+ candidatesTokensDetails:
54
+ - modality: TEXT
55
+ tokenCount: 11
56
+ promptTokenCount: 2
57
+ promptTokensDetails:
58
+ - modality: TEXT
59
+ tokenCount: 2
60
+ totalTokenCount: 13
61
+ status:
62
+ code: 200
63
+ message: OK
64
+ version: 1
@@ -0,0 +1,180 @@
1
+ interactions:
2
+ - request:
3
+ headers:
4
+ accept:
5
+ - '*/*'
6
+ accept-encoding:
7
+ - gzip, deflate
8
+ connection:
9
+ - keep-alive
10
+ content-length:
11
+ - '477'
12
+ content-type:
13
+ - application/json
14
+ host:
15
+ - generativelanguage.googleapis.com
16
+ method: POST
17
+ parsed_body:
18
+ contents:
19
+ - parts:
20
+ - text: run bar for me please
21
+ role: user
22
+ generationConfig: {}
23
+ toolConfig:
24
+ functionCallingConfig:
25
+ mode: ANY
26
+ tools:
27
+ - functionDeclarations:
28
+ - description: ''
29
+ name: bar
30
+ parameters:
31
+ properties: {}
32
+ type: OBJECT
33
+ - description: The final response which ends this conversation
34
+ name: final_result
35
+ parameters:
36
+ properties:
37
+ bar:
38
+ type: STRING
39
+ required:
40
+ - bar
41
+ type: OBJECT
42
+ uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
43
+ response:
44
+ headers:
45
+ alt-svc:
46
+ - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
47
+ content-length:
48
+ - '721'
49
+ content-type:
50
+ - application/json; charset=UTF-8
51
+ server-timing:
52
+ - gfet4t7; dur=720
53
+ transfer-encoding:
54
+ - chunked
55
+ vary:
56
+ - Origin
57
+ - X-Origin
58
+ - Referer
59
+ parsed_body:
60
+ candidates:
61
+ - avgLogprobs: 2.094004230457358e-05
62
+ content:
63
+ parts:
64
+ - functionCall:
65
+ args: {}
66
+ name: bar
67
+ role: model
68
+ finishReason: STOP
69
+ modelVersion: gemini-2.0-flash
70
+ responseId: Ba1QaMKCL-qm1PIPwJSz4AI
71
+ usageMetadata:
72
+ candidatesTokenCount: 1
73
+ candidatesTokensDetails:
74
+ - modality: TEXT
75
+ tokenCount: 1
76
+ promptTokenCount: 21
77
+ promptTokensDetails:
78
+ - modality: TEXT
79
+ tokenCount: 21
80
+ totalTokenCount: 22
81
+ status:
82
+ code: 200
83
+ message: OK
84
+ - request:
85
+ headers:
86
+ accept:
87
+ - '*/*'
88
+ accept-encoding:
89
+ - gzip, deflate
90
+ connection:
91
+ - keep-alive
92
+ content-length:
93
+ - '759'
94
+ content-type:
95
+ - application/json
96
+ host:
97
+ - generativelanguage.googleapis.com
98
+ method: POST
99
+ parsed_body:
100
+ contents:
101
+ - parts:
102
+ - text: run bar for me please
103
+ role: user
104
+ - parts:
105
+ - functionCall:
106
+ args: {}
107
+ id: pyd_ai_4809c3117a3d4ed398851cb98f8ec303
108
+ name: bar
109
+ role: model
110
+ - parts:
111
+ - functionResponse:
112
+ id: pyd_ai_4809c3117a3d4ed398851cb98f8ec303
113
+ name: bar
114
+ response:
115
+ return_value: hello
116
+ role: user
117
+ generationConfig: {}
118
+ toolConfig:
119
+ functionCallingConfig:
120
+ mode: ANY
121
+ tools:
122
+ - functionDeclarations:
123
+ - description: ''
124
+ name: bar
125
+ parameters:
126
+ properties: {}
127
+ type: OBJECT
128
+ - description: The final response which ends this conversation
129
+ name: final_result
130
+ parameters:
131
+ properties:
132
+ bar:
133
+ type: STRING
134
+ required:
135
+ - bar
136
+ type: OBJECT
137
+ uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
138
+ response:
139
+ headers:
140
+ alt-svc:
141
+ - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
142
+ content-length:
143
+ - '776'
144
+ content-type:
145
+ - application/json; charset=UTF-8
146
+ server-timing:
147
+ - gfet4t7; dur=589
148
+ transfer-encoding:
149
+ - chunked
150
+ vary:
151
+ - Origin
152
+ - X-Origin
153
+ - Referer
154
+ parsed_body:
155
+ candidates:
156
+ - avgLogprobs: -0.002446441538631916
157
+ content:
158
+ parts:
159
+ - functionCall:
160
+ args:
161
+ bar: hello
162
+ name: final_result
163
+ role: model
164
+ finishReason: STOP
165
+ modelVersion: gemini-2.0-flash
166
+ responseId: Bq1QaNCkF5SF_NUPqYHxmAg
167
+ usageMetadata:
168
+ candidatesTokenCount: 5
169
+ candidatesTokensDetails:
170
+ - modality: TEXT
171
+ tokenCount: 5
172
+ promptTokenCount: 27
173
+ promptTokensDetails:
174
+ - modality: TEXT
175
+ tokenCount: 27
176
+ totalTokenCount: 32
177
+ status:
178
+ code: 200
179
+ message: OK
180
+ version: 1
@@ -1398,3 +1398,84 @@ async def test_response_with_thought_part(get_gemini_client: GetGeminiClient):
1398
1398
 
1399
1399
  assert result.output == 'Hello from thought test'
1400
1400
  assert result.usage() == snapshot(Usage(requests=1, request_tokens=1, response_tokens=2, total_tokens=3))
1401
+
1402
+
1403
+ @pytest.mark.vcr()
1404
+ async def test_gemini_tool_config_any_with_tool_without_args(allow_model_requests: None, gemini_api_key: str):
1405
+ class Foo(BaseModel):
1406
+ bar: str
1407
+
1408
+ m = GeminiModel('gemini-2.0-flash', provider=GoogleGLAProvider(api_key=gemini_api_key))
1409
+ agent = Agent(m, output_type=Foo)
1410
+
1411
+ @agent.tool_plain
1412
+ async def bar() -> str:
1413
+ return 'hello'
1414
+
1415
+ result = await agent.run('run bar for me please')
1416
+ assert result.all_messages() == snapshot(
1417
+ [
1418
+ ModelRequest(
1419
+ parts=[
1420
+ UserPromptPart(
1421
+ content='run bar for me please',
1422
+ timestamp=IsDatetime(),
1423
+ )
1424
+ ]
1425
+ ),
1426
+ ModelResponse(
1427
+ parts=[ToolCallPart(tool_name='bar', args={}, tool_call_id=IsStr())],
1428
+ usage=Usage(
1429
+ requests=1,
1430
+ request_tokens=21,
1431
+ response_tokens=1,
1432
+ total_tokens=22,
1433
+ details={'text_candidates_tokens': 1, 'text_prompt_tokens': 21},
1434
+ ),
1435
+ model_name='gemini-2.0-flash',
1436
+ timestamp=IsDatetime(),
1437
+ vendor_details={'finish_reason': 'STOP'},
1438
+ vendor_id=IsStr(),
1439
+ ),
1440
+ ModelRequest(
1441
+ parts=[
1442
+ ToolReturnPart(
1443
+ tool_name='bar',
1444
+ content='hello',
1445
+ tool_call_id=IsStr(),
1446
+ timestamp=IsDatetime(),
1447
+ )
1448
+ ]
1449
+ ),
1450
+ ModelResponse(
1451
+ parts=[
1452
+ ToolCallPart(
1453
+ tool_name='final_result',
1454
+ args={'bar': 'hello'},
1455
+ tool_call_id=IsStr(),
1456
+ )
1457
+ ],
1458
+ usage=Usage(
1459
+ requests=1,
1460
+ request_tokens=27,
1461
+ response_tokens=5,
1462
+ total_tokens=32,
1463
+ details={'text_candidates_tokens': 5, 'text_prompt_tokens': 27},
1464
+ ),
1465
+ model_name='gemini-2.0-flash',
1466
+ timestamp=IsDatetime(),
1467
+ vendor_details={'finish_reason': 'STOP'},
1468
+ vendor_id=IsStr(),
1469
+ ),
1470
+ ModelRequest(
1471
+ parts=[
1472
+ ToolReturnPart(
1473
+ tool_name='final_result',
1474
+ content='Final result processed.',
1475
+ tool_call_id=IsStr(),
1476
+ timestamp=IsDatetime(),
1477
+ )
1478
+ ]
1479
+ ),
1480
+ ]
1481
+ )
@@ -6,7 +6,7 @@ from dataclasses import dataclass
6
6
  from typing import Any, Union
7
7
 
8
8
  import pytest
9
- from httpx import Request
9
+ from httpx import Request, Timeout
10
10
  from inline_snapshot import Is, snapshot
11
11
  from pytest_mock import MockerFixture
12
12
  from typing_extensions import TypedDict
@@ -726,3 +726,94 @@ async def test_google_gs_url_force_download_raises_user_error(allow_model_reques
726
726
  url = ImageUrl(url='gs://pydantic-ai-dev/wikipedia_screenshot.png', force_download=True)
727
727
  with pytest.raises(UserError, match='Downloading from protocol "gs://" is not supported.'):
728
728
  _ = await agent.run(['What is the main content of this URL?', url])
729
+
730
+
731
+ async def test_google_tool_config_any_with_tool_without_args(
732
+ allow_model_requests: None, google_provider: GoogleProvider
733
+ ):
734
+ class Foo(TypedDict):
735
+ bar: str
736
+
737
+ m = GoogleModel('gemini-2.0-flash', provider=google_provider)
738
+ agent = Agent(m, output_type=Foo)
739
+
740
+ @agent.tool_plain
741
+ async def bar() -> str:
742
+ return 'hello'
743
+
744
+ result = await agent.run('run bar for me please')
745
+ assert result.all_messages() == snapshot(
746
+ [
747
+ ModelRequest(
748
+ parts=[
749
+ UserPromptPart(
750
+ content='run bar for me please',
751
+ timestamp=IsDatetime(),
752
+ )
753
+ ]
754
+ ),
755
+ ModelResponse(
756
+ parts=[ToolCallPart(tool_name='bar', args={}, tool_call_id=IsStr())],
757
+ usage=Usage(
758
+ requests=1,
759
+ request_tokens=21,
760
+ response_tokens=1,
761
+ total_tokens=22,
762
+ details={'text_candidates_tokens': 1, 'text_prompt_tokens': 21},
763
+ ),
764
+ model_name='gemini-2.0-flash',
765
+ timestamp=IsDatetime(),
766
+ vendor_details={'finish_reason': 'STOP'},
767
+ ),
768
+ ModelRequest(
769
+ parts=[
770
+ ToolReturnPart(
771
+ tool_name='bar',
772
+ content='hello',
773
+ tool_call_id=IsStr(),
774
+ timestamp=IsDatetime(),
775
+ )
776
+ ]
777
+ ),
778
+ ModelResponse(
779
+ parts=[
780
+ ToolCallPart(
781
+ tool_name='final_result',
782
+ args={'bar': 'hello'},
783
+ tool_call_id=IsStr(),
784
+ )
785
+ ],
786
+ usage=Usage(
787
+ requests=1,
788
+ request_tokens=27,
789
+ response_tokens=5,
790
+ total_tokens=32,
791
+ details={'text_candidates_tokens': 5, 'text_prompt_tokens': 27},
792
+ ),
793
+ model_name='gemini-2.0-flash',
794
+ timestamp=IsDatetime(),
795
+ vendor_details={'finish_reason': 'STOP'},
796
+ ),
797
+ ModelRequest(
798
+ parts=[
799
+ ToolReturnPart(
800
+ tool_name='final_result',
801
+ content='Final result processed.',
802
+ tool_call_id=IsStr(),
803
+ timestamp=IsDatetime(),
804
+ )
805
+ ]
806
+ ),
807
+ ]
808
+ )
809
+
810
+
811
+ async def test_google_timeout(allow_model_requests: None, google_provider: GoogleProvider):
812
+ model = GoogleModel('gemini-1.5-flash', provider=google_provider)
813
+ agent = Agent(model=model)
814
+
815
+ result = await agent.run('Hello!', model_settings={'timeout': 10})
816
+ assert result.output == snapshot('Hello there! How can I help you today?\n')
817
+
818
+ with pytest.raises(UserError, match='Google does not support setting ModelSettings.timeout to a httpx.Timeout'):
819
+ await agent.run('Hello!', model_settings={'timeout': Timeout(10)})
@@ -65,3 +65,10 @@ def test_infer_provider(provider: str, provider_cls: type[Provider[Any]], except
65
65
  infer_provider(provider)
66
66
  else:
67
67
  assert isinstance(infer_provider(provider), provider_cls)
68
+
69
+
70
+ @pytest.mark.parametrize(('provider', 'provider_cls', 'exception_has'), test_infer_provider_params)
71
+ def test_infer_provider_class(provider: str, provider_cls: type[Provider[Any]], exception_has: str | None):
72
+ from pydantic_ai.providers import infer_provider_class
73
+
74
+ assert infer_provider_class(provider) == provider_cls
@@ -2425,6 +2425,10 @@ def test_instructions_raise_error_when_instructions_is_set():
2425
2425
  def instructions() -> str:
2426
2426
  return 'An instructions!'
2427
2427
 
2428
+ @agent.instructions
2429
+ def empty_instructions() -> str:
2430
+ return ''
2431
+
2428
2432
  result = agent.run_sync('Hello')
2429
2433
  assert result.all_messages()[0] == snapshot(
2430
2434
  ModelRequest(
@@ -2512,7 +2516,10 @@ def test_instructions_parameter_with_sequence():
2512
2516
  def instructions() -> str:
2513
2517
  return 'You are a potato.'
2514
2518
 
2515
- agent = Agent('test', instructions=('You are a helpful assistant.', instructions))
2519
+ def empty_instructions() -> str:
2520
+ return ''
2521
+
2522
+ agent = Agent('test', instructions=('You are a helpful assistant.', empty_instructions, instructions))
2516
2523
  result = agent.run_sync('Hello')
2517
2524
  assert result.all_messages()[0] == snapshot(
2518
2525
  ModelRequest(