pydantic-ai-slim 0.7.3__tar.gz → 0.7.4__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-slim might be problematic. Click here for more details.

Files changed (116) hide show
  1. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/PKG-INFO +3 -3
  2. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/__init__.py +2 -1
  3. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/builtin_tools.py +9 -1
  4. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/google.py +17 -10
  5. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/tools.py +5 -2
  6. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/usage.py +1 -1
  7. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/.gitignore +0 -0
  8. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/LICENSE +0 -0
  9. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/README.md +0 -0
  10. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/__main__.py +0 -0
  11. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_a2a.py +0 -0
  12. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_agent_graph.py +0 -0
  13. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_cli.py +0 -0
  14. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_function_schema.py +0 -0
  15. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_griffe.py +0 -0
  16. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_mcp.py +0 -0
  17. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_output.py +0 -0
  18. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_parts_manager.py +0 -0
  19. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_run_context.py +0 -0
  20. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_system_prompt.py +0 -0
  21. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_thinking_part.py +0 -0
  22. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_tool_manager.py +0 -0
  23. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/_utils.py +0 -0
  24. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/ag_ui.py +0 -0
  25. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/agent/__init__.py +0 -0
  26. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/agent/abstract.py +0 -0
  27. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/agent/wrapper.py +0 -0
  28. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/common_tools/__init__.py +0 -0
  29. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/common_tools/duckduckgo.py +0 -0
  30. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/common_tools/tavily.py +0 -0
  31. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/direct.py +0 -0
  32. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/__init__.py +0 -0
  33. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
  34. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
  35. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
  36. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
  37. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
  38. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
  39. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  40. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
  41. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/exceptions.py +0 -0
  42. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/ext/__init__.py +0 -0
  43. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/ext/aci.py +0 -0
  44. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/ext/langchain.py +0 -0
  45. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/format_prompt.py +0 -0
  46. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/mcp.py +0 -0
  47. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/messages.py +0 -0
  48. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/__init__.py +0 -0
  49. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/anthropic.py +0 -0
  50. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/bedrock.py +0 -0
  51. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/cohere.py +0 -0
  52. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/fallback.py +0 -0
  53. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/function.py +0 -0
  54. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/gemini.py +0 -0
  55. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/groq.py +0 -0
  56. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/huggingface.py +0 -0
  57. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/instrumented.py +0 -0
  58. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/mcp_sampling.py +0 -0
  59. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/mistral.py +0 -0
  60. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/openai.py +0 -0
  61. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/test.py +0 -0
  62. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/models/wrapper.py +0 -0
  63. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/output.py +0 -0
  64. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/__init__.py +0 -0
  65. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/_json_schema.py +0 -0
  66. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/amazon.py +0 -0
  67. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/anthropic.py +0 -0
  68. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/cohere.py +0 -0
  69. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/deepseek.py +0 -0
  70. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/google.py +0 -0
  71. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/grok.py +0 -0
  72. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/groq.py +0 -0
  73. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/meta.py +0 -0
  74. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/mistral.py +0 -0
  75. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/moonshotai.py +0 -0
  76. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/openai.py +0 -0
  77. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/profiles/qwen.py +0 -0
  78. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/__init__.py +0 -0
  79. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/anthropic.py +0 -0
  80. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/azure.py +0 -0
  81. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/bedrock.py +0 -0
  82. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/cohere.py +0 -0
  83. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/deepseek.py +0 -0
  84. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/fireworks.py +0 -0
  85. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/github.py +0 -0
  86. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/google.py +0 -0
  87. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/google_gla.py +0 -0
  88. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/google_vertex.py +0 -0
  89. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/grok.py +0 -0
  90. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/groq.py +0 -0
  91. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/heroku.py +0 -0
  92. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/huggingface.py +0 -0
  93. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/mistral.py +0 -0
  94. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/moonshotai.py +0 -0
  95. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/ollama.py +0 -0
  96. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/openai.py +0 -0
  97. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/openrouter.py +0 -0
  98. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/together.py +0 -0
  99. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/providers/vercel.py +0 -0
  100. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/py.typed +0 -0
  101. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/result.py +0 -0
  102. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/retries.py +0 -0
  103. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/run.py +0 -0
  104. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/settings.py +0 -0
  105. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/__init__.py +0 -0
  106. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/_dynamic.py +0 -0
  107. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/abstract.py +0 -0
  108. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/combined.py +0 -0
  109. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/deferred.py +0 -0
  110. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/filtered.py +0 -0
  111. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/function.py +0 -0
  112. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/prefixed.py +0 -0
  113. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/prepared.py +0 -0
  114. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/renamed.py +0 -0
  115. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pydantic_ai/toolsets/wrapper.py +0 -0
  116. {pydantic_ai_slim-0.7.3 → pydantic_ai_slim-0.7.4}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-slim
3
- Version: 0.7.3
3
+ Version: 0.7.4
4
4
  Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
5
5
  Project-URL: Homepage, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
6
6
  Project-URL: Source, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
@@ -35,7 +35,7 @@ Requires-Dist: genai-prices>=0.0.22
35
35
  Requires-Dist: griffe>=1.3.2
36
36
  Requires-Dist: httpx>=0.27
37
37
  Requires-Dist: opentelemetry-api>=1.28.0
38
- Requires-Dist: pydantic-graph==0.7.3
38
+ Requires-Dist: pydantic-graph==0.7.4
39
39
  Requires-Dist: pydantic>=2.10
40
40
  Requires-Dist: typing-inspection>=0.4.0
41
41
  Provides-Extra: a2a
@@ -57,7 +57,7 @@ Requires-Dist: cohere>=5.16.0; (platform_system != 'Emscripten') and extra == 'c
57
57
  Provides-Extra: duckduckgo
58
58
  Requires-Dist: ddgs>=9.0.0; extra == 'duckduckgo'
59
59
  Provides-Extra: evals
60
- Requires-Dist: pydantic-evals==0.7.3; extra == 'evals'
60
+ Requires-Dist: pydantic-evals==0.7.4; extra == 'evals'
61
61
  Provides-Extra: google
62
62
  Requires-Dist: google-genai>=1.28.0; extra == 'google'
63
63
  Provides-Extra: groq
@@ -1,7 +1,7 @@
1
1
  from importlib.metadata import version as _metadata_version
2
2
 
3
3
  from .agent import Agent, CallToolsNode, EndStrategy, ModelRequestNode, UserPromptNode, capture_run_messages
4
- from .builtin_tools import CodeExecutionTool, WebSearchTool, WebSearchUserLocation
4
+ from .builtin_tools import CodeExecutionTool, UrlContextTool, WebSearchTool, WebSearchUserLocation
5
5
  from .exceptions import (
6
6
  AgentRunError,
7
7
  FallbackExceptionGroup,
@@ -45,6 +45,7 @@ __all__ = (
45
45
  # builtin_tools
46
46
  'WebSearchTool',
47
47
  'WebSearchUserLocation',
48
+ 'UrlContextTool',
48
49
  'CodeExecutionTool',
49
50
  # output
50
51
  'ToolOutput',
@@ -6,7 +6,7 @@ from typing import Literal
6
6
 
7
7
  from typing_extensions import TypedDict
8
8
 
9
- __all__ = ('AbstractBuiltinTool', 'WebSearchTool', 'WebSearchUserLocation', 'CodeExecutionTool')
9
+ __all__ = ('AbstractBuiltinTool', 'WebSearchTool', 'WebSearchUserLocation', 'CodeExecutionTool', 'UrlContextTool')
10
10
 
11
11
 
12
12
  @dataclass
@@ -103,3 +103,11 @@ class CodeExecutionTool(AbstractBuiltinTool):
103
103
  * OpenAI
104
104
  * Google
105
105
  """
106
+
107
+
108
+ class UrlContextTool(AbstractBuiltinTool):
109
+ """Allows your agent to access contents from URLs.
110
+
111
+ Supported by:
112
+ * Google
113
+ """
@@ -13,7 +13,7 @@ from typing_extensions import assert_never
13
13
  from .. import UnexpectedModelBehavior, _utils, usage
14
14
  from .._output import OutputObjectDefinition
15
15
  from .._run_context import RunContext
16
- from ..builtin_tools import CodeExecutionTool, WebSearchTool
16
+ from ..builtin_tools import CodeExecutionTool, UrlContextTool, WebSearchTool
17
17
  from ..exceptions import UserError
18
18
  from ..messages import (
19
19
  BinaryContent,
@@ -72,6 +72,7 @@ try:
72
72
  ToolConfigDict,
73
73
  ToolDict,
74
74
  ToolListUnionDict,
75
+ UrlContextDict,
75
76
  )
76
77
 
77
78
  from ..providers.google import GoogleProvider
@@ -218,7 +219,7 @@ class GoogleModel(Model):
218
219
  )
219
220
  if self._provider.name != 'google-gla':
220
221
  # The fields are not supported by the Gemini API per https://github.com/googleapis/python-genai/blob/7e4ec284dc6e521949626f3ed54028163ef9121d/google/genai/models.py#L1195-L1214
221
- config.update(
222
+ config.update( # pragma: lax no cover
222
223
  system_instruction=generation_config.get('system_instruction'),
223
224
  tools=cast(list[ToolDict], generation_config.get('tools')),
224
225
  # Annoyingly, GenerationConfigDict has fewer fields than GenerateContentConfigDict, and no extra fields are allowed.
@@ -270,6 +271,8 @@ class GoogleModel(Model):
270
271
  for tool in model_request_parameters.builtin_tools:
271
272
  if isinstance(tool, WebSearchTool):
272
273
  tools.append(ToolDict(google_search=GoogleSearchDict()))
274
+ elif isinstance(tool, UrlContextTool):
275
+ tools.append(ToolDict(url_context=UrlContextDict()))
273
276
  elif isinstance(tool, CodeExecutionTool): # pragma: no branch
274
277
  tools.append(ToolDict(code_execution=ToolCodeExecutionDict()))
275
278
  else: # pragma: no cover
@@ -374,17 +377,18 @@ class GoogleModel(Model):
374
377
  def _process_response(self, response: GenerateContentResponse) -> ModelResponse:
375
378
  if not response.candidates or len(response.candidates) != 1:
376
379
  raise UnexpectedModelBehavior('Expected exactly one candidate in Gemini response') # pragma: no cover
377
- if response.candidates[0].content is None or response.candidates[0].content.parts is None:
378
- if response.candidates[0].finish_reason == 'SAFETY':
380
+ candidate = response.candidates[0]
381
+ if candidate.content is None or candidate.content.parts is None:
382
+ if candidate.finish_reason == 'SAFETY':
379
383
  raise UnexpectedModelBehavior('Safety settings triggered', str(response))
380
384
  else:
381
385
  raise UnexpectedModelBehavior(
382
386
  'Content field missing from Gemini response', str(response)
383
387
  ) # pragma: no cover
384
- parts = response.candidates[0].content.parts or []
388
+ parts = candidate.content.parts or []
385
389
  vendor_id = response.response_id or None
386
390
  vendor_details: dict[str, Any] | None = None
387
- finish_reason = response.candidates[0].finish_reason
391
+ finish_reason = candidate.finish_reason
388
392
  if finish_reason: # pragma: no branch
389
393
  vendor_details = {'finish_reason': finish_reason.value}
390
394
  usage = _metadata_as_usage(response)
@@ -526,10 +530,13 @@ class GeminiStreamedResponse(StreamedResponse):
526
530
 
527
531
  assert chunk.candidates is not None
528
532
  candidate = chunk.candidates[0]
529
- if candidate.content is None:
530
- raise UnexpectedModelBehavior('Streamed response has no content field') # pragma: no cover
531
- assert candidate.content.parts is not None
532
- for part in candidate.content.parts:
533
+ if candidate.content is None or candidate.content.parts is None:
534
+ if candidate.finish_reason == 'SAFETY': # pragma: no cover
535
+ raise UnexpectedModelBehavior('Safety settings triggered', str(chunk))
536
+ else: # pragma: no cover
537
+ raise UnexpectedModelBehavior('Content field missing from streaming Gemini response', str(chunk))
538
+ parts = candidate.content.parts or []
539
+ for part in parts:
533
540
  if part.text is not None:
534
541
  if part.thought:
535
542
  yield self._parts_manager.handle_thinking_delta(vendor_part_id='thinking', content=part.text)
@@ -266,6 +266,7 @@ class Tool(Generic[AgentDepsT]):
266
266
  name: str,
267
267
  description: str | None,
268
268
  json_schema: JsonSchemaValue,
269
+ takes_ctx: bool = False,
269
270
  ) -> Self:
270
271
  """Creates a Pydantic tool from a function and a JSON schema.
271
272
 
@@ -277,6 +278,8 @@ class Tool(Generic[AgentDepsT]):
277
278
  description: Used to tell the model how/when/why to use the tool.
278
279
  You can provide few-shot examples as a part of the description.
279
280
  json_schema: The schema for the function arguments
281
+ takes_ctx: An optional boolean parameter indicating whether the function
282
+ accepts the context object as an argument.
280
283
 
281
284
  Returns:
282
285
  A Pydantic tool that calls the function
@@ -286,13 +289,13 @@ class Tool(Generic[AgentDepsT]):
286
289
  description=description,
287
290
  validator=SchemaValidator(schema=core_schema.any_schema()),
288
291
  json_schema=json_schema,
289
- takes_ctx=False,
292
+ takes_ctx=takes_ctx,
290
293
  is_async=_utils.is_async_callable(function),
291
294
  )
292
295
 
293
296
  return cls(
294
297
  function,
295
- takes_ctx=False,
298
+ takes_ctx=takes_ctx,
296
299
  name=name,
297
300
  description=description,
298
301
  function_schema=function_schema,
@@ -292,7 +292,7 @@ class UsageLimits:
292
292
 
293
293
  total_tokens = usage.total_tokens
294
294
  if self.total_tokens_limit is not None and total_tokens > self.total_tokens_limit:
295
- raise UsageLimitExceeded(
295
+ raise UsageLimitExceeded( # pragma: lax no cover
296
296
  f'The next request would exceed the total_tokens_limit of {self.total_tokens_limit} ({total_tokens=})'
297
297
  )
298
298