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.
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/PKG-INFO +3 -3
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/mcp_server.py +18 -0
- pydantic_ai-0.2.20/tests/models/cassettes/test_gemini/test_gemini_tool_config_any_with_tool_without_args.yaml +182 -0
- pydantic_ai-0.2.20/tests/models/cassettes/test_google/test_google_timeout.yaml +64 -0
- pydantic_ai-0.2.20/tests/models/cassettes/test_google/test_google_tool_config_any_with_tool_without_args.yaml +180 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_gemini.py +81 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_google.py +92 -1
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_provider_names.py +7 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_agent.py +8 -1
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_examples.py +3 -3
- pydantic_ai-0.2.20/tests/test_history_processor.py +303 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_mcp.py +49 -5
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_streaming.py +120 -1
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_utils.py +25 -1
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/.gitignore +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/LICENSE +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/Makefile +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/README.md +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/pyproject.toml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/dummy.pdf +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/kiwi.png +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/marcelo.mp3 +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/assets/small_video.mp4 +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_agent_with_stdio_server.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_audio_resource.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_dict.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_error.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_image.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_image_resource.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_multiple_items.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_none.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_str.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_mcp/test_tool_returning_text_resource.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[anthropic].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[bedrock].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[cohere].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[gemini].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[google].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[groq].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[mistral].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/cassettes/test_settings/test_stop_settings[openai].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/conftest.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_dataset.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_base.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_common.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_context.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluator_spec.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_evaluators.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_llm_as_a_judge.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_otel.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_render_numbers.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_reporting.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_reports.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/test_utils.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/evals/utils.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/README.md +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/bank_database.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/fake_database.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/example_modules/weather_service.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/ext/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/ext/test_langchain.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/fasta2a/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/fasta2a/test_applications.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_file_persistence.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_graph.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_mermaid.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_persistence.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_state.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/graph/test_utils.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/import_examples.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/json_body_serializer.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/__init__.py +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_anthropic_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_document_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_extra_headers.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_image_url_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_multiple_parallel_tool_calls.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_anthropic/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_empty_system_prompt.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_guardrail_config.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_iter_stream.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_max_tokens.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_other_parameters.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_performance_config.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_retry.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_stream.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_structured_response.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_model_top_p.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_bedrock_multiple_documents_in_history.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_text_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_video_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_bedrock/test_video_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_cohere/test_cohere_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_cohere/test_request_simple_success_with_vcr.yaml +0 -0
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_false.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_true.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_drop_exclusive_maximum.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_exclusive_minimum_and_maximum.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_gemini_youtube_video_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_image_as_binary_content_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_image_url_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_video_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini/test_video_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_labels.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[AudioUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[AudioUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[DocumentUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[DocumentUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[ImageUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[ImageUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl (YouTube)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input[VideoUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_gemini_vertex/test_url_input_force_download.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_empty_user_prompt.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_image_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_iter_stream.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_max_tokens.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_retry.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_safety_settings.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_stream.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_structured_response.yaml +0 -0
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_thinking_config.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_top_p.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_vertex_labels.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_vertex_provider.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_model_video_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[AudioUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[AudioUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[DocumentUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[DocumentUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[ImageUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[ImageUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl (YouTube)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl (gs)].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input[VideoUrl].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_google/test_google_url_input_force_download.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_extra_headers.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_groq_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_image_as_binary_content_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_groq/test_image_url_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_mistral/test_mistral_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_model_names/test_known_model_names.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_audio_as_binary_content_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_document_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_extra_headers.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_image_as_binary_content_input.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_image_url_tool_response.yaml +0 -0
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_max_completion_tokens[o3-mini].yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_multiple_agent_tool_calls.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_audio_url_input.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_instructions.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_openai_model_without_system_prompt.yaml +0 -0
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_reasoning_model_with_temperature.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai/test_user_id.yaml +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_instructions.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_retry.yaml +0 -0
- {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
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_output_type.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_effort.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_stream.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_openai_responses_system_prompt.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/cassettes/test_openai_responses/test_reasoning_model_with_temperature.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/mock_async_stream.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_anthropic.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_bedrock.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_cohere.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_download_item.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_fallback.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_gemini_vertex.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_groq.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_instrumented.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_mistral.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_function.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_names.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_request_parameters.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_model_test.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_openai.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/models/test_openai_responses.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/__init__.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_azure/test_azure_provider_call.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_google_vertex/test_vertexai_provider.yaml +0 -0
- {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
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/cassettes/test_openrouter/test_openrouter_with_google_model.yaml +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_anthropic.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_azure.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_bedrock.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_cohere.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_deepseek.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_fireworks.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_google_gla.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_google_vertex.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_grok.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_groq.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_heroku.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_mistral.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_openai.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_openrouter.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/providers/test_together.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_a2a.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_cli.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_deps.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_direct.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_format_as_xml.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_json_body_serializer.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_live.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_logfire.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_messages.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_parts_manager.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_settings.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_tools.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/test_usage_limits.py +0 -0
- {pydantic_ai-0.2.18 → pydantic_ai-0.2.20}/tests/typed_agent.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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(
|