pydantic-ai-slim 1.7.0__py3-none-any.whl → 1.11.0__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.

Files changed (47) hide show
  1. pydantic_ai/__init__.py +2 -0
  2. pydantic_ai/_agent_graph.py +3 -0
  3. pydantic_ai/_cli.py +2 -2
  4. pydantic_ai/_run_context.py +8 -2
  5. pydantic_ai/_tool_manager.py +1 -0
  6. pydantic_ai/_utils.py +18 -0
  7. pydantic_ai/ag_ui.py +50 -696
  8. pydantic_ai/agent/__init__.py +13 -3
  9. pydantic_ai/agent/abstract.py +172 -9
  10. pydantic_ai/agent/wrapper.py +5 -0
  11. pydantic_ai/direct.py +16 -4
  12. pydantic_ai/durable_exec/dbos/_agent.py +31 -0
  13. pydantic_ai/durable_exec/prefect/_agent.py +28 -0
  14. pydantic_ai/durable_exec/temporal/_agent.py +28 -0
  15. pydantic_ai/durable_exec/temporal/_function_toolset.py +23 -73
  16. pydantic_ai/durable_exec/temporal/_mcp_server.py +30 -30
  17. pydantic_ai/durable_exec/temporal/_run_context.py +9 -3
  18. pydantic_ai/durable_exec/temporal/_toolset.py +67 -3
  19. pydantic_ai/messages.py +49 -8
  20. pydantic_ai/models/__init__.py +42 -1
  21. pydantic_ai/models/google.py +5 -12
  22. pydantic_ai/models/groq.py +9 -1
  23. pydantic_ai/models/openai.py +6 -3
  24. pydantic_ai/profiles/openai.py +5 -2
  25. pydantic_ai/providers/anthropic.py +2 -2
  26. pydantic_ai/providers/openrouter.py +3 -0
  27. pydantic_ai/result.py +178 -11
  28. pydantic_ai/tools.py +10 -6
  29. pydantic_ai/ui/__init__.py +16 -0
  30. pydantic_ai/ui/_adapter.py +386 -0
  31. pydantic_ai/ui/_event_stream.py +591 -0
  32. pydantic_ai/ui/_messages_builder.py +28 -0
  33. pydantic_ai/ui/ag_ui/__init__.py +9 -0
  34. pydantic_ai/ui/ag_ui/_adapter.py +187 -0
  35. pydantic_ai/ui/ag_ui/_event_stream.py +236 -0
  36. pydantic_ai/ui/ag_ui/app.py +148 -0
  37. pydantic_ai/ui/vercel_ai/__init__.py +16 -0
  38. pydantic_ai/ui/vercel_ai/_adapter.py +199 -0
  39. pydantic_ai/ui/vercel_ai/_event_stream.py +187 -0
  40. pydantic_ai/ui/vercel_ai/_utils.py +16 -0
  41. pydantic_ai/ui/vercel_ai/request_types.py +275 -0
  42. pydantic_ai/ui/vercel_ai/response_types.py +230 -0
  43. {pydantic_ai_slim-1.7.0.dist-info → pydantic_ai_slim-1.11.0.dist-info}/METADATA +10 -6
  44. {pydantic_ai_slim-1.7.0.dist-info → pydantic_ai_slim-1.11.0.dist-info}/RECORD +47 -33
  45. {pydantic_ai_slim-1.7.0.dist-info → pydantic_ai_slim-1.11.0.dist-info}/WHEEL +0 -0
  46. {pydantic_ai_slim-1.7.0.dist-info → pydantic_ai_slim-1.11.0.dist-info}/entry_points.txt +0 -0
  47. {pydantic_ai_slim-1.7.0.dist-info → pydantic_ai_slim-1.11.0.dist-info}/licenses/LICENSE +0 -0
pydantic_ai/__init__.py CHANGED
@@ -65,6 +65,7 @@ from .messages import (
65
65
  ModelResponseStreamEvent,
66
66
  MultiModalContent,
67
67
  PartDeltaEvent,
68
+ PartEndEvent,
68
69
  PartStartEvent,
69
70
  RetryPromptPart,
70
71
  SystemPromptPart,
@@ -164,6 +165,7 @@ __all__ = (
164
165
  'ModelResponseStreamEvent',
165
166
  'MultiModalContent',
166
167
  'PartDeltaEvent',
168
+ 'PartEndEvent',
167
169
  'PartStartEvent',
168
170
  'RetryPromptPart',
169
171
  'SystemPromptPart',
@@ -267,6 +267,9 @@ class UserPromptNode(AgentNode[DepsT, NodeRunEndT]):
267
267
 
268
268
  next_message.instructions = await ctx.deps.get_instructions(run_context)
269
269
 
270
+ if not messages and not next_message.parts and not next_message.instructions:
271
+ raise exceptions.UserError('No message history, user prompt, or instructions provided')
272
+
270
273
  return ModelRequestNode[DepsT, NodeRunEndT](request=next_message)
271
274
 
272
275
  async def _handle_deferred_tool_results( # noqa: C901
pydantic_ai/_cli.py CHANGED
@@ -103,7 +103,7 @@ def cli_exit(prog_name: str = 'pai'): # pragma: no cover
103
103
 
104
104
 
105
105
  def cli( # noqa: C901
106
- args_list: Sequence[str] | None = None, *, prog_name: str = 'pai', default_model: str = 'openai:gpt-4.1'
106
+ args_list: Sequence[str] | None = None, *, prog_name: str = 'pai', default_model: str = 'openai:gpt-5'
107
107
  ) -> int:
108
108
  """Run the CLI and return the exit code for the process."""
109
109
  parser = argparse.ArgumentParser(
@@ -124,7 +124,7 @@ Special prompts:
124
124
  '-m',
125
125
  '--model',
126
126
  nargs='?',
127
- help=f'Model to use, in format "<provider>:<model>" e.g. "openai:gpt-4.1" or "anthropic:claude-sonnet-4-0". Defaults to "{default_model}".',
127
+ help=f'Model to use, in format "<provider>:<model>" e.g. "openai:gpt-5" or "anthropic:claude-sonnet-4-5". Defaults to "{default_model}".',
128
128
  )
129
129
  # we don't want to autocomplete or list models that don't include the provider,
130
130
  # e.g. we want to show `openai:gpt-4o` but not `gpt-4o`
@@ -16,15 +16,19 @@ if TYPE_CHECKING:
16
16
  from .models import Model
17
17
  from .result import RunUsage
18
18
 
19
+ # TODO (v2): Change the default for all typevars like this from `None` to `object`
19
20
  AgentDepsT = TypeVar('AgentDepsT', default=None, contravariant=True)
20
21
  """Type variable for agent dependencies."""
21
22
 
23
+ RunContextAgentDepsT = TypeVar('RunContextAgentDepsT', default=None, covariant=True)
24
+ """Type variable for the agent dependencies in `RunContext`."""
25
+
22
26
 
23
27
  @dataclasses.dataclass(repr=False, kw_only=True)
24
- class RunContext(Generic[AgentDepsT]):
28
+ class RunContext(Generic[RunContextAgentDepsT]):
25
29
  """Information about the current call."""
26
30
 
27
- deps: AgentDepsT
31
+ deps: RunContextAgentDepsT
28
32
  """Dependencies for the agent."""
29
33
  model: Model
30
34
  """The model used in this run."""
@@ -54,6 +58,8 @@ class RunContext(Generic[AgentDepsT]):
54
58
  """The current step in the run."""
55
59
  tool_call_approved: bool = False
56
60
  """Whether a tool call that required approval has now been approved."""
61
+ partial_output: bool = False
62
+ """Whether the output passed to an output validator is partial."""
57
63
 
58
64
  @property
59
65
  def last_attempt(self) -> bool:
@@ -147,6 +147,7 @@ class ToolManager(Generic[AgentDepsT]):
147
147
  tool_call_id=call.tool_call_id,
148
148
  retry=self.ctx.retries.get(name, 0),
149
149
  max_retries=tool.max_retries,
150
+ partial_output=allow_partial,
150
151
  )
151
152
 
152
153
  pyd_allow_partial = 'trailing-strings' if allow_partial else 'off'
pydantic_ai/_utils.py CHANGED
@@ -234,6 +234,15 @@ def sync_anext(iterator: Iterator[T]) -> T:
234
234
  raise StopAsyncIteration() from e
235
235
 
236
236
 
237
+ def sync_async_iterator(async_iter: AsyncIterator[T]) -> Iterator[T]:
238
+ loop = get_event_loop()
239
+ while True:
240
+ try:
241
+ yield loop.run_until_complete(anext(async_iter))
242
+ except StopAsyncIteration:
243
+ break
244
+
245
+
237
246
  def now_utc() -> datetime:
238
247
  return datetime.now(tz=timezone.utc)
239
248
 
@@ -489,3 +498,12 @@ def get_union_args(tp: Any) -> tuple[Any, ...]:
489
498
  return tuple(_unwrap_annotated(arg) for arg in get_args(tp))
490
499
  else:
491
500
  return ()
501
+
502
+
503
+ def get_event_loop():
504
+ try:
505
+ event_loop = asyncio.get_event_loop()
506
+ except RuntimeError: # pragma: lax no cover
507
+ event_loop = asyncio.new_event_loop()
508
+ asyncio.set_event_loop(event_loop)
509
+ return event_loop