django-ag-ui 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.
- django_ag_ui-0.1.0/.github/workflows/release.yml +54 -0
- django_ag_ui-0.1.0/.github/workflows/tests.yml +95 -0
- django_ag_ui-0.1.0/.gitignore +122 -0
- django_ag_ui-0.1.0/.pre-commit-config.yaml +32 -0
- django_ag_ui-0.1.0/CHANGELOG.md +28 -0
- django_ag_ui-0.1.0/CLAUDE.md +173 -0
- django_ag_ui-0.1.0/LICENSE +21 -0
- django_ag_ui-0.1.0/Makefile +79 -0
- django_ag_ui-0.1.0/PKG-INFO +54 -0
- django_ag_ui-0.1.0/README.md +16 -0
- django_ag_ui-0.1.0/django_ag_ui/__init__.py +66 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/agent_factory.py +124 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/agui_view.py +188 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/resolve_agent_factory.py +19 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/resolve_dotted_instances.py +24 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/system_prompt.py +10 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/types/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/types/agent_config.py +44 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/types/agent_factory_fn.py +24 -0
- django_ag_ui-0.1.0/django_ag_ui/agent/urls.py +21 -0
- django_ag_ui-0.1.0/django_ag_ui/conf.py +87 -0
- django_ag_ui-0.1.0/django_ag_ui/constants.py +38 -0
- django_ag_ui-0.1.0/django_ag_ui/integrations/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/integrations/drf_mcp.py +77 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/django_session_conversation_store.py +60 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/model_conversation_store.py +52 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/null_conversation_store.py +26 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/resolve_conversation_store.py +30 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/types/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/types/conversation.py +22 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/types/conversation_store.py +26 -0
- django_ag_ui-0.1.0/django_ag_ui/persistence/utils.py +31 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/logging_audit_logger.py +37 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/null_audit_logger.py +13 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/resolve_audit_logger.py +31 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/types/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/types/audit_event.py +23 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/audit/types/audit_logger.py +22 -0
- django_ag_ui-0.1.0/django_ag_ui/policy/auto_confirm.py +18 -0
- django_ag_ui-0.1.0/django_ag_ui/py.typed +0 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/build_input_schema.py +99 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/decorator.py +55 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/tool_registry.py +95 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/types/__init__.py +0 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/types/tool_binding.py +22 -0
- django_ag_ui-0.1.0/django_ag_ui/registry/types/tool_spec.py +42 -0
- django_ag_ui-0.1.0/django_ag_ui/version.py +5 -0
- django_ag_ui-0.1.0/docs/api.md +80 -0
- django_ag_ui-0.1.0/docs/concepts.md +171 -0
- django_ag_ui-0.1.0/docs/configuration.md +167 -0
- django_ag_ui-0.1.0/docs/index.md +76 -0
- django_ag_ui-0.1.0/docs/installation.md +51 -0
- django_ag_ui-0.1.0/docs/quickstart.md +107 -0
- django_ag_ui-0.1.0/mkdocs.yml +80 -0
- django_ag_ui-0.1.0/pyproject.toml +144 -0
- django_ag_ui-0.1.0/scripts/release-publish.sh +211 -0
- django_ag_ui-0.1.0/tests/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/agent/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/agent/factories.py +28 -0
- django_ag_ui-0.1.0/tests/agent/test_agent_factory.py +139 -0
- django_ag_ui-0.1.0/tests/agent/test_agui_view.py +219 -0
- django_ag_ui-0.1.0/tests/agent/test_resolve_agent_factory.py +13 -0
- django_ag_ui-0.1.0/tests/agent/test_resolve_dotted_instances.py +22 -0
- django_ag_ui-0.1.0/tests/agent/test_system_prompt.py +8 -0
- django_ag_ui-0.1.0/tests/agent/test_urls.py +21 -0
- django_ag_ui-0.1.0/tests/conftest.py +0 -0
- django_ag_ui-0.1.0/tests/conftest_settings.py +32 -0
- django_ag_ui-0.1.0/tests/integrations/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/integrations/drf_server.py +26 -0
- django_ag_ui-0.1.0/tests/integrations/test_drf_mcp.py +38 -0
- django_ag_ui-0.1.0/tests/persistence/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/persistence/test_django_session_conversation_store.py +53 -0
- django_ag_ui-0.1.0/tests/persistence/test_model_conversation_store.py +34 -0
- django_ag_ui-0.1.0/tests/persistence/test_null_conversation_store.py +14 -0
- django_ag_ui-0.1.0/tests/persistence/test_resolve_conversation_store.py +31 -0
- django_ag_ui-0.1.0/tests/persistence/test_utils.py +48 -0
- django_ag_ui-0.1.0/tests/persistence/types/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/policy/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/policy/audit/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/policy/audit/test_logging_audit_logger.py +38 -0
- django_ag_ui-0.1.0/tests/policy/audit/test_null_audit_logger.py +10 -0
- django_ag_ui-0.1.0/tests/policy/audit/test_resolve_audit_logger.py +28 -0
- django_ag_ui-0.1.0/tests/policy/audit/types/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/policy/audit/types/test_audit_event.py +19 -0
- django_ag_ui-0.1.0/tests/policy/test_auto_confirm.py +28 -0
- django_ag_ui-0.1.0/tests/registry/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/registry/test_build_input_schema.py +117 -0
- django_ag_ui-0.1.0/tests/registry/test_decorator.py +82 -0
- django_ag_ui-0.1.0/tests/registry/test_tool_registry.py +70 -0
- django_ag_ui-0.1.0/tests/registry/types/__init__.py +0 -0
- django_ag_ui-0.1.0/tests/registry/types/test_tool_spec.py +23 -0
- django_ag_ui-0.1.0/tests/test_conf.py +58 -0
- django_ag_ui-0.1.0/tests/test_constants.py +20 -0
- django_ag_ui-0.1.0/tests/test_version.py +8 -0
- django_ag_ui-0.1.0/uv.lock +4811 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Main-triggered: every merge to `main` runs `release-publish-prepare`, which
|
|
4
|
+
# short-circuits to a no-op unless the version in source has been bumped past
|
|
5
|
+
# the most recent `vX.Y.Z` tag.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: release-main
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
release:
|
|
16
|
+
name: release
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment:
|
|
19
|
+
name: pypi
|
|
20
|
+
url: https://pypi.org/p/django-ag-ui
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write # PyPI OIDC trusted publishing
|
|
23
|
+
contents: write # tag push + gh release create
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v5
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
- uses: astral-sh/setup-uv@v7
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
- name: Install
|
|
32
|
+
run: uv sync --all-groups
|
|
33
|
+
|
|
34
|
+
- name: Prepare release (version check, test, build dist)
|
|
35
|
+
id: prepare
|
|
36
|
+
run: make release-publish-prepare
|
|
37
|
+
|
|
38
|
+
- name: Publish to PyPI
|
|
39
|
+
if: steps.prepare.outputs.released == 'true'
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
41
|
+
|
|
42
|
+
- name: Tag + GitHub Release
|
|
43
|
+
if: steps.prepare.outputs.released == 'true'
|
|
44
|
+
env:
|
|
45
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
46
|
+
run: make release-publish-finalize
|
|
47
|
+
|
|
48
|
+
- name: Deploy docs to gh-pages
|
|
49
|
+
if: steps.prepare.outputs.released == 'true' && hashFiles('mkdocs.yml') != ''
|
|
50
|
+
run: |
|
|
51
|
+
git config user.name 'github-actions[bot]'
|
|
52
|
+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
|
53
|
+
DJANGO_SETTINGS_MODULE=tests.conftest_settings \
|
|
54
|
+
uv run mkdocs gh-deploy --force --clean --config-file mkdocs.yml
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: tests-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
lint:
|
|
14
|
+
name: lint
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v5
|
|
18
|
+
- uses: astral-sh/setup-uv@v7
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
- name: Install
|
|
22
|
+
run: uv sync --all-groups
|
|
23
|
+
- name: ruff check
|
|
24
|
+
run: uv run ruff check .
|
|
25
|
+
- name: ruff format check
|
|
26
|
+
run: uv run ruff format --check --diff .
|
|
27
|
+
- name: ty
|
|
28
|
+
run: uv run ty check django_ag_ui
|
|
29
|
+
|
|
30
|
+
docs:
|
|
31
|
+
name: docs build
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v5
|
|
35
|
+
- uses: astral-sh/setup-uv@v7
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
- name: Install with docs group
|
|
39
|
+
run: uv sync --all-groups
|
|
40
|
+
- name: mkdocs build --strict
|
|
41
|
+
run: DJANGO_SETTINGS_MODULE=tests.conftest_settings uv run mkdocs build --strict
|
|
42
|
+
|
|
43
|
+
test:
|
|
44
|
+
name: ${{ matrix.python-version }} / Django ${{ matrix.django-version }}
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
strategy:
|
|
47
|
+
fail-fast: false
|
|
48
|
+
matrix:
|
|
49
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
50
|
+
django-version: ["4.2", "5.0", "5.1", "5.2", "6.0"]
|
|
51
|
+
exclude:
|
|
52
|
+
# Django 4.2 supports Python 3.8–3.12
|
|
53
|
+
- python-version: "3.13"
|
|
54
|
+
django-version: "4.2"
|
|
55
|
+
- python-version: "3.14"
|
|
56
|
+
django-version: "4.2"
|
|
57
|
+
# Django 5.0 supports Python 3.10–3.12
|
|
58
|
+
- python-version: "3.13"
|
|
59
|
+
django-version: "5.0"
|
|
60
|
+
- python-version: "3.14"
|
|
61
|
+
django-version: "5.0"
|
|
62
|
+
# Django 5.1 supports Python 3.10–3.13
|
|
63
|
+
- python-version: "3.14"
|
|
64
|
+
django-version: "5.1"
|
|
65
|
+
# Django 6.0 requires Python 3.12+
|
|
66
|
+
- python-version: "3.10"
|
|
67
|
+
django-version: "6.0"
|
|
68
|
+
- python-version: "3.11"
|
|
69
|
+
django-version: "6.0"
|
|
70
|
+
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v5
|
|
73
|
+
- uses: astral-sh/setup-uv@v7
|
|
74
|
+
with:
|
|
75
|
+
enable-cache: true
|
|
76
|
+
- name: Install Python ${{ matrix.python-version }}
|
|
77
|
+
run: uv python install ${{ matrix.python-version }}
|
|
78
|
+
- name: Sync dev deps
|
|
79
|
+
run: uv sync --all-groups --python ${{ matrix.python-version }}
|
|
80
|
+
- name: Pin Django ${{ matrix.django-version }}
|
|
81
|
+
run: uv pip install --reinstall-package django "django~=${{ matrix.django-version }}.0"
|
|
82
|
+
- name: pytest
|
|
83
|
+
run: |
|
|
84
|
+
uv run --no-sync pytest \
|
|
85
|
+
--cov-report=xml:coverage.xml \
|
|
86
|
+
--cov-report=html:htmlcov
|
|
87
|
+
- name: Upload coverage artifact
|
|
88
|
+
if: always()
|
|
89
|
+
uses: actions/upload-artifact@v5
|
|
90
|
+
with:
|
|
91
|
+
name: coverage-py${{ matrix.python-version }}-django${{ matrix.django-version }}
|
|
92
|
+
path: |
|
|
93
|
+
coverage.xml
|
|
94
|
+
htmlcov/
|
|
95
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
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
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.nox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
.cache
|
|
44
|
+
nosetests.xml
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
*.py,cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
.pytest_cache/
|
|
50
|
+
cover/
|
|
51
|
+
coverage*.json
|
|
52
|
+
coverage*.xml
|
|
53
|
+
|
|
54
|
+
# release.yml renders this at workflow-time and drops it under docs/ so
|
|
55
|
+
# mkdocs gh-deploy carries it to the gh-pages root.
|
|
56
|
+
docs/coverage.json
|
|
57
|
+
|
|
58
|
+
# Translations
|
|
59
|
+
*.mo
|
|
60
|
+
*.pot
|
|
61
|
+
|
|
62
|
+
# Django stuff
|
|
63
|
+
*.log
|
|
64
|
+
local_settings.py
|
|
65
|
+
db.sqlite3
|
|
66
|
+
db.sqlite3-journal
|
|
67
|
+
|
|
68
|
+
# Sphinx documentation
|
|
69
|
+
docs/_build/
|
|
70
|
+
|
|
71
|
+
# Environments
|
|
72
|
+
.env
|
|
73
|
+
.venv
|
|
74
|
+
env/
|
|
75
|
+
venv/
|
|
76
|
+
ENV/
|
|
77
|
+
env.bak/
|
|
78
|
+
venv.bak/
|
|
79
|
+
|
|
80
|
+
# Virtualenv-style scripts dirs (we re-include the repo-root scripts/ directory).
|
|
81
|
+
[Ss]cripts
|
|
82
|
+
!/scripts/
|
|
83
|
+
pyvenv.cfg
|
|
84
|
+
.Python
|
|
85
|
+
[Bb]in
|
|
86
|
+
[Ii]nclude
|
|
87
|
+
[Ll]ib
|
|
88
|
+
[Ll]ib64
|
|
89
|
+
[Ll]ocal
|
|
90
|
+
|
|
91
|
+
# uv
|
|
92
|
+
.uv-cache/
|
|
93
|
+
|
|
94
|
+
# mkdocs
|
|
95
|
+
/site
|
|
96
|
+
|
|
97
|
+
# Type checkers
|
|
98
|
+
.mypy_cache/
|
|
99
|
+
.dmypy.json
|
|
100
|
+
dmypy.json
|
|
101
|
+
.pyre/
|
|
102
|
+
.pytype/
|
|
103
|
+
.ruff_cache/
|
|
104
|
+
.ty_cache/
|
|
105
|
+
|
|
106
|
+
# IDE
|
|
107
|
+
.vscode/
|
|
108
|
+
.idea/
|
|
109
|
+
*.iml
|
|
110
|
+
*.code-workspace
|
|
111
|
+
.history/
|
|
112
|
+
|
|
113
|
+
# OS
|
|
114
|
+
.DS_Store
|
|
115
|
+
Thumbs.db
|
|
116
|
+
|
|
117
|
+
# Release metadata (rendered by scripts/release-publish.sh during CI)
|
|
118
|
+
.release-metadata/
|
|
119
|
+
|
|
120
|
+
# AI-specific items
|
|
121
|
+
.ai/
|
|
122
|
+
.claude/
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v6.0.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
args: ["--maxkb=2000"]
|
|
10
|
+
|
|
11
|
+
- repo: local
|
|
12
|
+
hooks:
|
|
13
|
+
- id: ruff-check
|
|
14
|
+
name: "ruff check --fix"
|
|
15
|
+
entry: make lint-fix
|
|
16
|
+
pass_filenames: false
|
|
17
|
+
language: system
|
|
18
|
+
stages: [pre-commit]
|
|
19
|
+
|
|
20
|
+
- id: ruff-format
|
|
21
|
+
name: "ruff format"
|
|
22
|
+
entry: make format
|
|
23
|
+
pass_filenames: false
|
|
24
|
+
language: system
|
|
25
|
+
stages: [pre-commit]
|
|
26
|
+
|
|
27
|
+
- id: backend-type-check
|
|
28
|
+
name: "type check (ty)"
|
|
29
|
+
entry: make type-check
|
|
30
|
+
pass_filenames: false
|
|
31
|
+
language: system
|
|
32
|
+
stages: [pre-commit]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] — 2026-06-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `ToolRegistry` + the `@tool` decorator (`destructive=` / `category=`), with
|
|
14
|
+
JSON-Schema derived from signatures and `x-destructive` / `x-category`
|
|
15
|
+
extensions.
|
|
16
|
+
- `DjangoAGUIView`, an async endpoint over Pydantic-AI's `AGUIAdapter` (SSE),
|
|
17
|
+
plus `get_urls()` for mounting.
|
|
18
|
+
- `AgentConfig` + `build_agent`, and the `DJANGO_AG_UI` settings (`MODEL`,
|
|
19
|
+
`MODEL_SETTINGS`, `RETRIES`, `AGENT_FACTORY`, `TOOLSETS`, `CAPABILITIES`,
|
|
20
|
+
`AUTO_CONFIRM`, `SYSTEM_PROMPT`).
|
|
21
|
+
- `AuditLogger` protocol with `NullAuditLogger` / `LoggingAuditLogger`.
|
|
22
|
+
- Opt-in server-side conversation persistence: the `ConversationStore` protocol,
|
|
23
|
+
`NullConversationStore` (default, stateless), `DjangoSessionConversationStore`,
|
|
24
|
+
and the abstract `ModelConversationStore` base.
|
|
25
|
+
- In-process `drf-mcp` toolset bridge behind the `[drf-mcp]` extra.
|
|
26
|
+
|
|
27
|
+
[Unreleased]: https://github.com/Artui/django-ag-ui/compare/v0.1.0...HEAD
|
|
28
|
+
[0.1.0]: https://github.com/Artui/django-ag-ui/releases/tag/v0.1.0
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Repo conventions for `django-ag-ui`
|
|
2
|
+
|
|
3
|
+
This file is the single source of truth for how to write code in this package.
|
|
4
|
+
Rules are non-negotiable unless flagged as a heuristic.
|
|
5
|
+
|
|
6
|
+
## What this package is
|
|
7
|
+
|
|
8
|
+
A Django ↔ Pydantic-AI ↔ [AG-UI](https://docs.ag-ui.com) integration. Provides:
|
|
9
|
+
- A tool registry (`ToolRegistry`, `@tool` decorator) with `destructive=` and `category=`
|
|
10
|
+
metadata, and a `build_input_schema` helper that emits an `x-destructive` JSON-Schema
|
|
11
|
+
extension when set.
|
|
12
|
+
- An async Django view (`DjangoAGUIView`) that wraps Pydantic-AI's
|
|
13
|
+
`pydantic_ai.ui.ag_ui.AGUIAdapter` and returns a `StreamingHttpResponse` of AG-UI events.
|
|
14
|
+
- An `AuditLogger` Protocol with `NullAuditLogger` and `LoggingAuditLogger` implementations.
|
|
15
|
+
- `conf.py` reading the `DJANGO_AG_UI` settings dict.
|
|
16
|
+
|
|
17
|
+
Downstream packages (e.g. `django-admin-agent`) build on this. **No admin specifics live in
|
|
18
|
+
this package.**
|
|
19
|
+
|
|
20
|
+
The design is at `/Users/arturveres/code/opensource/docs/plans/django-ag-ui-plan.md`.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
| Target | What it does |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `make init` | `uv sync --all-groups` + install pre-commit hooks |
|
|
27
|
+
| `make test` | pytest with 100% line+branch coverage gate |
|
|
28
|
+
| `make lint` | `ruff check .` + `ty check django_ag_ui` |
|
|
29
|
+
| `make format` | `ruff format .` |
|
|
30
|
+
| `make docs-serve` | live-reload mkdocs at `localhost:8000` |
|
|
31
|
+
| `make docs-build` | `mkdocs build --strict` |
|
|
32
|
+
| `make release-bump VERSION=X.Y.Z` | rewrite `version.py` + promote `[Unreleased]` in CHANGELOG |
|
|
33
|
+
| `make release-publish` | end-to-end workstation release |
|
|
34
|
+
|
|
35
|
+
## Structural rules
|
|
36
|
+
|
|
37
|
+
1. **One exported class or function per file.** File name = `snake_case` of the symbol.
|
|
38
|
+
`ToolRegistry` → `tool_registry.py`; `build_input_schema` → `build_input_schema.py`.
|
|
39
|
+
**Exception:** `django_ag_ui/constants.py` is the package's single home for enums and
|
|
40
|
+
constant-like module-level values, and is the only file allowed to export multiple symbols.
|
|
41
|
+
2. **Private helpers used in only one file** stay there with a leading `_`.
|
|
42
|
+
3. **Non-exported helpers shared across files** go into a sibling `utils.py`. Classes are
|
|
43
|
+
allowed in `utils.py` if they are internal infrastructure.
|
|
44
|
+
4. **Top-level imports only.** No function-local / lazy imports unless a circular import is
|
|
45
|
+
genuine and documented inline at the import site, **or** the dependency is optional —
|
|
46
|
+
those imports go inside the function body with a clear `ImportError` message.
|
|
47
|
+
5. **Full type annotations on every function and method signature.** `Any` is allowed only at
|
|
48
|
+
Django/Pydantic-AI boundaries where the type genuinely is `Any`.
|
|
49
|
+
6. **`__init__.py` is the only re-export point.** Each `__init__.py` lists the public surface
|
|
50
|
+
in `__all__`. Internal modules import from leaf paths, never from the package's `__init__`.
|
|
51
|
+
7. **Always `from __future__ import annotations`** at the top of any file with type
|
|
52
|
+
annotations. Python 3.10+, so no PEP 695 `type` statements.
|
|
53
|
+
8. **Absolute imports only.** Imports are ordered stdlib → third-party → first-party
|
|
54
|
+
(`django_ag_ui`). Within each block, alphabetical.
|
|
55
|
+
9. **NEVER use relative imports.** `from . import x`, `from .foo import bar`, any dotted-
|
|
56
|
+
relative form is forbidden everywhere in the package, including `__init__.py`. Always
|
|
57
|
+
write the full absolute path (`from django_ag_ui.foo import bar`).
|
|
58
|
+
10. **Types and functionality live in separate sub-packages.** When a directory contains both
|
|
59
|
+
type declarations (dataclasses, Protocols, frozen wire-shape records) and functionality
|
|
60
|
+
(callables, registries, dispatch helpers), the types move into a `types/` sibling.
|
|
61
|
+
`constants.py` remains the multi-export exception.
|
|
62
|
+
|
|
63
|
+
## API style rules
|
|
64
|
+
|
|
65
|
+
11. **Always dataclasses over `dict[str, Any]` for structured data.** Every wire-shape
|
|
66
|
+
payload, response envelope, configuration record, and tool spec field is a frozen
|
|
67
|
+
`@dataclass` with explicit field types. `dict[str, Any]` survives only at genuine
|
|
68
|
+
serialisation boundaries.
|
|
69
|
+
12. **Tool callables are typed.** Every registered tool declares typed parameters and a typed
|
|
70
|
+
return — no `**kwargs: Any` escape hatches. The registry uses signatures to derive JSON
|
|
71
|
+
Schema for AG-UI's tool definitions; an untyped tool breaks the schema.
|
|
72
|
+
|
|
73
|
+
## Security boundary
|
|
74
|
+
|
|
75
|
+
Per-tool `destructive: bool` metadata is the surfaced risk signal. The registry stamps it into
|
|
76
|
+
the JSON Schema as `x-destructive: true`; client-side AG-UI consumers (e.g. the
|
|
77
|
+
`@artui/ag-ui-web-component`) gate execution behind a confirmation modal. The wire stays
|
|
78
|
+
vanilla AG-UI.
|
|
79
|
+
|
|
80
|
+
The `AuditLogger` Protocol is the audit boundary. `LoggingAuditLogger` is the default;
|
|
81
|
+
projects supply their own (Sentry, Honeycomb, custom) by setting `DJANGO_AG_UI["AUDIT_LOGGER"]`
|
|
82
|
+
to a dotted path.
|
|
83
|
+
|
|
84
|
+
## No module-level or class-level mutable state
|
|
85
|
+
|
|
86
|
+
State lives on instances. Module-level constants (lookup tables, regexes, frozen settings
|
|
87
|
+
defaults, dispatch tables) are fine — module-level **mutable** state is not.
|
|
88
|
+
|
|
89
|
+
- No module-level mutable singletons (registries, caches, "warned-once" flags).
|
|
90
|
+
- No class-level mutable attributes declared on the class body. Initialise mutables in
|
|
91
|
+
`__init__`.
|
|
92
|
+
- The `ToolRegistry` is an instance: a `DjangoAGUIView` holds one; tests build a fresh
|
|
93
|
+
registry per scenario.
|
|
94
|
+
|
|
95
|
+
## Tests
|
|
96
|
+
|
|
97
|
+
- `make test` runs pytest with `--cov=django_ag_ui --cov-fail-under=100` (line + branch).
|
|
98
|
+
Restructure rather than reach for `# pragma: no cover`.
|
|
99
|
+
- Test layout mirrors the source tree under `tests/`. `django_ag_ui/foo/bar.py` →
|
|
100
|
+
`tests/foo/test_bar.py`.
|
|
101
|
+
- `tests/conftest_settings.py` is the Django settings module pytest uses (set via
|
|
102
|
+
`DJANGO_SETTINGS_MODULE` in `pyproject.toml`).
|
|
103
|
+
- Async tests: `async def test_...` with pytest-asyncio (`asyncio_mode = "auto"`).
|
|
104
|
+
- For the async view, use `httpx.AsyncClient` against the ASGI app to drive `RunAgentInput`
|
|
105
|
+
POSTs and parse the SSE event stream.
|
|
106
|
+
|
|
107
|
+
## Lint and types
|
|
108
|
+
|
|
109
|
+
- `make lint` runs `ruff check .` + `ty check django_ag_ui`. CI fails on either.
|
|
110
|
+
- `ruff format` is the source of truth for layout.
|
|
111
|
+
- Pre-commit runs `make lint-fix`, `make format`, `make type-check`. Commits must be clean
|
|
112
|
+
before push — never `--no-verify`.
|
|
113
|
+
- `ty` is scoped to `django_ag_ui/` only (not tests).
|
|
114
|
+
|
|
115
|
+
## Boundaries
|
|
116
|
+
|
|
117
|
+
- The package depends on `pydantic-ai[ag-ui]` for the AGUIAdapter. The AG-UI wire types come
|
|
118
|
+
from there; don't re-implement them.
|
|
119
|
+
- No admin specifics. Anything that touches `django.contrib.admin` belongs in
|
|
120
|
+
`django-admin-agent`, not here.
|
|
121
|
+
- The `agent/` layer does not import from `registry/types`; it imports the public re-exports
|
|
122
|
+
from `django_ag_ui.registry`.
|
|
123
|
+
|
|
124
|
+
## Compatibility floor
|
|
125
|
+
|
|
126
|
+
| Component | Floor | Tested |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| Python | 3.10 | 3.10, 3.11, 3.12, 3.13, 3.14 |
|
|
129
|
+
| Django | 4.2 LTS | 4.2, 5.0, 5.1, 5.2, 6.0 |
|
|
130
|
+
| Pydantic-AI | 1.0 (with `[ag-ui]` extra) | latest in matrix |
|
|
131
|
+
|
|
132
|
+
## Branching
|
|
133
|
+
|
|
134
|
+
When working on a new feature or version bump, **ALWAYS** switch to a new branch first
|
|
135
|
+
(`git checkout -b feat/...` or `release/vX.Y.Z`) and push to that branch. Never commit
|
|
136
|
+
feature work or version bumps directly to `main`, and never push to `main` from the local
|
|
137
|
+
checkout — `main` only advances via merged PRs (or, for releases, the tagged commit produced
|
|
138
|
+
on the release branch).
|
|
139
|
+
|
|
140
|
+
## Releases
|
|
141
|
+
|
|
142
|
+
Merge-to-main triggered. `.github/workflows/release.yml` runs on every push to `main` and
|
|
143
|
+
calls `make release-publish-prepare`. The script in `scripts/release-publish.sh` is the
|
|
144
|
+
single source of truth:
|
|
145
|
+
|
|
146
|
+
1. Extract version from `django_ag_ui/version.py`.
|
|
147
|
+
2. Short-circuit if `vX.Y.Z` already exists locally or on origin.
|
|
148
|
+
3. Run `uv run pytest` as a final gate.
|
|
149
|
+
4. `uv build` into `dist/`.
|
|
150
|
+
5. Extract the `## [X.Y.Z]` section from `CHANGELOG.md` into release notes.
|
|
151
|
+
6. Emit `released=true`.
|
|
152
|
+
|
|
153
|
+
If released:
|
|
154
|
+
- Publish to PyPI via OIDC trusted publishing.
|
|
155
|
+
- Tag, push, create GitHub Release.
|
|
156
|
+
- `mkdocs gh-deploy` to `gh-pages`.
|
|
157
|
+
|
|
158
|
+
### Cutting a release
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
make release-bump VERSION=0.2.0
|
|
162
|
+
git diff
|
|
163
|
+
git commit -am "Release 0.2.0"
|
|
164
|
+
git push -u origin release/0.2.0
|
|
165
|
+
gh pr create
|
|
166
|
+
# Merge to main; release.yml fires on the merge commit.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### One-time setup (manual)
|
|
170
|
+
|
|
171
|
+
1. **PyPI Trusted Publisher** — `Artui/django-ag-ui`, workflow `release.yml`, environment `pypi`.
|
|
172
|
+
2. **GitHub Environment** — create `pypi` (no secrets; OIDC).
|
|
173
|
+
3. **GitHub Pages** — branch `gh-pages` (created on first release with docs).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Artur Veres
|
|
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,79 @@
|
|
|
1
|
+
.PHONY: help init test lint lint-fix format format-check type-check deps-bump docs-serve docs-build release-bump release-publish release-publish-prepare release-publish-finalize
|
|
2
|
+
|
|
3
|
+
help:
|
|
4
|
+
@echo "Available targets:"
|
|
5
|
+
@echo " init Sync deps (all groups) and install pre-commit hooks"
|
|
6
|
+
@echo " test Run pytest with coverage (100% required)"
|
|
7
|
+
@echo " lint Run ruff check + ty check"
|
|
8
|
+
@echo " lint-fix Auto-fix lint issues with ruff"
|
|
9
|
+
@echo " format Format with ruff"
|
|
10
|
+
@echo " format-check Verify formatting"
|
|
11
|
+
@echo " type-check Run ty over the package"
|
|
12
|
+
@echo " deps-bump Upgrade pinned dependencies"
|
|
13
|
+
@echo " docs-serve Live-reload docs at http://localhost:8000 (needs mkdocs.yml)"
|
|
14
|
+
@echo " docs-build Build docs into ./site (strict — fails on broken links)"
|
|
15
|
+
@echo " release-bump Bump version files + CHANGELOG. Usage: make release-bump VERSION=X.Y.Z"
|
|
16
|
+
@echo " release-publish prepare → uv publish → finalize (workstation release)"
|
|
17
|
+
@echo " release-publish-prepare Run by release.yml on push to main (no-op unless bumped)"
|
|
18
|
+
@echo " release-publish-finalize Tag vX.Y.Z + create GitHub Release after PyPI publish"
|
|
19
|
+
|
|
20
|
+
init:
|
|
21
|
+
uv sync --all-groups
|
|
22
|
+
uv run pre-commit install
|
|
23
|
+
|
|
24
|
+
test:
|
|
25
|
+
uv run pytest
|
|
26
|
+
|
|
27
|
+
lint:
|
|
28
|
+
uv run ruff check .
|
|
29
|
+
uv run ty check django_ag_ui
|
|
30
|
+
|
|
31
|
+
lint-fix:
|
|
32
|
+
uv run ruff check --fix .
|
|
33
|
+
|
|
34
|
+
format:
|
|
35
|
+
uv run ruff format .
|
|
36
|
+
|
|
37
|
+
format-check:
|
|
38
|
+
uv run ruff format --check --diff .
|
|
39
|
+
|
|
40
|
+
type-check:
|
|
41
|
+
uv run ty check django_ag_ui
|
|
42
|
+
|
|
43
|
+
deps-bump:
|
|
44
|
+
uvx uv-upx upgrade run --profile with_pinned
|
|
45
|
+
|
|
46
|
+
docs-serve:
|
|
47
|
+
uv run --group docs mkdocs serve
|
|
48
|
+
|
|
49
|
+
docs-build:
|
|
50
|
+
uv run --group docs mkdocs build --strict
|
|
51
|
+
|
|
52
|
+
release-bump:
|
|
53
|
+
@if [ -z "$(VERSION)" ]; then \
|
|
54
|
+
echo "Usage: make release-bump VERSION=X.Y.Z"; exit 1; \
|
|
55
|
+
fi
|
|
56
|
+
uvx bump-my-version bump --new-version "$(VERSION)" patch
|
|
57
|
+
@echo ""
|
|
58
|
+
@echo "Bumped to $(VERSION). Edit CHANGELOG.md to fill the new section,"
|
|
59
|
+
@echo "review with 'git diff', then run 'make release-publish'."
|
|
60
|
+
|
|
61
|
+
# Release pipeline. Version lives in django_ag_ui/version.py
|
|
62
|
+
# (pyproject pulls it in via [tool.hatch.version] dynamic).
|
|
63
|
+
RELEASE_PACKAGE_NAME := django-ag-ui
|
|
64
|
+
RELEASE_VERSION_FILES := django_ag_ui/version.py|^__version__[^=]*= *
|
|
65
|
+
|
|
66
|
+
release-publish:
|
|
67
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
68
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
69
|
+
bash scripts/release-publish.sh all
|
|
70
|
+
|
|
71
|
+
release-publish-prepare:
|
|
72
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
73
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
74
|
+
bash scripts/release-publish.sh prepare
|
|
75
|
+
|
|
76
|
+
release-publish-finalize:
|
|
77
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
78
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
79
|
+
bash scripts/release-publish.sh finalize
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-ag-ui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Django ↔ Pydantic-AI ↔ AG-UI integration: async view, tool registry, audit logger.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Artui/django-ag-ui
|
|
6
|
+
Project-URL: Repository, https://github.com/Artui/django-ag-ui
|
|
7
|
+
Project-URL: Issues, https://github.com/Artui/django-ag-ui/issues
|
|
8
|
+
Author-email: Artur Veres <artur8118@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ag-ui,agent,ai,django,llm,pydantic-ai
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Web Environment
|
|
14
|
+
Classifier: Framework :: Django
|
|
15
|
+
Classifier: Framework :: Django :: 4.2
|
|
16
|
+
Classifier: Framework :: Django :: 5.0
|
|
17
|
+
Classifier: Framework :: Django :: 5.1
|
|
18
|
+
Classifier: Framework :: Django :: 5.2
|
|
19
|
+
Classifier: Framework :: Django :: 6.0
|
|
20
|
+
Classifier: Intended Audience :: Developers
|
|
21
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
22
|
+
Classifier: Operating System :: OS Independent
|
|
23
|
+
Classifier: Programming Language :: Python
|
|
24
|
+
Classifier: Programming Language :: Python :: 3
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
30
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
31
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
32
|
+
Requires-Python: >=3.10
|
|
33
|
+
Requires-Dist: django>=4.2
|
|
34
|
+
Requires-Dist: pydantic-ai[ag-ui]>=1.0
|
|
35
|
+
Provides-Extra: drf-mcp
|
|
36
|
+
Requires-Dist: djangorestframework-mcp-server>=0.5; extra == 'drf-mcp'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# django-ag-ui
|
|
40
|
+
|
|
41
|
+
[](https://github.com/Artui/django-ag-ui/actions/workflows/tests.yml)
|
|
42
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
43
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
44
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
45
|
+
[](https://github.com/astral-sh/ruff)
|
|
46
|
+
[](https://github.com/Artui/django-ag-ui/blob/main/LICENSE)
|
|
47
|
+
|
|
48
|
+
Django ↔ [Pydantic-AI](https://ai.pydantic.dev) ↔ [AG-UI](https://docs.ag-ui.com) integration: async view, tool registry with `destructive`/`category` metadata, audit logger.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install django-ag-ui
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
See the [docs](https://artui.github.io/django-ag-ui/) for the full surface.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# django-ag-ui
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Artui/django-ag-ui/actions/workflows/tests.yml)
|
|
4
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
5
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
6
|
+
[](https://pypi.org/project/django-ag-ui/)
|
|
7
|
+
[](https://github.com/astral-sh/ruff)
|
|
8
|
+
[](https://github.com/Artui/django-ag-ui/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
Django ↔ [Pydantic-AI](https://ai.pydantic.dev) ↔ [AG-UI](https://docs.ag-ui.com) integration: async view, tool registry with `destructive`/`category` metadata, audit logger.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install django-ag-ui
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
See the [docs](https://artui.github.io/django-ag-ui/) for the full surface.
|