pydantic-ai-trace 0.1.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.
Files changed (64) hide show
  1. pydantic_ai_trace-0.1.0/.github/workflows/ci.yml +36 -0
  2. pydantic_ai_trace-0.1.0/.github/workflows/release.yml +70 -0
  3. pydantic_ai_trace-0.1.0/.gitignore +223 -0
  4. pydantic_ai_trace-0.1.0/AGENTS.md +33 -0
  5. pydantic_ai_trace-0.1.0/LICENSE +21 -0
  6. pydantic_ai_trace-0.1.0/PKG-INFO +96 -0
  7. pydantic_ai_trace-0.1.0/README.md +75 -0
  8. pydantic_ai_trace-0.1.0/frontend/.prettierrc +3 -0
  9. pydantic_ai_trace-0.1.0/frontend/eslint.config.js +12 -0
  10. pydantic_ai_trace-0.1.0/frontend/index.html +17 -0
  11. pydantic_ai_trace-0.1.0/frontend/package-lock.json +5654 -0
  12. pydantic_ai_trace-0.1.0/frontend/package.json +34 -0
  13. pydantic_ai_trace-0.1.0/frontend/src/api.ts +53 -0
  14. pydantic_ai_trace-0.1.0/frontend/src/app.server.test.tsx +56 -0
  15. pydantic_ai_trace-0.1.0/frontend/src/app.test.tsx +288 -0
  16. pydantic_ai_trace-0.1.0/frontend/src/app.tsx +195 -0
  17. pydantic_ai_trace-0.1.0/frontend/src/components/Block.tsx +52 -0
  18. pydantic_ai_trace-0.1.0/frontend/src/components/JsonTree.tsx +98 -0
  19. pydantic_ai_trace-0.1.0/frontend/src/components/KeyboardNav.tsx +276 -0
  20. pydantic_ai_trace-0.1.0/frontend/src/components/Markdown.tsx +63 -0
  21. pydantic_ai_trace-0.1.0/frontend/src/components/MessageCard.tsx +194 -0
  22. pydantic_ai_trace-0.1.0/frontend/src/components/ThemeToggle.tsx +38 -0
  23. pydantic_ai_trace-0.1.0/frontend/src/components/TraceView.tsx +47 -0
  24. pydantic_ai_trace-0.1.0/frontend/src/components/TreePane.test.tsx +58 -0
  25. pydantic_ai_trace-0.1.0/frontend/src/components/TreePane.tsx +150 -0
  26. pydantic_ai_trace-0.1.0/frontend/src/components/parts/CompactionPart.tsx +26 -0
  27. pydantic_ai_trace-0.1.0/frontend/src/components/parts/FallbackPart.tsx +21 -0
  28. pydantic_ai_trace-0.1.0/frontend/src/components/parts/FilePart.tsx +23 -0
  29. pydantic_ai_trace-0.1.0/frontend/src/components/parts/RetryPrompt.tsx +59 -0
  30. pydantic_ai_trace-0.1.0/frontend/src/components/parts/SystemPrompt.tsx +20 -0
  31. pydantic_ai_trace-0.1.0/frontend/src/components/parts/TextPart.tsx +20 -0
  32. pydantic_ai_trace-0.1.0/frontend/src/components/parts/ThinkingPart.tsx +23 -0
  33. pydantic_ai_trace-0.1.0/frontend/src/components/parts/ToolCallGroup.tsx +95 -0
  34. pydantic_ai_trace-0.1.0/frontend/src/components/parts/UserPrompt.tsx +63 -0
  35. pydantic_ai_trace-0.1.0/frontend/src/components/parts/common.tsx +156 -0
  36. pydantic_ai_trace-0.1.0/frontend/src/main.tsx +5 -0
  37. pydantic_ai_trace-0.1.0/frontend/src/pairing.test.ts +132 -0
  38. pydantic_ai_trace-0.1.0/frontend/src/pairing.ts +58 -0
  39. pydantic_ai_trace-0.1.0/frontend/src/parse.test.ts +142 -0
  40. pydantic_ai_trace-0.1.0/frontend/src/parse.ts +157 -0
  41. pydantic_ai_trace-0.1.0/frontend/src/selection.ts +14 -0
  42. pydantic_ai_trace-0.1.0/frontend/src/styles/index.css +781 -0
  43. pydantic_ai_trace-0.1.0/frontend/src/types.ts +167 -0
  44. pydantic_ai_trace-0.1.0/frontend/tsconfig.json +18 -0
  45. pydantic_ai_trace-0.1.0/frontend/vite.config.ts +21 -0
  46. pydantic_ai_trace-0.1.0/hatch_build.py +18 -0
  47. pydantic_ai_trace-0.1.0/pixi.lock +2560 -0
  48. pydantic_ai_trace-0.1.0/pixi.toml +40 -0
  49. pydantic_ai_trace-0.1.0/pyproject.toml +65 -0
  50. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/__init__.py +3 -0
  51. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/cli.py +114 -0
  52. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/export.py +54 -0
  53. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/scan.py +175 -0
  54. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/server.py +147 -0
  55. pydantic_ai_trace-0.1.0/src/pydantic_ai_trace/static/index.html +217 -0
  56. pydantic_ai_trace-0.1.0/tests/conftest.py +15 -0
  57. pydantic_ai_trace-0.1.0/tests/fixtures/broken.json +1 -0
  58. pydantic_ai_trace-0.1.0/tests/fixtures/full_trace.json +128 -0
  59. pydantic_ai_trace-0.1.0/tests/fixtures/runs/media_and_builtins.json +66 -0
  60. pydantic_ai_trace-0.1.0/tests/fixtures/runs/multi.jsonl +2 -0
  61. pydantic_ai_trace-0.1.0/tests/test_cli.py +95 -0
  62. pydantic_ai_trace-0.1.0/tests/test_export.py +53 -0
  63. pydantic_ai_trace-0.1.0/tests/test_scan.py +120 -0
  64. pydantic_ai_trace-0.1.0/tests/test_server.py +85 -0
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ checks:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
13
+ with:
14
+ fetch-depth: 0
15
+ - uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
16
+ with:
17
+ cache: true
18
+ - name: Lint
19
+ run: pixi run lint
20
+ - name: Typecheck
21
+ run: pixi run typecheck
22
+ - name: Test
23
+ run: pixi run test
24
+ - name: Build PyPI package (frontend + sdist + wheel)
25
+ run: pixi run build
26
+ - name: Verify frontend assets are packaged
27
+ run: |
28
+ unzip -l dist/*.whl | grep -q 'pydantic_ai_trace/static/index.html'
29
+ tar -tzf dist/*.tar.gz | grep -q 'src/pydantic_ai_trace/static/index.html'
30
+ - name: Smoke-test built wheel
31
+ run: |
32
+ python3 -m venv /tmp/smoke
33
+ /tmp/smoke/bin/pip install --quiet dist/*.whl
34
+ /tmp/smoke/bin/paitrace --version
35
+ /tmp/smoke/bin/paitrace export tests/fixtures/full_trace.json -o /tmp/smoke/out.html
36
+ grep -q __TRACE_DATA__ /tmp/smoke/out.html
@@ -0,0 +1,70 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ concurrency:
8
+ group: release-${{ github.ref }}
9
+ cancel-in-progress: false
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16
+ with:
17
+ fetch-depth: 0
18
+ - uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
19
+ with:
20
+ cache: true
21
+ - name: Verify tag matches package version
22
+ run: |
23
+ package_version="$(pixi run python -c 'from pydantic_ai_trace import __version__; print(__version__)')"
24
+ test "$GITHUB_REF_NAME" = "v$package_version"
25
+ - name: Run completion gate
26
+ run: |
27
+ pixi run lint
28
+ pixi run typecheck
29
+ pixi run test
30
+ - name: Build sdist and wheel (includes frontend assets)
31
+ run: pixi run build
32
+ - name: Verify frontend assets are packaged
33
+ run: |
34
+ unzip -l dist/*.whl | grep -q 'pydantic_ai_trace/static/index.html'
35
+ tar -tzf dist/*.tar.gz | grep -q 'src/pydantic_ai_trace/static/index.html'
36
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
37
+ with:
38
+ name: pypi-distributions
39
+ path: dist/*
40
+ if-no-files-found: error
41
+
42
+ publish:
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ environment: pypi
46
+ permissions:
47
+ id-token: write # PyPI trusted publishing
48
+ steps:
49
+ - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
50
+ with:
51
+ name: pypi-distributions
52
+ path: dist/
53
+
54
+ - name: Publish package on PyPI
55
+ uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
56
+
57
+ github-release:
58
+ needs: publish
59
+ runs-on: ubuntu-latest
60
+ permissions:
61
+ contents: write
62
+ steps:
63
+ - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
64
+ with:
65
+ name: pypi-distributions
66
+ path: dist/
67
+ - name: Create GitHub release
68
+ env:
69
+ GH_TOKEN: ${{ github.token }}
70
+ run: gh release create "$GITHUB_REF_NAME" dist/* --repo "$GITHUB_REPOSITORY" --generate-notes
@@ -0,0 +1,223 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ /parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
219
+
220
+ reference-material/
221
+ src/pydantic_ai_trace/static/
222
+ node_modules/
223
+ frontend/dist/
@@ -0,0 +1,33 @@
1
+ # Agent guide
2
+
3
+ ## Start here
4
+
5
+ - Treat `README.md` as the product contract and `pixi.toml` as the command source of truth.
6
+ - Read the relevant implementation and tests before changing behavior.
7
+ - Keep changes narrow: update the owning layer and its observable-behavior tests together.
8
+
9
+ ## Code map
10
+
11
+ - `src/pydantic_ai_trace/`: Python CLI, filesystem scanning, Starlette API/SSE, and HTML export.
12
+ - `frontend/src/`: Preact viewer. `parse.ts` normalizes wire data, `pairing.ts` relates tool calls to results, and `components/` renders it.
13
+ - `tests/`: Python tests and trace fixtures. Frontend tests live beside their source as `*.test.ts[x]`.
14
+ - `hatch_build.py`: package-build guard for the bundled frontend.
15
+
16
+ ## Invariants
17
+
18
+ - Treat trace contents and paths as untrusted input. Keep filesystem discovery and reads inside the configured root.
19
+ - Preserve trace order and raw data. Pair tool results chronologically; render unknown message and part variants through fallbacks.
20
+ - Keep the functional core (`scan`, parsing, pairing, selection) separate from filesystem, HTTP, browser, and DOM effects.
21
+ - `src/pydantic_ai_trace/static/index.html` is generated by `pixi run build-frontend`; change frontend sources instead.
22
+
23
+ ## Completion gate
24
+
25
+ Run focused tests while iterating. Before handing off a code change, run:
26
+
27
+ ```bash
28
+ pixi run lint
29
+ pixi run typecheck
30
+ pixi run test
31
+ ```
32
+
33
+ Run `pixi run build` when frontend, packaging, or release behavior changes. Work is complete when relevant behavior is covered, required commands pass, and `git status` contains only intentional changes.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Moritz Wilksch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: pydantic-ai-trace
3
+ Version: 0.1.0
4
+ Summary: Fast local web viewer for pydantic-ai traces (list[ModelMessage] JSON dumps)
5
+ Project-URL: Repository, https://github.com/moritzwilksch/pydantic-ai-trace
6
+ Author: Moritz Wilksch
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: agent,llm,pydantic-ai,trace,viewer
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Software Development :: Debuggers
16
+ Requires-Python: >=3.12
17
+ Requires-Dist: starlette>=0.40
18
+ Requires-Dist: uvicorn>=0.30
19
+ Requires-Dist: watchfiles>=0.24
20
+ Description-Content-Type: text/markdown
21
+
22
+ # pydantic-ai-trace
23
+
24
+ Use `pydantic-ai-trace` when you need to inspect an agent run from a JSON dump. Give it a [pydantic-ai](https://ai.pydantic.dev) `list[ModelMessage]` dump and it opens the run in a browser view.
25
+
26
+ It is a lightweight local tool. Point it at a trace or a directory of traces and it reads the files from disk, reloads them when they change, and exports individual traces as self-contained HTML files. Your traces stay on disk, with no hosted service or account.
27
+
28
+ <img width="1323" height="1008" alt="Screenshot of a trace open in pydantic-ai-trace" src="https://github.com/user-attachments/assets/cf4f0866-ae4f-449f-8967-1ff6a26a2638" />
29
+
30
+ ## What you can inspect
31
+
32
+ - The full request and response sequence, including prompts, text, thinking, tool calls, tool results, and unknown parts
33
+ - Tool calls paired with their results, including results in later messages
34
+ - Model, provider, timing, and token usage
35
+ - A searchable directory tree for `.json` and `.jsonl` traces
36
+ - Collapsible large values, rendered Markdown, and keyboard navigation
37
+
38
+ ## Run from a checkout
39
+
40
+ This project uses [pixi](https://pixi.sh). Build the bundled frontend once, then run `paitrace` with a trace file or directory.
41
+
42
+ ```bash
43
+ pixi run build-frontend
44
+ pixi run paitrace trace.json
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ```bash
50
+ # View one trace
51
+ pixi run paitrace trace.json
52
+
53
+ # Browse a directory tree of traces
54
+ pixi run paitrace ./my-traces/
55
+
56
+ # Write one trace to a standalone HTML file
57
+ pixi run paitrace export trace.json -o trace.html
58
+
59
+ # Choose a trace line when exporting a multi-trace JSONL file
60
+ pixi run paitrace export runs.jsonl --line 2
61
+ ```
62
+
63
+ The viewer binds to `127.0.0.1:1205` and opens your browser. Pass `--port`, `--host`, or `--no-open` to change that behavior.
64
+
65
+ ## Trace files
66
+
67
+ The viewer reads the JSON emitted by `ModelMessagesTypeAdapter.dump_json(messages)`:
68
+
69
+ - `.json`: one bare JSON array of `ModelMessage` objects
70
+ - `.jsonl`: one such array per line
71
+
72
+ When you open a directory, each line in a multi-trace `.jsonl` file is available as a separate trace.
73
+
74
+ ## Development
75
+
76
+ Run the API and frontend in separate terminals while working on the viewer.
77
+
78
+ ```bash
79
+ pixi run dev-api ./trace.json # API with reload on port 1205
80
+ pixi run dev-web # Vite with HMR, proxying /api
81
+ ```
82
+
83
+ ```bash
84
+ pixi run test # pytest and vitest
85
+ pixi run lint # ruff, prettier, and eslint
86
+ pixi run typecheck # pyright and TypeScript
87
+ pixi run build # bundled frontend plus sdist and wheel
88
+ ```
89
+
90
+ ## Releasing
91
+
92
+ Push a `vX.Y.Z` tag. The package version is derived from that tag, so no source file needs a
93
+ version bump. GitHub Actions runs the full check suite, builds the frontend into the wheel and
94
+ source distribution, publishes both to PyPI using trusted publishing, and creates a GitHub
95
+ release. Configure a `pypi` environment in GitHub and add this repository as a trusted publisher
96
+ for the `pydantic-ai-trace` project on PyPI before the first release.
@@ -0,0 +1,75 @@
1
+ # pydantic-ai-trace
2
+
3
+ Use `pydantic-ai-trace` when you need to inspect an agent run from a JSON dump. Give it a [pydantic-ai](https://ai.pydantic.dev) `list[ModelMessage]` dump and it opens the run in a browser view.
4
+
5
+ It is a lightweight local tool. Point it at a trace or a directory of traces and it reads the files from disk, reloads them when they change, and exports individual traces as self-contained HTML files. Your traces stay on disk, with no hosted service or account.
6
+
7
+ <img width="1323" height="1008" alt="Screenshot of a trace open in pydantic-ai-trace" src="https://github.com/user-attachments/assets/cf4f0866-ae4f-449f-8967-1ff6a26a2638" />
8
+
9
+ ## What you can inspect
10
+
11
+ - The full request and response sequence, including prompts, text, thinking, tool calls, tool results, and unknown parts
12
+ - Tool calls paired with their results, including results in later messages
13
+ - Model, provider, timing, and token usage
14
+ - A searchable directory tree for `.json` and `.jsonl` traces
15
+ - Collapsible large values, rendered Markdown, and keyboard navigation
16
+
17
+ ## Run from a checkout
18
+
19
+ This project uses [pixi](https://pixi.sh). Build the bundled frontend once, then run `paitrace` with a trace file or directory.
20
+
21
+ ```bash
22
+ pixi run build-frontend
23
+ pixi run paitrace trace.json
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ```bash
29
+ # View one trace
30
+ pixi run paitrace trace.json
31
+
32
+ # Browse a directory tree of traces
33
+ pixi run paitrace ./my-traces/
34
+
35
+ # Write one trace to a standalone HTML file
36
+ pixi run paitrace export trace.json -o trace.html
37
+
38
+ # Choose a trace line when exporting a multi-trace JSONL file
39
+ pixi run paitrace export runs.jsonl --line 2
40
+ ```
41
+
42
+ The viewer binds to `127.0.0.1:1205` and opens your browser. Pass `--port`, `--host`, or `--no-open` to change that behavior.
43
+
44
+ ## Trace files
45
+
46
+ The viewer reads the JSON emitted by `ModelMessagesTypeAdapter.dump_json(messages)`:
47
+
48
+ - `.json`: one bare JSON array of `ModelMessage` objects
49
+ - `.jsonl`: one such array per line
50
+
51
+ When you open a directory, each line in a multi-trace `.jsonl` file is available as a separate trace.
52
+
53
+ ## Development
54
+
55
+ Run the API and frontend in separate terminals while working on the viewer.
56
+
57
+ ```bash
58
+ pixi run dev-api ./trace.json # API with reload on port 1205
59
+ pixi run dev-web # Vite with HMR, proxying /api
60
+ ```
61
+
62
+ ```bash
63
+ pixi run test # pytest and vitest
64
+ pixi run lint # ruff, prettier, and eslint
65
+ pixi run typecheck # pyright and TypeScript
66
+ pixi run build # bundled frontend plus sdist and wheel
67
+ ```
68
+
69
+ ## Releasing
70
+
71
+ Push a `vX.Y.Z` tag. The package version is derived from that tag, so no source file needs a
72
+ version bump. GitHub Actions runs the full check suite, builds the frontend into the wheel and
73
+ source distribution, publishes both to PyPI using trusted publishing, and creates a GitHub
74
+ release. Configure a `pypi` environment in GitHub and add this repository as a trusted publisher
75
+ for the `pydantic-ai-trace` project on PyPI before the first release.
@@ -0,0 +1,3 @@
1
+ {
2
+ "printWidth": 100
3
+ }
@@ -0,0 +1,12 @@
1
+ import tseslint from "typescript-eslint";
2
+
3
+ export default tseslint.config(
4
+ ...tseslint.configs.recommended,
5
+ {
6
+ rules: {
7
+ "@typescript-eslint/no-explicit-any": "off",
8
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
9
+ },
10
+ },
11
+ { ignores: ["dist/"] },
12
+ );
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Trace Viewer</title>
7
+ <link
8
+ rel="icon"
9
+ type="image/svg+xml"
10
+ href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236d5ae6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='8' height='8' x='3' y='3' rx='2'/%3E%3Cpath d='M7 11v4a2 2 0 0 0 2 2h4'/%3E%3Crect width='8' height='8' x='13' y='13' rx='2'/%3E%3C/svg%3E"
11
+ />
12
+ </head>
13
+ <body>
14
+ <div id="app"></div>
15
+ <script type="module" src="/src/main.tsx"></script>
16
+ </body>
17
+ </html>