pydantic-ai-slim 0.7.5__tar.gz → 0.8.0__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 (120) hide show
  1. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/PKG-INFO +4 -4
  2. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_cli.py +2 -1
  3. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/ag_ui.py +2 -2
  4. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/agent/__init__.py +19 -12
  5. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/agent/abstract.py +31 -18
  6. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/direct.py +5 -3
  7. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_function_toolset.py +9 -2
  8. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/mcp.py +48 -71
  9. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/messages.py +46 -10
  10. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/__init__.py +24 -14
  11. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/anthropic.py +2 -2
  12. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/bedrock.py +1 -1
  13. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/openai.py +74 -38
  14. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/__init__.py +1 -1
  15. pydantic_ai_slim-0.8.0/pydantic_ai/profiles/harmony.py +13 -0
  16. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/openai.py +6 -1
  17. pydantic_ai_slim-0.8.0/pydantic_ai/profiles/qwen.py +19 -0
  18. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/__init__.py +5 -1
  19. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/azure.py +1 -1
  20. pydantic_ai_slim-0.8.0/pydantic_ai/providers/cerebras.py +96 -0
  21. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/cohere.py +2 -2
  22. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/deepseek.py +4 -4
  23. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/fireworks.py +3 -3
  24. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/github.py +4 -4
  25. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/grok.py +3 -3
  26. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/groq.py +3 -3
  27. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/heroku.py +3 -3
  28. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/mistral.py +3 -3
  29. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/moonshotai.py +3 -6
  30. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/ollama.py +1 -1
  31. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/openrouter.py +4 -4
  32. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/together.py +3 -3
  33. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/vercel.py +4 -4
  34. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/result.py +5 -5
  35. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/retries.py +154 -42
  36. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pyproject.toml +1 -1
  37. pydantic_ai_slim-0.7.5/pydantic_ai/profiles/qwen.py +0 -11
  38. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/.gitignore +0 -0
  39. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/LICENSE +0 -0
  40. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/README.md +0 -0
  41. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/__init__.py +0 -0
  42. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/__main__.py +0 -0
  43. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_a2a.py +0 -0
  44. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_agent_graph.py +0 -0
  45. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_function_schema.py +0 -0
  46. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_griffe.py +0 -0
  47. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_mcp.py +0 -0
  48. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_otel_messages.py +0 -0
  49. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_output.py +0 -0
  50. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_parts_manager.py +0 -0
  51. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_run_context.py +0 -0
  52. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_system_prompt.py +0 -0
  53. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_thinking_part.py +0 -0
  54. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_tool_manager.py +0 -0
  55. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/_utils.py +0 -0
  56. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/agent/wrapper.py +0 -0
  57. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/builtin_tools.py +0 -0
  58. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/common_tools/__init__.py +0 -0
  59. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/common_tools/duckduckgo.py +0 -0
  60. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/common_tools/tavily.py +0 -0
  61. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/__init__.py +0 -0
  62. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
  63. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
  64. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
  65. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
  66. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
  67. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  68. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
  69. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/exceptions.py +0 -0
  70. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/ext/__init__.py +0 -0
  71. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/ext/aci.py +0 -0
  72. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/ext/langchain.py +0 -0
  73. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/format_prompt.py +0 -0
  74. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/cohere.py +0 -0
  75. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/fallback.py +0 -0
  76. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/function.py +0 -0
  77. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/gemini.py +0 -0
  78. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/google.py +0 -0
  79. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/groq.py +0 -0
  80. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/huggingface.py +0 -0
  81. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/instrumented.py +0 -0
  82. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/mcp_sampling.py +0 -0
  83. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/mistral.py +0 -0
  84. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/test.py +0 -0
  85. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/models/wrapper.py +0 -0
  86. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/output.py +0 -0
  87. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/_json_schema.py +0 -0
  88. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/amazon.py +0 -0
  89. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/anthropic.py +0 -0
  90. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/cohere.py +0 -0
  91. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/deepseek.py +0 -0
  92. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/google.py +0 -0
  93. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/grok.py +0 -0
  94. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/groq.py +0 -0
  95. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/meta.py +0 -0
  96. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/mistral.py +0 -0
  97. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/profiles/moonshotai.py +0 -0
  98. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/anthropic.py +0 -0
  99. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/bedrock.py +0 -0
  100. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/google.py +0 -0
  101. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/google_gla.py +0 -0
  102. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/google_vertex.py +0 -0
  103. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/huggingface.py +0 -0
  104. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/providers/openai.py +0 -0
  105. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/py.typed +0 -0
  106. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/run.py +0 -0
  107. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/settings.py +0 -0
  108. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/tools.py +0 -0
  109. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/__init__.py +0 -0
  110. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/_dynamic.py +0 -0
  111. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/abstract.py +0 -0
  112. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/combined.py +0 -0
  113. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/deferred.py +0 -0
  114. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/filtered.py +0 -0
  115. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/function.py +0 -0
  116. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/prefixed.py +0 -0
  117. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/prepared.py +0 -0
  118. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/renamed.py +0 -0
  119. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/toolsets/wrapper.py +0 -0
  120. {pydantic_ai_slim-0.7.5 → pydantic_ai_slim-0.8.0}/pydantic_ai/usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-slim
3
- Version: 0.7.5
3
+ Version: 0.8.0
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.5
38
+ Requires-Dist: pydantic-graph==0.8.0
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.5; extra == 'evals'
60
+ Requires-Dist: pydantic-evals==0.8.0; extra == 'evals'
61
61
  Provides-Extra: google
62
62
  Requires-Dist: google-genai>=1.31.0; extra == 'google'
63
63
  Provides-Extra: groq
@@ -67,7 +67,7 @@ Requires-Dist: huggingface-hub[inference]>=0.33.5; extra == 'huggingface'
67
67
  Provides-Extra: logfire
68
68
  Requires-Dist: logfire>=3.14.1; extra == 'logfire'
69
69
  Provides-Extra: mcp
70
- Requires-Dist: mcp>=1.10.0; (python_version >= '3.10') and extra == 'mcp'
70
+ Requires-Dist: mcp>=1.12.3; (python_version >= '3.10') and extra == 'mcp'
71
71
  Provides-Extra: mistral
72
72
  Requires-Dist: mistralai>=1.9.2; extra == 'mistral'
73
73
  Provides-Extra: openai
@@ -228,6 +228,7 @@ async def run_chat(
228
228
  prog_name: str,
229
229
  config_dir: Path | None = None,
230
230
  deps: AgentDepsT = None,
231
+ message_history: list[ModelMessage] | None = None,
231
232
  ) -> int:
232
233
  prompt_history_path = (config_dir or PYDANTIC_AI_HOME) / PROMPT_HISTORY_FILENAME
233
234
  prompt_history_path.parent.mkdir(parents=True, exist_ok=True)
@@ -235,7 +236,7 @@ async def run_chat(
235
236
  session: PromptSession[Any] = PromptSession(history=FileHistory(str(prompt_history_path)))
236
237
 
237
238
  multiline = False
238
- messages: list[ModelMessage] = []
239
+ messages: list[ModelMessage] = message_history[:] if message_history else []
239
240
 
240
241
  while True:
241
242
  try:
@@ -28,11 +28,11 @@ from ._agent_graph import CallToolsNode, ModelRequestNode
28
28
  from .agent import AbstractAgent, AgentRun
29
29
  from .exceptions import UserError
30
30
  from .messages import (
31
- AgentStreamEvent,
32
31
  FunctionToolResultEvent,
33
32
  ModelMessage,
34
33
  ModelRequest,
35
34
  ModelResponse,
35
+ ModelResponseStreamEvent,
36
36
  PartDeltaEvent,
37
37
  PartStartEvent,
38
38
  SystemPromptPart,
@@ -403,7 +403,7 @@ async def _agent_stream(run: AgentRun[AgentDepsT, Any]) -> AsyncIterator[BaseEve
403
403
 
404
404
  async def _handle_model_request_event(
405
405
  stream_ctx: _RequestStreamContext,
406
- agent_event: AgentStreamEvent,
406
+ agent_event: ModelResponseStreamEvent,
407
407
  ) -> AsyncIterator[BaseEvent]:
408
408
  """Handle an agent event and yield AG-UI protocol events.
409
409
 
@@ -26,7 +26,14 @@ from .. import (
26
26
  models,
27
27
  usage as _usage,
28
28
  )
29
- from .._agent_graph import HistoryProcessor
29
+ from .._agent_graph import (
30
+ CallToolsNode,
31
+ EndStrategy,
32
+ HistoryProcessor,
33
+ ModelRequestNode,
34
+ UserPromptNode,
35
+ capture_run_messages,
36
+ )
30
37
  from .._output import OutputToolset
31
38
  from .._tool_manager import ToolManager
32
39
  from ..builtin_tools import AbstractBuiltinTool
@@ -60,13 +67,6 @@ from ..toolsets.prepared import PreparedToolset
60
67
  from .abstract import AbstractAgent, EventStreamHandler, RunOutputDataT
61
68
  from .wrapper import WrapperAgent
62
69
 
63
- # Re-exporting like this improves auto-import behavior in PyCharm
64
- capture_run_messages = _agent_graph.capture_run_messages
65
- EndStrategy = _agent_graph.EndStrategy
66
- CallToolsNode = _agent_graph.CallToolsNode
67
- ModelRequestNode = _agent_graph.ModelRequestNode
68
- UserPromptNode = _agent_graph.UserPromptNode
69
-
70
70
  if TYPE_CHECKING:
71
71
  from ..mcp import MCPServer
72
72
 
@@ -677,16 +677,23 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
677
677
  def _run_span_end_attributes(
678
678
  self, state: _agent_graph.GraphAgentState, usage: _usage.RunUsage, settings: InstrumentationSettings
679
679
  ):
680
+ if settings.version == 1:
681
+ attr_name = 'all_messages_events'
682
+ value = [
683
+ InstrumentedModel.event_to_dict(e) for e in settings.messages_to_otel_events(state.message_history)
684
+ ]
685
+ else:
686
+ attr_name = 'pydantic_ai.all_messages'
687
+ value = settings.messages_to_otel_messages(state.message_history)
688
+
680
689
  return {
681
690
  **usage.opentelemetry_attributes(),
682
- 'all_messages_events': json.dumps(
683
- [InstrumentedModel.event_to_dict(e) for e in settings.messages_to_otel_events(state.message_history)]
684
- ),
691
+ attr_name: json.dumps(value),
685
692
  'logfire.json_schema': json.dumps(
686
693
  {
687
694
  'type': 'object',
688
695
  'properties': {
689
- 'all_messages_events': {'type': 'array'},
696
+ attr_name: {'type': 'array'},
690
697
  'final_result': {'type': 'object'},
691
698
  },
692
699
  }
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
5
5
  from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Iterator, Mapping, Sequence
6
6
  from contextlib import AbstractAsyncContextManager, asynccontextmanager, contextmanager
7
7
  from types import FrameType
8
- from typing import TYPE_CHECKING, Any, Callable, Generic, Union, cast, overload
8
+ from typing import TYPE_CHECKING, Any, Callable, Generic, cast, overload
9
9
 
10
10
  from typing_extensions import Self, TypeAlias, TypeIs, TypeVar
11
11
 
@@ -34,13 +34,6 @@ from ..tools import (
34
34
  from ..toolsets import AbstractToolset
35
35
  from ..usage import RunUsage, UsageLimits
36
36
 
37
- # Re-exporting like this improves auto-import behavior in PyCharm
38
- capture_run_messages = _agent_graph.capture_run_messages
39
- EndStrategy = _agent_graph.EndStrategy
40
- CallToolsNode = _agent_graph.CallToolsNode
41
- ModelRequestNode = _agent_graph.ModelRequestNode
42
- UserPromptNode = _agent_graph.UserPromptNode
43
-
44
37
  if TYPE_CHECKING:
45
38
  from fasta2a.applications import FastA2A
46
39
  from fasta2a.broker import Broker
@@ -60,11 +53,7 @@ RunOutputDataT = TypeVar('RunOutputDataT')
60
53
  """Type variable for the result data of a run where `output_type` was customized on the run call."""
61
54
 
62
55
  EventStreamHandler: TypeAlias = Callable[
63
- [
64
- RunContext[AgentDepsT],
65
- AsyncIterable[Union[_messages.AgentStreamEvent, _messages.HandleResponseEvent]],
66
- ],
67
- Awaitable[None],
56
+ [RunContext[AgentDepsT], AsyncIterable[_messages.AgentStreamEvent]], Awaitable[None]
68
57
  ]
69
58
  """A function that receives agent [`RunContext`][pydantic_ai.tools.RunContext] and an async iterable of events from the model's streaming response and the agent's execution of tools."""
70
59
 
@@ -452,7 +441,9 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
452
441
  async with node.stream(graph_ctx) as stream:
453
442
  final_result_event = None
454
443
 
455
- async def stream_to_final(stream: AgentStream) -> AsyncIterator[_messages.AgentStreamEvent]:
444
+ async def stream_to_final(
445
+ stream: AgentStream,
446
+ ) -> AsyncIterator[_messages.ModelResponseStreamEvent]:
456
447
  nonlocal final_result_event
457
448
  async for event in stream:
458
449
  yield event
@@ -899,12 +890,18 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
899
890
  lifespan=lifespan,
900
891
  )
901
892
 
902
- async def to_cli(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
893
+ async def to_cli(
894
+ self: Self,
895
+ deps: AgentDepsT = None,
896
+ prog_name: str = 'pydantic-ai',
897
+ message_history: list[_messages.ModelMessage] | None = None,
898
+ ) -> None:
903
899
  """Run the agent in a CLI chat interface.
904
900
 
905
901
  Args:
906
902
  deps: The dependencies to pass to the agent.
907
903
  prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
904
+ message_history: History of the conversation so far.
908
905
 
909
906
  Example:
910
907
  ```python {title="agent_to_cli.py" test="skip"}
@@ -920,14 +917,28 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
920
917
 
921
918
  from pydantic_ai._cli import run_chat
922
919
 
923
- await run_chat(stream=True, agent=self, deps=deps, console=Console(), code_theme='monokai', prog_name=prog_name)
920
+ await run_chat(
921
+ stream=True,
922
+ agent=self,
923
+ deps=deps,
924
+ console=Console(),
925
+ code_theme='monokai',
926
+ prog_name=prog_name,
927
+ message_history=message_history,
928
+ )
924
929
 
925
- def to_cli_sync(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
930
+ def to_cli_sync(
931
+ self: Self,
932
+ deps: AgentDepsT = None,
933
+ prog_name: str = 'pydantic-ai',
934
+ message_history: list[_messages.ModelMessage] | None = None,
935
+ ) -> None:
926
936
  """Run the agent in a CLI chat interface with the non-async interface.
927
937
 
928
938
  Args:
929
939
  deps: The dependencies to pass to the agent.
930
940
  prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
941
+ message_history: History of the conversation so far.
931
942
 
932
943
  ```python {title="agent_to_cli_sync.py" test="skip"}
933
944
  from pydantic_ai import Agent
@@ -937,4 +948,6 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
937
948
  agent.to_cli_sync(prog_name='assistant')
938
949
  ```
939
950
  """
940
- return get_event_loop().run_until_complete(self.to_cli(deps=deps, prog_name=prog_name))
951
+ return get_event_loop().run_until_complete(
952
+ self.to_cli(deps=deps, prog_name=prog_name, message_history=message_history)
953
+ )
@@ -275,7 +275,9 @@ class StreamedResponseSync:
275
275
  """
276
276
 
277
277
  _async_stream_cm: AbstractAsyncContextManager[StreamedResponse]
278
- _queue: queue.Queue[messages.AgentStreamEvent | Exception | None] = field(default_factory=queue.Queue, init=False)
278
+ _queue: queue.Queue[messages.ModelResponseStreamEvent | Exception | None] = field(
279
+ default_factory=queue.Queue, init=False
280
+ )
279
281
  _thread: threading.Thread | None = field(default=None, init=False)
280
282
  _stream_response: StreamedResponse | None = field(default=None, init=False)
281
283
  _exception: Exception | None = field(default=None, init=False)
@@ -295,8 +297,8 @@ class StreamedResponseSync:
295
297
  ) -> None:
296
298
  self._cleanup()
297
299
 
298
- def __iter__(self) -> Iterator[messages.AgentStreamEvent]:
299
- """Stream the response as an iterable of [`AgentStreamEvent`][pydantic_ai.messages.AgentStreamEvent]s."""
300
+ def __iter__(self) -> Iterator[messages.ModelResponseStreamEvent]:
301
+ """Stream the response as an iterable of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s."""
300
302
  self._check_context_manager_usage()
301
303
 
302
304
  while True:
@@ -51,7 +51,10 @@ class TemporalFunctionToolset(TemporalWrapperToolset[AgentDepsT]):
51
51
  'Removing or renaming tools during an agent run is not supported with Temporal.'
52
52
  ) from e
53
53
 
54
- return await self.wrapped.call_tool(name, params.tool_args, ctx, tool)
54
+ # The tool args will already have been validated into their proper types in the `ToolManager`,
55
+ # but `execute_activity` would have turned them into simple Python types again, so we need to re-validate them.
56
+ args_dict = tool.args_validator.validate_python(params.tool_args)
57
+ return await self.wrapped.call_tool(name, args_dict, ctx, tool)
55
58
 
56
59
  # Set type hint explicitly so that Temporal can take care of serialization and deserialization
57
60
  call_tool_activity.__annotations__['deps'] = deps_type
@@ -85,7 +88,11 @@ class TemporalFunctionToolset(TemporalWrapperToolset[AgentDepsT]):
85
88
  return await workflow.execute_activity( # pyright: ignore[reportUnknownMemberType]
86
89
  activity=self.call_tool_activity,
87
90
  args=[
88
- _CallToolParams(name=name, tool_args=tool_args, serialized_run_context=serialized_run_context),
91
+ _CallToolParams(
92
+ name=name,
93
+ tool_args=tool_args,
94
+ serialized_run_context=serialized_run_context,
95
+ ),
89
96
  ctx.deps,
90
97
  ],
91
98
  **tool_activity_config,
@@ -18,14 +18,13 @@ import pydantic_core
18
18
  from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
19
19
  from typing_extensions import Self, assert_never, deprecated
20
20
 
21
- from pydantic_ai._run_context import RunContext
22
- from pydantic_ai.tools import ToolDefinition
21
+ from pydantic_ai.tools import RunContext, ToolDefinition
23
22
 
24
23
  from .toolsets.abstract import AbstractToolset, ToolsetTool
25
24
 
26
25
  try:
27
26
  from mcp import types as mcp_types
28
- from mcp.client.session import ClientSession, LoggingFnT
27
+ from mcp.client.session import ClientSession, ElicitationFnT, LoggingFnT
29
28
  from mcp.client.sse import sse_client
30
29
  from mcp.client.stdio import StdioServerParameters, stdio_client
31
30
  from mcp.client.streamable_http import GetSessionIdCallback, streamablehttp_client
@@ -57,14 +56,49 @@ class MCPServer(AbstractToolset[Any], ABC):
57
56
  """
58
57
 
59
58
  tool_prefix: str | None
59
+ """A prefix to add to all tools that are registered with the server.
60
+
61
+ If not empty, will include a trailing underscore(`_`).
62
+
63
+ e.g. if `tool_prefix='foo'`, then a tool named `bar` will be registered as `foo_bar`
64
+ """
65
+
60
66
  log_level: mcp_types.LoggingLevel | None
67
+ """The log level to set when connecting to the server, if any.
68
+
69
+ See <https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging#logging> for more details.
70
+
71
+ If `None`, no log level will be set.
72
+ """
73
+
61
74
  log_handler: LoggingFnT | None
75
+ """A handler for logging messages from the server."""
76
+
62
77
  timeout: float
78
+ """The timeout in seconds to wait for the client to initialize."""
79
+
63
80
  read_timeout: float
81
+ """Maximum time in seconds to wait for new messages before timing out.
82
+
83
+ This timeout applies to the long-lived connection after it's established.
84
+ If no new messages are received within this time, the connection will be considered stale
85
+ and may be closed. Defaults to 5 minutes (300 seconds).
86
+ """
87
+
64
88
  process_tool_call: ProcessToolCallback | None
89
+ """Hook to customize tool calling and optionally pass extra metadata."""
90
+
65
91
  allow_sampling: bool
92
+ """Whether to allow MCP sampling through this client."""
93
+
66
94
  sampling_model: models.Model | None
95
+ """The model to use for sampling."""
96
+
67
97
  max_retries: int
98
+ """The maximum number of times to retry a tool call."""
99
+
100
+ elicitation_callback: ElicitationFnT | None = None
101
+ """Callback function to handle elicitation requests from the server."""
68
102
 
69
103
  _id: str | None
70
104
 
@@ -87,6 +121,7 @@ class MCPServer(AbstractToolset[Any], ABC):
87
121
  allow_sampling: bool = True,
88
122
  sampling_model: models.Model | None = None,
89
123
  max_retries: int = 1,
124
+ elicitation_callback: ElicitationFnT | None = None,
90
125
  *,
91
126
  id: str | None = None,
92
127
  ):
@@ -99,6 +134,7 @@ class MCPServer(AbstractToolset[Any], ABC):
99
134
  self.allow_sampling = allow_sampling
100
135
  self.sampling_model = sampling_model
101
136
  self.max_retries = max_retries
137
+ self.elicitation_callback = elicitation_callback
102
138
 
103
139
  self._id = id or tool_prefix
104
140
 
@@ -247,6 +283,7 @@ class MCPServer(AbstractToolset[Any], ABC):
247
283
  read_stream=self._read_stream,
248
284
  write_stream=self._write_stream,
249
285
  sampling_callback=self._sampling_callback if self.allow_sampling else None,
286
+ elicitation_callback=self.elicitation_callback,
250
287
  logging_callback=self.log_handler,
251
288
  read_timeout_seconds=timedelta(seconds=self.read_timeout),
252
289
  )
@@ -404,46 +441,15 @@ class MCPServerStdio(MCPServer):
404
441
 
405
442
  # last fields are re-defined from the parent class so they appear as fields
406
443
  tool_prefix: str | None
407
- """A prefix to add to all tools that are registered with the server.
408
-
409
- If not empty, will include a trailing underscore(`_`).
410
-
411
- e.g. if `tool_prefix='foo'`, then a tool named `bar` will be registered as `foo_bar`
412
- """
413
-
414
444
  log_level: mcp_types.LoggingLevel | None
415
- """The log level to set when connecting to the server, if any.
416
-
417
- See <https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging#logging> for more details.
418
-
419
- If `None`, no log level will be set.
420
- """
421
-
422
445
  log_handler: LoggingFnT | None
423
- """A handler for logging messages from the server."""
424
-
425
446
  timeout: float
426
- """The timeout in seconds to wait for the client to initialize."""
427
-
428
447
  read_timeout: float
429
- """Maximum time in seconds to wait for new messages before timing out.
430
-
431
- This timeout applies to the long-lived connection after it's established.
432
- If no new messages are received within this time, the connection will be considered stale
433
- and may be closed. Defaults to 5 minutes (300 seconds).
434
- """
435
-
436
448
  process_tool_call: ProcessToolCallback | None
437
- """Hook to customize tool calling and optionally pass extra metadata."""
438
-
439
449
  allow_sampling: bool
440
- """Whether to allow MCP sampling through this client."""
441
-
442
450
  sampling_model: models.Model | None
443
- """The model to use for sampling."""
444
-
445
451
  max_retries: int
446
- """The maximum number of times to retry a tool call."""
452
+ elicitation_callback: ElicitationFnT | None = None
447
453
 
448
454
  def __init__(
449
455
  self,
@@ -460,6 +466,7 @@ class MCPServerStdio(MCPServer):
460
466
  allow_sampling: bool = True,
461
467
  sampling_model: models.Model | None = None,
462
468
  max_retries: int = 1,
469
+ elicitation_callback: ElicitationFnT | None = None,
463
470
  *,
464
471
  id: str | None = None,
465
472
  ):
@@ -479,6 +486,7 @@ class MCPServerStdio(MCPServer):
479
486
  allow_sampling: Whether to allow MCP sampling through this client.
480
487
  sampling_model: The model to use for sampling.
481
488
  max_retries: The maximum number of times to retry a tool call.
489
+ elicitation_callback: Callback function to handle elicitation requests from the server.
482
490
  id: An optional unique ID for the MCP server. An MCP server needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the server's activities within the workflow.
483
491
  """
484
492
  self.command = command
@@ -496,6 +504,7 @@ class MCPServerStdio(MCPServer):
496
504
  allow_sampling,
497
505
  sampling_model,
498
506
  max_retries,
507
+ elicitation_callback,
499
508
  id=id,
500
509
  )
501
510
 
@@ -560,50 +569,15 @@ class _MCPServerHTTP(MCPServer):
560
569
 
561
570
  # last fields are re-defined from the parent class so they appear as fields
562
571
  tool_prefix: str | None
563
- """A prefix to add to all tools that are registered with the server.
564
-
565
- If not empty, will include a trailing underscore (`_`).
566
-
567
- For example, if `tool_prefix='foo'`, then a tool named `bar` will be registered as `foo_bar`
568
- """
569
-
570
572
  log_level: mcp_types.LoggingLevel | None
571
- """The log level to set when connecting to the server, if any.
572
-
573
- See <https://modelcontextprotocol.io/introduction#logging> for more details.
574
-
575
- If `None`, no log level will be set.
576
- """
577
-
578
573
  log_handler: LoggingFnT | None
579
- """A handler for logging messages from the server."""
580
-
581
574
  timeout: float
582
- """Initial connection timeout in seconds for establishing the connection.
583
-
584
- This timeout applies to the initial connection setup and handshake.
585
- If the connection cannot be established within this time, the operation will fail.
586
- """
587
-
588
575
  read_timeout: float
589
- """Maximum time in seconds to wait for new messages before timing out.
590
-
591
- This timeout applies to the long-lived connection after it's established.
592
- If no new messages are received within this time, the connection will be considered stale
593
- and may be closed. Defaults to 5 minutes (300 seconds).
594
- """
595
-
596
576
  process_tool_call: ProcessToolCallback | None
597
- """Hook to customize tool calling and optionally pass extra metadata."""
598
-
599
577
  allow_sampling: bool
600
- """Whether to allow MCP sampling through this client."""
601
-
602
578
  sampling_model: models.Model | None
603
- """The model to use for sampling."""
604
-
605
579
  max_retries: int
606
- """The maximum number of times to retry a tool call."""
580
+ elicitation_callback: ElicitationFnT | None = None
607
581
 
608
582
  def __init__(
609
583
  self,
@@ -621,6 +595,7 @@ class _MCPServerHTTP(MCPServer):
621
595
  allow_sampling: bool = True,
622
596
  sampling_model: models.Model | None = None,
623
597
  max_retries: int = 1,
598
+ elicitation_callback: ElicitationFnT | None = None,
624
599
  **_deprecated_kwargs: Any,
625
600
  ):
626
601
  """Build a new MCP server.
@@ -639,6 +614,7 @@ class _MCPServerHTTP(MCPServer):
639
614
  allow_sampling: Whether to allow MCP sampling through this client.
640
615
  sampling_model: The model to use for sampling.
641
616
  max_retries: The maximum number of times to retry a tool call.
617
+ elicitation_callback: Callback function to handle elicitation requests from the server.
642
618
  """
643
619
  if 'sse_read_timeout' in _deprecated_kwargs:
644
620
  if read_timeout is not None:
@@ -668,6 +644,7 @@ class _MCPServerHTTP(MCPServer):
668
644
  allow_sampling,
669
645
  sampling_model,
670
646
  max_retries,
647
+ elicitation_callback,
671
648
  id=id,
672
649
  )
673
650
 
@@ -110,7 +110,9 @@ class FileUrl(ABC):
110
110
  - `GoogleModel`: `VideoUrl.vendor_metadata` is used as `video_metadata`: https://ai.google.dev/gemini-api/docs/video-understanding#customize-video-processing
111
111
  """
112
112
 
113
- _media_type: str | None = field(init=False, repr=False, compare=False)
113
+ _media_type: Annotated[str | None, pydantic.Field(alias='media_type', default=None, exclude=True)] = field(
114
+ compare=False, default=None
115
+ )
114
116
 
115
117
  def __init__(
116
118
  self,
@@ -124,6 +126,7 @@ class FileUrl(ABC):
124
126
  self.force_download = force_download
125
127
  self._media_type = media_type
126
128
 
129
+ @pydantic.computed_field
127
130
  @property
128
131
  def media_type(self) -> str:
129
132
  """Return the media type of the file, based on the URL or the provided `media_type`."""
@@ -160,8 +163,16 @@ class VideoUrl(FileUrl):
160
163
  vendor_metadata: dict[str, Any] | None = None,
161
164
  media_type: str | None = None,
162
165
  kind: Literal['video-url'] = 'video-url',
166
+ *,
167
+ # Required for inline-snapshot which expects all dataclass `__init__` methods to take all field names as kwargs.
168
+ _media_type: str | None = None,
163
169
  ) -> None:
164
- super().__init__(url=url, force_download=force_download, vendor_metadata=vendor_metadata, media_type=media_type)
170
+ super().__init__(
171
+ url=url,
172
+ force_download=force_download,
173
+ vendor_metadata=vendor_metadata,
174
+ media_type=media_type or _media_type,
175
+ )
165
176
  self.kind = kind
166
177
 
167
178
  def _infer_media_type(self) -> VideoMediaType:
@@ -223,8 +234,16 @@ class AudioUrl(FileUrl):
223
234
  vendor_metadata: dict[str, Any] | None = None,
224
235
  media_type: str | None = None,
225
236
  kind: Literal['audio-url'] = 'audio-url',
237
+ *,
238
+ # Required for inline-snapshot which expects all dataclass `__init__` methods to take all field names as kwargs.
239
+ _media_type: str | None = None,
226
240
  ) -> None:
227
- super().__init__(url=url, force_download=force_download, vendor_metadata=vendor_metadata, media_type=media_type)
241
+ super().__init__(
242
+ url=url,
243
+ force_download=force_download,
244
+ vendor_metadata=vendor_metadata,
245
+ media_type=media_type or _media_type,
246
+ )
228
247
  self.kind = kind
229
248
 
230
249
  def _infer_media_type(self) -> AudioMediaType:
@@ -273,8 +292,16 @@ class ImageUrl(FileUrl):
273
292
  vendor_metadata: dict[str, Any] | None = None,
274
293
  media_type: str | None = None,
275
294
  kind: Literal['image-url'] = 'image-url',
295
+ *,
296
+ # Required for inline-snapshot which expects all dataclass `__init__` methods to take all field names as kwargs.
297
+ _media_type: str | None = None,
276
298
  ) -> None:
277
- super().__init__(url=url, force_download=force_download, vendor_metadata=vendor_metadata, media_type=media_type)
299
+ super().__init__(
300
+ url=url,
301
+ force_download=force_download,
302
+ vendor_metadata=vendor_metadata,
303
+ media_type=media_type or _media_type,
304
+ )
278
305
  self.kind = kind
279
306
 
280
307
  def _infer_media_type(self) -> ImageMediaType:
@@ -318,8 +345,16 @@ class DocumentUrl(FileUrl):
318
345
  vendor_metadata: dict[str, Any] | None = None,
319
346
  media_type: str | None = None,
320
347
  kind: Literal['document-url'] = 'document-url',
348
+ *,
349
+ # Required for inline-snapshot which expects all dataclass `__init__` methods to take all field names as kwargs.
350
+ _media_type: str | None = None,
321
351
  ) -> None:
322
- super().__init__(url=url, force_download=force_download, vendor_metadata=vendor_metadata, media_type=media_type)
352
+ super().__init__(
353
+ url=url,
354
+ force_download=force_download,
355
+ vendor_metadata=vendor_metadata,
356
+ media_type=media_type or _media_type,
357
+ )
323
358
  self.kind = kind
324
359
 
325
360
  def _infer_media_type(self) -> str:
@@ -1263,13 +1298,10 @@ class FinalResultEvent:
1263
1298
  __repr__ = _utils.dataclasses_no_defaults_repr
1264
1299
 
1265
1300
 
1266
- ModelResponseStreamEvent = Annotated[Union[PartStartEvent, PartDeltaEvent], pydantic.Discriminator('event_kind')]
1267
- """An event in the model response stream, either starting a new part or applying a delta to an existing one."""
1268
-
1269
- AgentStreamEvent = Annotated[
1301
+ ModelResponseStreamEvent = Annotated[
1270
1302
  Union[PartStartEvent, PartDeltaEvent, FinalResultEvent], pydantic.Discriminator('event_kind')
1271
1303
  ]
1272
- """An event in the agent stream."""
1304
+ """An event in the model response stream, starting a new part, applying a delta to an existing one, or indicating the final result."""
1273
1305
 
1274
1306
 
1275
1307
  @dataclass(repr=False)
@@ -1338,3 +1370,7 @@ HandleResponseEvent = Annotated[
1338
1370
  Union[FunctionToolCallEvent, FunctionToolResultEvent, BuiltinToolCallEvent, BuiltinToolResultEvent],
1339
1371
  pydantic.Discriminator('event_kind'),
1340
1372
  ]
1373
+ """An event yielded when handling a model response, indicating tool calls and results."""
1374
+
1375
+ AgentStreamEvent = Annotated[Union[ModelResponseStreamEvent, HandleResponseEvent], pydantic.Discriminator('event_kind')]
1376
+ """An event in the agent stream: model response stream events and response-handling events."""