django-admin-agent 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_admin_agent-0.1.0/.github/workflows/release.yml +81 -0
- django_admin_agent-0.1.0/.github/workflows/tests.yml +95 -0
- django_admin_agent-0.1.0/.gitignore +122 -0
- django_admin_agent-0.1.0/.pre-commit-config.yaml +32 -0
- django_admin_agent-0.1.0/CHANGELOG.md +29 -0
- django_admin_agent-0.1.0/CLAUDE.md +146 -0
- django_admin_agent-0.1.0/LICENSE +21 -0
- django_admin_agent-0.1.0/Makefile +116 -0
- django_admin_agent-0.1.0/PKG-INFO +142 -0
- django_admin_agent-0.1.0/README.md +104 -0
- django_admin_agent-0.1.0/django_admin_agent/__init__.py +19 -0
- django_admin_agent-0.1.0/django_admin_agent/admin/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/admin/build_route_map.py +50 -0
- django_admin_agent-0.1.0/django_admin_agent/admin/build_sidebar_context.py +44 -0
- django_admin_agent-0.1.0/django_admin_agent/admin/sidebar_admin_site.py +26 -0
- django_admin_agent-0.1.0/django_admin_agent/conf.py +43 -0
- django_admin_agent-0.1.0/django_admin_agent/py.typed +0 -0
- django_admin_agent-0.1.0/django_admin_agent/static/django_admin_agent/admin_agent.js +50 -0
- django_admin_agent-0.1.0/django_admin_agent/static/django_admin_agent/admin_tools.js +482 -0
- django_admin_agent-0.1.0/django_admin_agent/static/django_admin_agent/ag-ui-web-component.bundle.js +319 -0
- django_admin_agent-0.1.0/django_admin_agent/static/django_admin_agent/unfold_shim.js +57 -0
- django_admin_agent-0.1.0/django_admin_agent/templates/django_admin_agent/sidebar.html +9 -0
- django_admin_agent-0.1.0/django_admin_agent/templatetags/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/templatetags/django_admin_agent.py +24 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/get_settings_summary.py +70 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/inspect_modeladmin.py +83 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/list_admin_models.py +44 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/list_installed_apps.py +23 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/list_models.py +35 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/list_signals.py +71 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/list_urls.py +39 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/introspect/register.py +25 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/register.py +26 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/count_model.py +24 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/get_model_instance.py +31 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/inspect_model_schema.py +56 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/query_model.py +49 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/shell/register.py +19 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/types/__init__.py +0 -0
- django_admin_agent-0.1.0/django_admin_agent/tools/utils.py +33 -0
- django_admin_agent-0.1.0/django_admin_agent/urls.py +38 -0
- django_admin_agent-0.1.0/django_admin_agent/version.py +5 -0
- django_admin_agent-0.1.0/docs/admin-wiring.md +92 -0
- django_admin_agent-0.1.0/docs/configuration.md +76 -0
- django_admin_agent-0.1.0/docs/index.md +63 -0
- django_admin_agent-0.1.0/docs/installation.md +138 -0
- django_admin_agent-0.1.0/docs/reference.md +57 -0
- django_admin_agent-0.1.0/docs/tools.md +153 -0
- django_admin_agent-0.1.0/docs/unfold.md +66 -0
- django_admin_agent-0.1.0/mkdocs.yml +81 -0
- django_admin_agent-0.1.0/pyproject.toml +147 -0
- django_admin_agent-0.1.0/scripts/release-publish.sh +211 -0
- django_admin_agent-0.1.0/tests/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/admin/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/admin/test_build_route_map.py +25 -0
- django_admin_agent-0.1.0/tests/admin/test_build_sidebar_context.py +28 -0
- django_admin_agent-0.1.0/tests/admin/test_sidebar_admin_site.py +30 -0
- django_admin_agent-0.1.0/tests/admin/urls_no_admin.py +11 -0
- django_admin_agent-0.1.0/tests/conftest.py +0 -0
- django_admin_agent-0.1.0/tests/conftest_settings.py +57 -0
- django_admin_agent-0.1.0/tests/e2e/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/e2e/conftest.py +22 -0
- django_admin_agent-0.1.0/tests/e2e/scripted_model.py +87 -0
- django_admin_agent-0.1.0/tests/e2e/settings.py +61 -0
- django_admin_agent-0.1.0/tests/e2e/templates/admin/base_site.html +7 -0
- django_admin_agent-0.1.0/tests/e2e/test_vanilla.py +41 -0
- django_admin_agent-0.1.0/tests/e2e/urls.py +12 -0
- django_admin_agent-0.1.0/tests/templatetags/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/templatetags/test_django_admin_agent.py +28 -0
- django_admin_agent-0.1.0/tests/test_conf.py +33 -0
- django_admin_agent-0.1.0/tests/test_urls.py +33 -0
- django_admin_agent-0.1.0/tests/test_version.py +8 -0
- django_admin_agent-0.1.0/tests/testapp/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/testapp/admin.py +37 -0
- django_admin_agent-0.1.0/tests/testapp/apps.py +9 -0
- django_admin_agent-0.1.0/tests/testapp/migrations/0001_initial.py +65 -0
- django_admin_agent-0.1.0/tests/testapp/migrations/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/testapp/models.py +25 -0
- django_admin_agent-0.1.0/tests/testapp/urls.py +8 -0
- django_admin_agent-0.1.0/tests/tools/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/tools/introspect/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/tools/introspect/test_introspect_tools.py +143 -0
- django_admin_agent-0.1.0/tests/tools/shell/__init__.py +0 -0
- django_admin_agent-0.1.0/tests/tools/shell/test_shell_tools.py +95 -0
- django_admin_agent-0.1.0/tests/tools/test_register.py +53 -0
- django_admin_agent-0.1.0/tests/tools/test_utils.py +23 -0
- django_admin_agent-0.1.0/uv.lock +5046 -0
|
@@ -0,0 +1,81 @@
|
|
|
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-admin-agent
|
|
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
|
+
# Embed a coverage-badge JSON into the docs build so `mkdocs gh-deploy`
|
|
49
|
+
# carries it to the gh-pages root, where the README's shields.io endpoint
|
|
50
|
+
# badge reads it. `release-publish-prepare`'s pytest run wrote .coverage
|
|
51
|
+
# to the workspace root.
|
|
52
|
+
- name: Render coverage badge for the docs site
|
|
53
|
+
if: steps.prepare.outputs.released == 'true' && hashFiles('mkdocs.yml') != ''
|
|
54
|
+
run: |
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
uv run coverage xml -o coverage.xml
|
|
57
|
+
python - <<'PY'
|
|
58
|
+
import json
|
|
59
|
+
import xml.etree.ElementTree as ET
|
|
60
|
+
|
|
61
|
+
pct = round(float(ET.parse("coverage.xml").getroot().attrib["line-rate"]) * 100, 1)
|
|
62
|
+
color = (
|
|
63
|
+
"brightgreen" if pct >= 95
|
|
64
|
+
else "green" if pct >= 85
|
|
65
|
+
else "yellow" if pct >= 70
|
|
66
|
+
else "red"
|
|
67
|
+
)
|
|
68
|
+
payload = {"schemaVersion": 1, "label": "coverage", "message": f"{pct}%", "color": color}
|
|
69
|
+
with open("docs/coverage.json", "w") as fh:
|
|
70
|
+
json.dump(payload, fh)
|
|
71
|
+
fh.write("\n")
|
|
72
|
+
print(json.dumps(payload))
|
|
73
|
+
PY
|
|
74
|
+
|
|
75
|
+
- name: Deploy docs + coverage badge to gh-pages
|
|
76
|
+
if: steps.prepare.outputs.released == 'true' && hashFiles('mkdocs.yml') != ''
|
|
77
|
+
run: |
|
|
78
|
+
git config user.name 'github-actions[bot]'
|
|
79
|
+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
|
80
|
+
DJANGO_SETTINGS_MODULE=tests.conftest_settings \
|
|
81
|
+
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_admin_agent
|
|
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,29 @@
|
|
|
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
|
+
- Chat-agent sidebar for the Django admin, built on `django-ag-ui` and the
|
|
14
|
+
vendored `@artooi/ag-ui-web-component` `<ag-ui-chat>` bundle.
|
|
15
|
+
- Default server-side tool registry (`build_default_registry`) of read-only
|
|
16
|
+
`shell.*` (query / count / fetch / inspect-schema) and `introspect.*`
|
|
17
|
+
(model + admin registration) tools, plus `register_*_tools` builders and
|
|
18
|
+
`get_urls()` to mount the agent endpoint.
|
|
19
|
+
- Frontend admin tool layer: `nav.*` navigation and DOM-driving handlers
|
|
20
|
+
(fill field, click, apply changelist filter) with visible animations, and a
|
|
21
|
+
confirmation modal gating `x-destructive` tools.
|
|
22
|
+
- Sidebar wiring: the `{% django_admin_agent_sidebar %}` template tag and a
|
|
23
|
+
`SidebarAdminSite` (`each_context`) path, with an admin route + page map.
|
|
24
|
+
- Django Unfold compatibility shim (runtime JS; lazy, guarded Python).
|
|
25
|
+
- Optional `[mcp]` extra exposing the admin tools as an HTTP MCP server via
|
|
26
|
+
`djangorestframework-mcp-server`.
|
|
27
|
+
|
|
28
|
+
[Unreleased]: https://github.com/Artui/django-admin-agent/compare/v0.1.0...HEAD
|
|
29
|
+
[0.1.0]: https://github.com/Artui/django-admin-agent/releases/tag/v0.1.0
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Repo conventions for `django-admin-agent`
|
|
2
|
+
|
|
3
|
+
Single source of truth for how to write code here. Rules are non-negotiable
|
|
4
|
+
unless flagged as a heuristic.
|
|
5
|
+
|
|
6
|
+
## What this package is
|
|
7
|
+
|
|
8
|
+
An always-present chat-agent sidebar embedded in the Django admin. It depends
|
|
9
|
+
on two sibling packages:
|
|
10
|
+
- **`django-ag-ui`** — the Django ↔ Pydantic-AI ↔ AG-UI bridge. Provides
|
|
11
|
+
`ToolRegistry`, the `@tool` decorator, `DjangoAGUIView`, `get_urls`, the
|
|
12
|
+
audit logger. This package *builds on* those; it does not reimplement them.
|
|
13
|
+
- **`@artooi/ag-ui-web-component`** — the `<ag-ui-chat>` Web Component. We
|
|
14
|
+
vendor its built bundle into `django_admin_agent/static/django_admin_agent/`
|
|
15
|
+
and load it from the admin templates.
|
|
16
|
+
|
|
17
|
+
This package adds: server-side admin tools (`shell.*` / `introspect.*` /
|
|
18
|
+
`nav.*`), the admin-specific frontend tool handlers (DOM driving), the
|
|
19
|
+
`SidebarAdminSite` / `each_context` / template-tag plumbing, and an Unfold
|
|
20
|
+
compatibility shim.
|
|
21
|
+
|
|
22
|
+
The design is at `/Users/arturveres/code/opensource/docs/plans/django-ag-ui-plan.md`.
|
|
23
|
+
|
|
24
|
+
## Local development
|
|
25
|
+
|
|
26
|
+
`django-ag-ui` is resolved from PyPI via the plain `django-ag-ui>=0.1` pin in
|
|
27
|
+
`pyproject.toml` (so CI, which has no sibling checkout, syncs cleanly). To
|
|
28
|
+
develop both packages together against a local checkout, add a `[tool.uv.sources]`
|
|
29
|
+
override *locally* (do not commit it) and `uv sync`:
|
|
30
|
+
|
|
31
|
+
```toml
|
|
32
|
+
[tool.uv.sources]
|
|
33
|
+
django-ag-ui = { path = "../django-ag-ui", editable = true }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### The vendored web-component bundle
|
|
37
|
+
|
|
38
|
+
`django_admin_agent/static/django_admin_agent/ag-ui-web-component.bundle.js` is
|
|
39
|
+
a **build artefact**, not hand-written — it is esbuild's minified output from
|
|
40
|
+
`@artooi/ag-ui-web-component` (TypeScript source), with `@ag-ui/*` inlined.
|
|
41
|
+
|
|
42
|
+
The bundle is **version-pinned** in the `Makefile` (`WEB_COMPONENT_VERSION`).
|
|
43
|
+
That pin is the source of truth:
|
|
44
|
+
|
|
45
|
+
- **Release** re-vendors the pinned published version. `make
|
|
46
|
+
release-publish-prepare` runs `make vendor-bundle-release` (which `npm pack`s
|
|
47
|
+
`@artooi/ag-ui-web-component@$(WEB_COMPONENT_VERSION)` and copies its built
|
|
48
|
+
bundle) *before* building the wheel. So a released wheel always ships exactly
|
|
49
|
+
the pinned bundle — ongoing web-component changes can never retroactively
|
|
50
|
+
break a released `django-admin-agent`, and bumping the bundle is a deliberate
|
|
51
|
+
`WEB_COMPONENT_VERSION` change + release.
|
|
52
|
+
- **Dev** uses `make vendor-bundle` to copy from the sibling
|
|
53
|
+
`../ag-ui-web-component/dist/` checkout. The committed copy is a convenience
|
|
54
|
+
(so `git clone` + `runserver` works) and may drift; the release re-vendor is
|
|
55
|
+
the authoritative refresh.
|
|
56
|
+
|
|
57
|
+
To adopt a new web-component version: bump `WEB_COMPONENT_VERSION`, run `make
|
|
58
|
+
vendor-bundle-release` (or `vendor-bundle` in dev), commit, release.
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
| Target | What it does |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `make init` | `uv sync --all-groups` + install pre-commit hooks |
|
|
65
|
+
| `make test` | pytest with 100% line+branch coverage gate |
|
|
66
|
+
| `make lint` | `ruff check .` + `ty check django_admin_agent` |
|
|
67
|
+
| `make format` | `ruff format .` |
|
|
68
|
+
| `make docs-build` | `mkdocs build --strict` |
|
|
69
|
+
| `make release-bump VERSION=X.Y.Z` | rewrite `version.py` + promote CHANGELOG |
|
|
70
|
+
|
|
71
|
+
## Structural rules
|
|
72
|
+
|
|
73
|
+
1. **One exported class or function per file.** File name = `snake_case` of the
|
|
74
|
+
symbol. `constants.py` is the only multi-export file (enums + constants).
|
|
75
|
+
2. **Private one-file helpers** stay local with a leading `_`.
|
|
76
|
+
3. **Cross-file non-exported helpers** go in a sibling `utils.py`.
|
|
77
|
+
4. **Top-level imports only.** Optional deps (`unfold`, `rest_framework_mcp`)
|
|
78
|
+
import lazily inside function bodies with a clear `ImportError` message.
|
|
79
|
+
5. **Full type annotations** on every signature. `Any` only at Django ORM /
|
|
80
|
+
admin boundaries where the type genuinely is `Any`.
|
|
81
|
+
6. **`__init__.py` is the only re-export point.** Internal modules import from
|
|
82
|
+
leaf paths, never from the package `__init__`.
|
|
83
|
+
7. **Always `from __future__ import annotations`.** Python 3.10+, no PEP 695
|
|
84
|
+
`type` statements, no `match`.
|
|
85
|
+
8. **Absolute imports only**, ordered stdlib → third-party → first-party
|
|
86
|
+
(`django_admin_agent`). Never relative.
|
|
87
|
+
9. **Types and functionality in separate sub-packages** (`types/` siblings).
|
|
88
|
+
|
|
89
|
+
## Reuse, don't reimplement
|
|
90
|
+
|
|
91
|
+
The agent loop, tool registry, AG-UI transport, and audit logger live in
|
|
92
|
+
`django-ag-ui`. Import them:
|
|
93
|
+
- `django_ag_ui.ToolRegistry`, `django_ag_ui.tool` (the `@tool` decorator),
|
|
94
|
+
`django_ag_ui.ToolCategory`
|
|
95
|
+
- `django_ag_ui.DjangoAGUIView`, `django_ag_ui.get_urls`
|
|
96
|
+
- `django_ag_ui.AuditLogger` and friends
|
|
97
|
+
|
|
98
|
+
This package contributes *tools* and *admin wiring*, not transport.
|
|
99
|
+
|
|
100
|
+
## No module-level or class-level mutable state
|
|
101
|
+
|
|
102
|
+
State lives on instances. No module-level mutable singletons or class-body
|
|
103
|
+
mutables; initialise in `__init__`. A project may mount more than one sidebar.
|
|
104
|
+
|
|
105
|
+
## Tests
|
|
106
|
+
|
|
107
|
+
- `make test` runs pytest with `--cov=django_admin_agent --cov-fail-under=100`
|
|
108
|
+
(line + branch). Restructure rather than `# pragma: no cover`.
|
|
109
|
+
- Layout mirrors the source tree under `tests/`.
|
|
110
|
+
- `tests/conftest_settings.py` is the Django settings module (admin + auth +
|
|
111
|
+
sessions installed). Fixture admin apps live under `tests/`.
|
|
112
|
+
- Async tests: `async def test_...` (pytest-asyncio auto mode). DB tests:
|
|
113
|
+
`@pytest.mark.django_db`.
|
|
114
|
+
|
|
115
|
+
## Lint and types
|
|
116
|
+
|
|
117
|
+
- `make lint` runs `ruff check .` + `ty check django_admin_agent`. CI fails on
|
|
118
|
+
either. `ruff format` is the layout source of truth.
|
|
119
|
+
- Pre-commit runs `make lint-fix`, `make format`, `make type-check`. Never
|
|
120
|
+
`--no-verify`.
|
|
121
|
+
|
|
122
|
+
## Boundaries
|
|
123
|
+
|
|
124
|
+
- Core imports `django.contrib.admin`; that is expected here (unlike
|
|
125
|
+
`django-ag-ui`, which must stay admin-free).
|
|
126
|
+
- `unfold` is never imported at module load — the shim is JS, runtime-detected
|
|
127
|
+
in the browser; any Python Unfold introspection is lazy + guarded.
|
|
128
|
+
- The `[mcp]` extra plugs into `djangorestframework-mcp-server`; import it
|
|
129
|
+
lazily.
|
|
130
|
+
|
|
131
|
+
## Compatibility floor
|
|
132
|
+
|
|
133
|
+
| Component | Floor | Tested |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| Python | 3.10 | 3.10–3.14 |
|
|
136
|
+
| Django | 4.2 LTS | 4.2, 5.0, 5.1, 5.2, 6.0 |
|
|
137
|
+
| django-ag-ui | 0.1 | from PyPI (`>=0.1`) |
|
|
138
|
+
| Django Unfold (supported, optional) | 0.40 | latest in matrix |
|
|
139
|
+
|
|
140
|
+
## Branching & releases
|
|
141
|
+
|
|
142
|
+
Branch-first for every feature/bump; never commit to `main` locally. Releases
|
|
143
|
+
are merge-to-main triggered via `.github/workflows/release.yml` →
|
|
144
|
+
`scripts/release-publish.sh` (version source: `django_admin_agent/version.py`).
|
|
145
|
+
OIDC trusted publishing to PyPI; `mkdocs gh-deploy` to gh-pages. Cut a release
|
|
146
|
+
with `make release-bump VERSION=X.Y.Z`, edit CHANGELOG, PR, merge.
|
|
@@ -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,116 @@
|
|
|
1
|
+
.PHONY: help init test lint lint-fix format format-check type-check deps-bump docs-serve docs-build vendor-bundle vendor-bundle-release 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 " vendor-bundle Copy the web-component bundle from the sibling checkout (dev)"
|
|
16
|
+
@echo " vendor-bundle-release Vendor the PINNED published web-component bundle (release)"
|
|
17
|
+
@echo " release-bump Bump version files + CHANGELOG. Usage: make release-bump VERSION=X.Y.Z"
|
|
18
|
+
@echo " release-publish prepare → uv publish → finalize (workstation release)"
|
|
19
|
+
@echo " release-publish-prepare Run by release.yml on push to main (no-op unless bumped)"
|
|
20
|
+
@echo " release-publish-finalize Tag vX.Y.Z + create GitHub Release after PyPI publish"
|
|
21
|
+
|
|
22
|
+
init:
|
|
23
|
+
uv sync --all-groups
|
|
24
|
+
uv run pre-commit install
|
|
25
|
+
|
|
26
|
+
test:
|
|
27
|
+
uv run pytest
|
|
28
|
+
|
|
29
|
+
# Browser end-to-end suite: Playwright drives a live admin through the sidebar.
|
|
30
|
+
# Separate settings + no coverage gate (it exercises JS + the server over HTTP).
|
|
31
|
+
test-e2e:
|
|
32
|
+
DJANGO_ALLOW_ASYNC_UNSAFE=1 uv run pytest tests/e2e --ds=tests.e2e.settings -o addopts="" -p no:cacheprovider
|
|
33
|
+
|
|
34
|
+
lint:
|
|
35
|
+
uv run ruff check .
|
|
36
|
+
uv run ty check django_admin_agent
|
|
37
|
+
|
|
38
|
+
lint-fix:
|
|
39
|
+
uv run ruff check --fix .
|
|
40
|
+
|
|
41
|
+
format:
|
|
42
|
+
uv run ruff format .
|
|
43
|
+
|
|
44
|
+
format-check:
|
|
45
|
+
uv run ruff format --check --diff .
|
|
46
|
+
|
|
47
|
+
type-check:
|
|
48
|
+
uv run ty check django_admin_agent
|
|
49
|
+
|
|
50
|
+
deps-bump:
|
|
51
|
+
uvx uv-upx upgrade run --profile with_pinned
|
|
52
|
+
|
|
53
|
+
docs-serve:
|
|
54
|
+
uv run --group docs mkdocs serve
|
|
55
|
+
|
|
56
|
+
docs-build:
|
|
57
|
+
uv run --group docs mkdocs build --strict
|
|
58
|
+
|
|
59
|
+
# The web-component bundle is a vendored build artefact. The PINNED version
|
|
60
|
+
# below is the single source of truth: a release re-vendors exactly this
|
|
61
|
+
# version (see release-publish-prepare), so a published wheel never depends on
|
|
62
|
+
# the live web-component source and ongoing component changes cannot
|
|
63
|
+
# retroactively affect a released django-admin-agent.
|
|
64
|
+
WEB_COMPONENT_PKG := @artooi/ag-ui-web-component
|
|
65
|
+
WEB_COMPONENT_VERSION := 0.1.1
|
|
66
|
+
BUNDLE_DEST := django_admin_agent/static/django_admin_agent/ag-ui-web-component.bundle.js
|
|
67
|
+
|
|
68
|
+
# Dev: copy the locally-built bundle from the sibling checkout (run
|
|
69
|
+
# `make build` in ../ag-ui-web-component first). Convenient, may drift — the
|
|
70
|
+
# release re-vendor is the authoritative refresh.
|
|
71
|
+
vendor-bundle:
|
|
72
|
+
cp ../ag-ui-web-component/dist/ag-ui-web-component.bundle.js $(BUNDLE_DEST)
|
|
73
|
+
@echo "Vendored ag-ui-web-component.bundle.js from the sibling checkout (dev)."
|
|
74
|
+
|
|
75
|
+
# Release: fetch the PINNED published version and vendor its built bundle. Run
|
|
76
|
+
# automatically by release-publish-prepare so every wheel ships exactly
|
|
77
|
+
# $(WEB_COMPONENT_PKG)@$(WEB_COMPONENT_VERSION). Fails loudly if the pinned
|
|
78
|
+
# version cannot be fetched — better than shipping a stale bundle.
|
|
79
|
+
vendor-bundle-release:
|
|
80
|
+
@set -e; tmp="$$(mktemp -d)"; \
|
|
81
|
+
( cd "$$tmp" && npm pack "$(WEB_COMPONENT_PKG)@$(WEB_COMPONENT_VERSION)" >/dev/null ); \
|
|
82
|
+
tar -xzf "$$tmp"/*.tgz -C "$$tmp"; \
|
|
83
|
+
cp "$$tmp/package/dist/ag-ui-web-component.bundle.js" "$(BUNDLE_DEST)"; \
|
|
84
|
+
rm -rf "$$tmp"; \
|
|
85
|
+
echo "Vendored $(WEB_COMPONENT_PKG)@$(WEB_COMPONENT_VERSION) bundle (release)."
|
|
86
|
+
|
|
87
|
+
release-bump:
|
|
88
|
+
@if [ -z "$(VERSION)" ]; then \
|
|
89
|
+
echo "Usage: make release-bump VERSION=X.Y.Z"; exit 1; \
|
|
90
|
+
fi
|
|
91
|
+
uvx bump-my-version bump --new-version "$(VERSION)" patch
|
|
92
|
+
@echo ""
|
|
93
|
+
@echo "Bumped to $(VERSION). Edit CHANGELOG.md to fill the new section,"
|
|
94
|
+
@echo "review with 'git diff', then run 'make release-publish'."
|
|
95
|
+
|
|
96
|
+
# Release pipeline. Version lives in django_admin_agent/version.py
|
|
97
|
+
# (pyproject pulls it in via [tool.hatch.version] dynamic).
|
|
98
|
+
RELEASE_PACKAGE_NAME := django-admin-agent
|
|
99
|
+
RELEASE_VERSION_FILES := django_admin_agent/version.py|^__version__[^=]*= *
|
|
100
|
+
|
|
101
|
+
release-publish: vendor-bundle-release
|
|
102
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
103
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
104
|
+
bash scripts/release-publish.sh all
|
|
105
|
+
|
|
106
|
+
# Re-vendor the pinned bundle BEFORE the script builds the wheel, so the
|
|
107
|
+
# published artefact always carries a fresh, version-pinned bundle.
|
|
108
|
+
release-publish-prepare: vendor-bundle-release
|
|
109
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
110
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
111
|
+
bash scripts/release-publish.sh prepare
|
|
112
|
+
|
|
113
|
+
release-publish-finalize:
|
|
114
|
+
@PACKAGE_NAME='$(RELEASE_PACKAGE_NAME)' \
|
|
115
|
+
VERSION_FILES="$$(printf '$(RELEASE_VERSION_FILES)')" \
|
|
116
|
+
bash scripts/release-publish.sh finalize
|