pydantic-ai-slim 0.7.3__py3-none-any.whl → 0.7.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

pydantic_ai/__init__.py CHANGED
@@ -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)
pydantic_ai/tools.py CHANGED
@@ -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,
pydantic_ai/usage.py CHANGED
@@ -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
 
@@ -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,4 +1,4 @@
1
- pydantic_ai/__init__.py,sha256=Uy0J4BgX4CXsa0sUUb5K0FC4uUWGIwBici93QHLkNsk,1478
1
+ pydantic_ai/__init__.py,sha256=i_AteC7yah1Z55PO7JNa3po2-mC10RoefDG-N6Vp4CQ,1516
2
2
  pydantic_ai/__main__.py,sha256=Q_zJU15DUA01YtlJ2mnaLCoId2YmgmreVEERGuQT-Y0,132
3
3
  pydantic_ai/_a2a.py,sha256=wux52DmJQceLJwF71qxb0Uqupk3aS61m005-NmuWZIw,12164
4
4
  pydantic_ai/_agent_graph.py,sha256=W6bdFC_LtROBkU7ZpWqWL-sTSKD17tYyeBI9nWzVL5k,38484
@@ -14,7 +14,7 @@ pydantic_ai/_thinking_part.py,sha256=x80-Vkon16GOyq3W6f2qzafTVPC5dCgF7QD3k8ZMmYU
14
14
  pydantic_ai/_tool_manager.py,sha256=WPMXgHBzyn7UgRKIuqU-oV2GpsAOW0nF2RsxPCKOp7U,9655
15
15
  pydantic_ai/_utils.py,sha256=Ge9rtu8NJvsfSFjx1MduITPr0-9b_I0emDFSpwJbYes,16372
16
16
  pydantic_ai/ag_ui.py,sha256=bd-RJYFFmcw2xkAWj-7N0ZLRMa1dam3LEhlgoNo1l9I,26475
17
- pydantic_ai/builtin_tools.py,sha256=mwIq-7m0ZSbCZp1zxswjRfQM648QE01IDfifvqDGxUQ,3023
17
+ pydantic_ai/builtin_tools.py,sha256=ipo0q5DISc99k2xD453Yaw61v-3tCmlD2mDval9UCRU,3181
18
18
  pydantic_ai/direct.py,sha256=ym1Lb7oCPDU2eMmN8LXzN7Dp_IUJIPmlyKgmxxBUxsc,14905
19
19
  pydantic_ai/exceptions.py,sha256=vHRH_b6JpMi5p5EGhz2O4FSeKGJv3WMD291Y1FjHYFc,3528
20
20
  pydantic_ai/format_prompt.py,sha256=Or-Ytq55RQb1UJqy2HKIyPpZ-knWXfdDP3Z6tNc6Orw,4244
@@ -26,8 +26,8 @@ pydantic_ai/result.py,sha256=gUVJIyoM1FewRFLj7ezuXr7M2RSaQL4AytoIpBMmDy8,19800
26
26
  pydantic_ai/retries.py,sha256=Xkj-gZAd3wc12CVsIErVYx2EIdIwD5yJOL4Ou6jDQ2s,10498
27
27
  pydantic_ai/run.py,sha256=acyyTDH8qP1W-gbUA8TBBcOqte-7ICyoelJRjO_ojeo,14879
28
28
  pydantic_ai/settings.py,sha256=yuUZ7-GkdPB-Gbx71kSdh8dSr6gwM9gEwk84qNxPO_I,3552
29
- pydantic_ai/tools.py,sha256=1_4kt4HGfpHH4XnYy0lQRzm5Io5SzOjk3AJxa-LJLmE,14821
30
- pydantic_ai/usage.py,sha256=znjemyBOSUo5h0kQwQGEzTBlPGu4qUy69T-mciMUndE,12126
29
+ pydantic_ai/tools.py,sha256=HzwxH7H-TVCRmGF8PnKIQe1zlElorDFD2o_qrWrmyDc,15006
30
+ pydantic_ai/usage.py,sha256=7A9GkTo9SohQtd54OzL3sl3oix4s634kDEdWsHI4wlA,12150
31
31
  pydantic_ai/agent/__init__.py,sha256=6qe2t2TRr4yjwClHYaVRCSWFnDD8_7_0LhSfqF1L1ac,59255
32
32
  pydantic_ai/agent/abstract.py,sha256=2B00V-SmKlFkrkVW2KQ4e0K_glr9cQL6Llq2OYLqlgg,42000
33
33
  pydantic_ai/agent/wrapper.py,sha256=sE_9rA1PNF5v0qAMhRYw0W8bIhLT4RP17S3TSLz0k5w,9084
@@ -53,7 +53,7 @@ pydantic_ai/models/cohere.py,sha256=jZPMuFvNv9JTVCbC_p7_1Uxuc5WGn6RVFpH_pwG7iO0,
53
53
  pydantic_ai/models/fallback.py,sha256=ftcYhl0oSOer0vYbLkaf7dfgI_3h0hk7hp07i1Wh9rI,5526
54
54
  pydantic_ai/models/function.py,sha256=dY1aCUwcVXot5e2jWApWMAMnKWkSeEH4vqoe6mTBBZ0,14139
55
55
  pydantic_ai/models/gemini.py,sha256=2KoN-sf5skHOkVcvbV5Zw4jGYanZX4n_K4jhyJVYK4U,39151
56
- pydantic_ai/models/google.py,sha256=dMp1zJOWQFPH2unHDsuVEPoAAjER5u-iSHew0t9lD7o,30498
56
+ pydantic_ai/models/google.py,sha256=46q5NF8hSUHAMNcGbFNqZgK_S24klWb2aAFelMYy79s,30891
57
57
  pydantic_ai/models/groq.py,sha256=kqegrHbeabp__jNwuib3k0vQTVpra7Gy3D_dwbH9vv8,20960
58
58
  pydantic_ai/models/huggingface.py,sha256=JcYDfZbkYsQ9KUlDwfraiWq7dbg8Q0FRKkx8Lv9IWjg,20182
59
59
  pydantic_ai/models/instrumented.py,sha256=wzdnuIIIgpMJ7zqhMf-S--ffg9YYEgn5WRkJE2cCwao,16307
@@ -109,8 +109,8 @@ pydantic_ai/toolsets/prefixed.py,sha256=0KwcDkW8OM36ZUsOLVP5h-Nj2tPq78L3_E2c-1Fb
109
109
  pydantic_ai/toolsets/prepared.py,sha256=Zjfz6S8In6PBVxoKFN9sKPN984zO6t0awB7Lnq5KODw,1431
110
110
  pydantic_ai/toolsets/renamed.py,sha256=JuLHpi-hYPiSPlaTpN8WiXLiGsywYK0axi2lW2Qs75k,1637
111
111
  pydantic_ai/toolsets/wrapper.py,sha256=mMuMPdko9PJUdcsexlRXbwViSwKKJfv6JE58d8HK3ds,1646
112
- pydantic_ai_slim-0.7.3.dist-info/METADATA,sha256=mfpWSZ9tg3qLymgDpn5XJmX25DYIU9id6c0fMSpHeBc,4661
113
- pydantic_ai_slim-0.7.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
114
- pydantic_ai_slim-0.7.3.dist-info/entry_points.txt,sha256=kbKxe2VtDCYS06hsI7P3uZGxcVC08-FPt1rxeiMpIps,50
115
- pydantic_ai_slim-0.7.3.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
116
- pydantic_ai_slim-0.7.3.dist-info/RECORD,,
112
+ pydantic_ai_slim-0.7.4.dist-info/METADATA,sha256=_fszjpgjDIP3jR56uyk7fD4f2-mlZcqtupc1P2pyv0E,4661
113
+ pydantic_ai_slim-0.7.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
114
+ pydantic_ai_slim-0.7.4.dist-info/entry_points.txt,sha256=kbKxe2VtDCYS06hsI7P3uZGxcVC08-FPt1rxeiMpIps,50
115
+ pydantic_ai_slim-0.7.4.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
116
+ pydantic_ai_slim-0.7.4.dist-info/RECORD,,