Skip to content

Commit f6ca999

Browse files
committed
Merge branch 'main' of github.com:pydantic/pydantic-ai into features/elicitation-callback
2 parents 4f1af20 + 8f28c34 commit f6ca999

File tree

69 files changed

+8750
-405
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+8750
-405
lines changed

.github/ISSUE_TEMPLATE/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
blank_issues_enabled: true
1+
blank_issues_enabled: false
22
contact_links:
33
- name: 💬 Join Slack
44
url: 'https://logfire.pydantic.dev/docs/help/#slack'

.github/workflows/ci.yml

Lines changed: 82 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ jobs:
107107
with:
108108
model: qwen2:0.5b
109109

110+
- run: uv sync --only-dev
110111
- run: >
111112
uv run
112113
--package pydantic-ai-slim
@@ -130,13 +131,14 @@ jobs:
130131
CO_API_KEY: ${{ secrets.COHERE_API_KEY }}
131132
132133
test:
133-
name: test on ${{ matrix.python-version }}
134+
name: test on ${{ matrix.python-version }} (${{ matrix.install }})
134135
runs-on: ubuntu-latest
135136
timeout-minutes: 10
136137
strategy:
137138
fail-fast: false
138139
matrix:
139140
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
141+
install: ["slim", "standard", "all-extras"]
140142
env:
141143
UV_PYTHON: ${{ matrix.python-version }}
142144
CI: true
@@ -152,42 +154,99 @@ jobs:
152154
with:
153155
deno-version: v2.x
154156

157+
- name: choose install command
158+
run: |
159+
if [ "${{ matrix.install }}" = "slim" ]; then
160+
echo "install-command=--package pydantic-ai-slim" >> $GITHUB_OUTPUT
161+
elif [ "${{ matrix.install }}" = "standard" ]; then
162+
echo "install-command=" >> $GITHUB_OUTPUT
163+
elif [ "${{ matrix.install }}" = "all-extras" ]; then
164+
echo "install-command=--all-extras" >> $GITHUB_OUTPUT
165+
fi
166+
id: install-command
167+
155168
- run: mkdir .coverage
156169

157-
# run tests with just `pydantic-ai-slim` dependencies
158-
- run: uv run --package pydantic-ai-slim coverage run -m pytest -n auto --dist=loadgroup
170+
- run: uv sync --group dev
171+
- run: uv run ${{ steps.install-command.outputs.install-command }} coverage run -m pytest -n auto --dist=loadgroup
159172
env:
160-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-slim
173+
COVERAGE_FILE: .coverage/.coverage.${{ matrix.python-version }}-${{ matrix.install }}
161174

162-
- run: uv run coverage run -m pytest -n auto --dist=loadgroup
163-
env:
164-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-standard
175+
- name: store coverage files
176+
uses: actions/upload-artifact@v4
177+
if: matrix.python-version != '3.9'
178+
with:
179+
name: coverage-${{ matrix.python-version }}-${{ matrix.install }}
180+
path: .coverage
181+
include-hidden-files: true
165182

166-
- run: uv run --all-extras coverage run -m pytest -n auto --dist=loadgroup
167-
env:
168-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-all-extras
183+
test-lowest-versions:
184+
name: test on ${{ matrix.python-version }} (lowest-versions)
185+
runs-on: ubuntu-latest
186+
timeout-minutes: 10
187+
strategy:
188+
fail-fast: false
189+
matrix:
190+
python-version: ["3.10", "3.11", "3.12", "3.13"]
191+
env:
192+
UV_PYTHON: ${{ matrix.python-version }}
193+
CI: true
194+
COVERAGE_PROCESS_START: ./pyproject.toml
195+
steps:
196+
- uses: actions/checkout@v4
169197

170-
- run: uv run --all-extras python tests/import_examples.py
198+
- uses: astral-sh/setup-uv@v5
199+
with:
200+
enable-cache: true
171201

172-
# this must run last as it modifies the environment!
173-
- name: test lowest versions
174-
if: matrix.python-version != '3.9'
175-
run: |
176-
unset UV_FROZEN
177-
uv run --all-extras --resolution lowest-direct coverage run -m pytest -n auto --dist=loadgroup
202+
- uses: denoland/setup-deno@v2
203+
with:
204+
deno-version: v2.x
205+
206+
- run: mkdir .coverage
207+
208+
- run: uv sync --group dev
209+
210+
- run: unset UV_FROZEN
211+
212+
- run: uv run --all-extras --resolution lowest-direct coverage run -m pytest -n auto --dist=loadgroup
178213
env:
179-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-lowest-versions
214+
COVERAGE_FILE: .coverage/.coverage.${{matrix.python-version}}-lowest-versions
180215

181216
- name: store coverage files
182217
uses: actions/upload-artifact@v4
183218
with:
184-
name: coverage-${{ matrix.python-version }}
219+
name: coverage-${{ matrix.python-version }}-lowest-versions
185220
path: .coverage
186221
include-hidden-files: true
187222

223+
test-examples:
224+
name: test examples on ${{ matrix.python-version }}
225+
runs-on: ubuntu-latest
226+
timeout-minutes: 10
227+
strategy:
228+
fail-fast: false
229+
matrix:
230+
python-version: ["3.11", "3.12", "3.13"]
231+
env:
232+
UV_PYTHON: ${{ matrix.python-version }}
233+
CI: true
234+
steps:
235+
- uses: actions/checkout@v4
236+
237+
- uses: astral-sh/setup-uv@v5
238+
with:
239+
enable-cache: true
240+
241+
- uses: denoland/setup-deno@v2
242+
with:
243+
deno-version: v2.x
244+
245+
- run: uv run --all-extras python tests/import_examples.py
246+
188247
coverage:
189248
runs-on: ubuntu-latest
190-
needs: [test]
249+
needs: [test, test-lowest-versions]
191250
steps:
192251
- uses: actions/checkout@v4
193252
with:
@@ -204,31 +263,9 @@ jobs:
204263
with:
205264
enable-cache: true
206265

207-
- run: uv sync --package pydantic-ai-slim --only-dev
208-
- run: rm .coverage/.coverage.*-py3.9-* # Exclude 3.9 coverage as it gets the wrong line numbers, causing invalid failures.
266+
- run: uv sync --group dev
209267
- run: uv run coverage combine
210-
211-
- run: uv run coverage html --show-contexts --title "Pydantic AI coverage for ${{ github.sha }}"
212-
213-
- name: Store coverage html
214-
uses: actions/upload-artifact@v4
215-
with:
216-
name: coverage-html
217-
path: htmlcov
218-
include-hidden-files: true
219-
220-
- run: uv run coverage xml
221-
222-
- run: uv run diff-cover coverage.xml --html-report index.html
223-
224-
- name: Store diff coverage html
225-
uses: actions/upload-artifact@v4
226-
with:
227-
name: diff-coverage-html
228-
path: index.html
229-
230-
- run: uv run coverage report --fail-under 100
231-
- run: uv run diff-cover coverage.xml --fail-under 100
268+
- run: uv run coverage report
232269

233270
- run: uv run strict-no-cover
234271
env:
@@ -260,7 +297,7 @@ jobs:
260297
# https://github.com/marketplace/actions/alls-green#why used for branch protection checks
261298
check:
262299
if: always()
263-
needs: [lint, mypy, docs, test-live, test, coverage, test-mcp-run-python]
300+
needs: [lint, mypy, docs, test-live, test, test-lowest-versions, test-examples, coverage, test-mcp-run-python]
264301
runs-on: ubuntu-latest
265302

266303
steps:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ typecheck-both: typecheck-pyright typecheck-mypy
6060

6161
.PHONY: test
6262
test: ## Run tests and collect coverage data
63-
COVERAGE_PROCESS_START=./pyproject.toml uv run coverage run -m pytest -n auto --dist=loadgroup
63+
uv run coverage run -m pytest -n auto --dist=loadgroup
6464
@uv run coverage combine
6565
@uv run coverage report
6666

docs/api/agent.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
- RunOutputDataT
1313
- capture_run_messages
1414
- InstrumentationSettings
15+
- EventStreamHandler

docs/api/durable_exec.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# `pydantic_ai.durable_exec`
2+
3+
::: pydantic_ai.durable_exec.temporal

docs/api/toolsets.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
- RenamedToolset
1313
- PreparedToolset
1414
- WrapperToolset
15+
- ToolsetFunc

docs/changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Pydantic AI is still pre-version 1, so breaking changes will occur, however:
1212
!!! note
1313
Here's a filtered list of the breaking changes for each version to help you upgrade Pydantic AI.
1414

15-
### v0.7.0 (2025-08-08)
15+
### v0.7.0 (2025-08-12)
1616

1717
See [#2458](https://github.com/pydantic/pydantic-ai/pull/2458) - `pydantic_ai.models.StreamedResponse` now yields a `FinalResultEvent` along with the existing `PartStartEvent` and `PartDeltaEvent`. If you're using `pydantic_ai.direct.model_request_stream` or `pydantic_ai.direct.model_request_stream_sync`, you may need to update your code to account for this.
1818

docs/evals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ _(This example is complete, it can be run "as is")_
313313

314314
You can control concurrency during evaluation (this might be useful to prevent exceeding a rate limit):
315315

316-
```python {title="parallel_evaluation_example.py" line_length="100"}
316+
```python {title="parallel_evaluation_example.py" line_length="100" test="skip"}
317317
import asyncio
318318
import time
319319

docs/message-history.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ custom processing logic.
334334
Pydantic AI provides a `history_processors` parameter on `Agent` that allows you to intercept and modify
335335
the message history before each model request.
336336

337+
!!! warning "History processors replace the message history"
338+
History processors replace the message history in the state with the processed messages, including the new user prompt part.
339+
This means that if you want to keep the original message history, you need to make a copy of it.
340+
337341
### Usage
338342

339343
The `history_processors` is a list of callables that take a list of
@@ -389,6 +393,9 @@ long_conversation_history: list[ModelMessage] = [] # Your long conversation his
389393
# result = agent.run_sync('What did we discuss?', message_history=long_conversation_history)
390394
```
391395

396+
!!! warning "Be careful when slicing the message history"
397+
When slicing the message history, you need to make sure that tool calls and returns are paired, otherwise the LLM may return an error. For more details, refer to [this GitHub issue](https://github.com/pydantic/pydantic-ai/issues/2050#issuecomment-3019976269).
398+
392399
#### `RunContext` parameter
393400

394401
History processors can optionally accept a [`RunContext`][pydantic_ai.tools.RunContext] parameter to access
@@ -449,6 +456,9 @@ async def summarize_old_messages(messages: list[ModelMessage]) -> list[ModelMess
449456
agent = Agent('openai:gpt-4o', history_processors=[summarize_old_messages])
450457
```
451458

459+
!!! warning "Be careful when summarizing the message history"
460+
When summarizing the message history, you need to make sure that tool calls and returns are paired, otherwise the LLM may return an error. For more details, refer to [this GitHub issue](https://github.com/pydantic/pydantic-ai/issues/2050#issuecomment-3019976269), where you can find examples of summarizing the message history.
461+
452462
### Testing History Processors
453463

454464
You can test what messages are actually sent to the model provider using

0 commit comments

Comments
 (0)