portacode 1.4.11.dev6__tar.gz → 1.4.11.dev8__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.
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/PKG-INFO +1 -1
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/_version.py +2 -2
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +26 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/__init__.py +2 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/proxmox_infra.py +204 -69
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/terminal.py +2 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/.claude/agents/communication-manager.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/.claude/settings.local.json +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/.gitignore +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/.gitmodules +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/LICENSE +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/MANIFEST.in +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/Makefile +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/backup.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/connect.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/connect.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docker-compose.yaml +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docs/images/device-transfer-button.png +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docs/images/device-transfer-modal.png +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docs/images/pair-device-button.png +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docs/images/pairing-request.png +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/docs/images/student-workspace.png +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/simple_device/Dockerfile +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/simple_device/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/simple_device/docker-compose.yaml +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/Dockerfile +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/docker-compose.yaml +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/manage.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/__main__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/cli.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/client.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/base.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/diff_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/git_manager.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/manager.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/registry.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/session.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/update_handler.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/multiplex.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/data.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/keypair.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/elinks +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/gio-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/gnome-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/gvfs-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/kde-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/kfmclient +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/links +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/links2 +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/lynx +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/mate-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/netsurf +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/sensible-browser +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/w3m +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/x-www-browser +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/link_capture/bin/xdg-open +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/logging_categories.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/pairing.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/service.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/utils/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/utils/diff_apply.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/utils/diff_renderer.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/utils/ntp_clock.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/requires.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode.egg-info/top_level.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/pyproject.toml +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/restore.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/run_tests.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/setup.cfg +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/setup.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_device_online.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_file_operations.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_git_status_ui.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_login_flow.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_play_store_screenshots.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_modules/test_terminal_start.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/test_request_id.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/.env.example +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/README.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/cli.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/__init__.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/base_test.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/cli_manager.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/runner.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/core/test_discovery.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/testing_framework/requirements.txt +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/agent_context_management.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/django_server_time_sync.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/portacode_service_silently_down.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/project_cpu_hotspots.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/todo/smartphone_terminal_input_frustrations.md +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/tools/generate_play_store_assets.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/tools/pairing_tester.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/tools/run_screenshot_suite.sh +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/tools/test_python_ntp_clock.py +0 -0
- {portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/validate.sh +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.4.11.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4, 11, '
|
|
31
|
+
__version__ = version = '1.4.11.dev8'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 11, 'dev8')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
{portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
@@ -396,6 +396,32 @@ Sent intermittently while `create_proxmox_container` is executing so callers can
|
|
|
396
396
|
* `details` (object, optional): Contains `attempt` (if retries were needed) and `error_summary` when a step fails.
|
|
397
397
|
* `request_id` (string, optional): Mirrors the request ID from the incoming `create_proxmox_container` payload when available.
|
|
398
398
|
|
|
399
|
+
### `start_portacode_service`
|
|
400
|
+
|
|
401
|
+
Runs `sudo portacode service install` inside the container after the dashboard has created the corresponding Device record with the supplied public key.
|
|
402
|
+
|
|
403
|
+
**Payload Fields:**
|
|
404
|
+
|
|
405
|
+
* `ctid` (string, required): Container ID target.
|
|
406
|
+
* `step_index` (integer, required): Next step index to render inside `proxmox_container_progress`.
|
|
407
|
+
* `total_steps` (integer, required): The overall total number of steps (including lifecycle, bootstrap, and service installation).
|
|
408
|
+
|
|
409
|
+
**Responses:**
|
|
410
|
+
|
|
411
|
+
* Emits additional [`proxmox_container_progress`](#proxmox_container_progress-event) events to report the authentication and service-install steps.
|
|
412
|
+
* On success, emits a [`proxmox_service_started`](#proxmox_service_started-event).
|
|
413
|
+
* On failure, emits a generic [`error`](#error) event.
|
|
414
|
+
|
|
415
|
+
### `proxmox_service_started`
|
|
416
|
+
|
|
417
|
+
Indicates that `portacode service install` finished successfully inside a managed container.
|
|
418
|
+
|
|
419
|
+
**Event Fields:**
|
|
420
|
+
|
|
421
|
+
* `success` (boolean): True when the install succeeded.
|
|
422
|
+
* `message` (string): Success summary (e.g., `Portacode service install completed`).
|
|
423
|
+
* `ctid` (string): Container ID.
|
|
424
|
+
|
|
399
425
|
### `clock_sync_request`
|
|
400
426
|
|
|
401
427
|
Internal event that devices send to the gateway to request the authoritative server timestamp (used for adjusting `portacode.utils.ntp_clock`). The gateway responds immediately with [`clock_sync_response`](#clock_sync_response).
|
|
@@ -45,6 +45,7 @@ from .proxmox_infra import (
|
|
|
45
45
|
ConfigureProxmoxInfraHandler,
|
|
46
46
|
CreateProxmoxContainerHandler,
|
|
47
47
|
RevertProxmoxInfraHandler,
|
|
48
|
+
StartPortacodeServiceHandler,
|
|
48
49
|
)
|
|
49
50
|
|
|
50
51
|
__all__ = [
|
|
@@ -84,6 +85,7 @@ __all__ = [
|
|
|
84
85
|
"ProjectStateGitUnstageHandler",
|
|
85
86
|
"ProjectStateGitRevertHandler",
|
|
86
87
|
"ProjectStateGitCommitHandler",
|
|
88
|
+
"StartPortacodeServiceHandler",
|
|
87
89
|
"UpdatePortacodeHandler",
|
|
88
90
|
"RevertProxmoxInfraHandler",
|
|
89
91
|
]
|
{portacode-1.4.11.dev6 → portacode-1.4.11.dev8}/portacode/connection/handlers/proxmox_infra.py
RENAMED
|
@@ -6,6 +6,7 @@ import asyncio
|
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
8
|
import os
|
|
9
|
+
import secrets
|
|
9
10
|
import shutil
|
|
10
11
|
import stat
|
|
11
12
|
import subprocess
|
|
@@ -43,6 +44,53 @@ UNIT_DIR = Path("/etc/systemd/system")
|
|
|
43
44
|
ProgressCallback = Callable[[int, int, Dict[str, Any], str, Optional[Dict[str, Any]]], None]
|
|
44
45
|
|
|
45
46
|
|
|
47
|
+
def _emit_progress_event(
|
|
48
|
+
handler: SyncHandler,
|
|
49
|
+
*,
|
|
50
|
+
step_index: int,
|
|
51
|
+
total_steps: int,
|
|
52
|
+
step_name: str,
|
|
53
|
+
step_label: str,
|
|
54
|
+
status: str,
|
|
55
|
+
message: str,
|
|
56
|
+
phase: str,
|
|
57
|
+
request_id: Optional[str],
|
|
58
|
+
details: Optional[Dict[str, Any]] = None,
|
|
59
|
+
) -> None:
|
|
60
|
+
loop = handler.context.get("event_loop")
|
|
61
|
+
if not loop or loop.is_closed():
|
|
62
|
+
logger.debug(
|
|
63
|
+
"progress event skipped (no event loop) step=%s status=%s",
|
|
64
|
+
step_name,
|
|
65
|
+
status,
|
|
66
|
+
)
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
payload: Dict[str, Any] = {
|
|
70
|
+
"event": "proxmox_container_progress",
|
|
71
|
+
"step_name": step_name,
|
|
72
|
+
"step_label": step_label,
|
|
73
|
+
"status": status,
|
|
74
|
+
"phase": phase,
|
|
75
|
+
"step_index": step_index,
|
|
76
|
+
"total_steps": total_steps,
|
|
77
|
+
"message": message,
|
|
78
|
+
}
|
|
79
|
+
if request_id:
|
|
80
|
+
payload["request_id"] = request_id
|
|
81
|
+
if details:
|
|
82
|
+
payload["details"] = details
|
|
83
|
+
|
|
84
|
+
future = asyncio.run_coroutine_threadsafe(handler.send_response(payload), loop)
|
|
85
|
+
future.add_done_callback(
|
|
86
|
+
lambda fut: logger.warning(
|
|
87
|
+
"Failed to emit progress event for %s: %s", step_name, fut.exception()
|
|
88
|
+
)
|
|
89
|
+
if fut.exception()
|
|
90
|
+
else None
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
46
94
|
def _call_subprocess(cmd: List[str], **kwargs: Any) -> subprocess.CompletedProcess[str]:
|
|
47
95
|
env = os.environ.copy()
|
|
48
96
|
env.setdefault("DEBIAN_FRONTEND", "noninteractive")
|
|
@@ -251,7 +299,9 @@ def _format_rootfs(storage: str, disk_gib: int, storage_type: str) -> str:
|
|
|
251
299
|
def _get_provisioning_user_info(message: Dict[str, Any]) -> Tuple[str, str, str]:
|
|
252
300
|
user = (message.get("username") or "svcuser").strip() if message else "svcuser"
|
|
253
301
|
user = user or "svcuser"
|
|
254
|
-
password = message.get("password")
|
|
302
|
+
password = message.get("password")
|
|
303
|
+
if not password:
|
|
304
|
+
password = secrets.token_urlsafe(10)
|
|
255
305
|
ssh_key = (message.get("ssh_key") or "").strip() if message else ""
|
|
256
306
|
return user, password, ssh_key
|
|
257
307
|
|
|
@@ -380,6 +430,13 @@ def _write_container_record(vmid: int, payload: Dict[str, Any]) -> None:
|
|
|
380
430
|
path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
|
|
381
431
|
|
|
382
432
|
|
|
433
|
+
def _read_container_record(vmid: int) -> Dict[str, Any]:
|
|
434
|
+
path = CONTAINERS_DIR / f"ct-{vmid}.json"
|
|
435
|
+
if not path.exists():
|
|
436
|
+
raise FileNotFoundError(f"Container record {path} missing")
|
|
437
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
438
|
+
|
|
439
|
+
|
|
383
440
|
def _build_container_payload(message: Dict[str, Any], config: Dict[str, Any]) -> Dict[str, Any]:
|
|
384
441
|
templates = config.get("templates") or []
|
|
385
442
|
default_template = templates[0] if templates else ""
|
|
@@ -428,10 +485,10 @@ def _connect_proxmox(config: Dict[str, Any]) -> Any:
|
|
|
428
485
|
)
|
|
429
486
|
|
|
430
487
|
|
|
431
|
-
def _run_pct(vmid: int, cmd: str) -> Dict[str, Any]:
|
|
488
|
+
def _run_pct(vmid: int, cmd: str, input_text: Optional[str] = None) -> Dict[str, Any]:
|
|
432
489
|
full = ["pct", "exec", str(vmid), "--", "bash", "-lc", cmd]
|
|
433
490
|
start = time.time()
|
|
434
|
-
proc = subprocess.run(full, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
491
|
+
proc = subprocess.run(full, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input_text)
|
|
435
492
|
return {
|
|
436
493
|
"cmd": cmd,
|
|
437
494
|
"returncode": proc.returncode,
|
|
@@ -560,6 +617,8 @@ def _run_setup_steps(
|
|
|
560
617
|
continue
|
|
561
618
|
|
|
562
619
|
attempts = 0
|
|
620
|
+
retry_on = step.get("retry_on", [])
|
|
621
|
+
max_attempts = step.get("retries", 0) + 1
|
|
563
622
|
while True:
|
|
564
623
|
attempts += 1
|
|
565
624
|
res = _run_pct(vmid, step["cmd"])
|
|
@@ -572,14 +631,21 @@ def _run_setup_steps(
|
|
|
572
631
|
if progress_callback:
|
|
573
632
|
progress_callback(step_index, computed_total, step, "completed", res)
|
|
574
633
|
break
|
|
634
|
+
|
|
635
|
+
will_retry = False
|
|
636
|
+
if attempts < max_attempts and retry_on:
|
|
637
|
+
stderr_stdout = (res.get("stderr", "") + res.get("stdout", ""))
|
|
638
|
+
if any(tok in stderr_stdout for tok in retry_on):
|
|
639
|
+
will_retry = True
|
|
640
|
+
|
|
575
641
|
if progress_callback:
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
if any(tok in (res.get("stderr", "") + res.get("stdout", "")) for tok in retry_on):
|
|
642
|
+
status = "retrying" if will_retry else "failed"
|
|
643
|
+
progress_callback(step_index, computed_total, step, status, res)
|
|
644
|
+
|
|
645
|
+
if will_retry:
|
|
581
646
|
time.sleep(step.get("retry_delay_s", 3))
|
|
582
647
|
continue
|
|
648
|
+
|
|
583
649
|
return results, False
|
|
584
650
|
return results, True
|
|
585
651
|
|
|
@@ -746,58 +812,12 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
746
812
|
def command_name(self) -> str:
|
|
747
813
|
return "create_proxmox_container"
|
|
748
814
|
|
|
749
|
-
def _emit_progress_event(
|
|
750
|
-
self,
|
|
751
|
-
*,
|
|
752
|
-
step_index: int,
|
|
753
|
-
total_steps: int,
|
|
754
|
-
step_name: str,
|
|
755
|
-
step_label: str,
|
|
756
|
-
status: str,
|
|
757
|
-
message: str,
|
|
758
|
-
phase: str,
|
|
759
|
-
request_id: Optional[str],
|
|
760
|
-
details: Optional[Dict[str, Any]] = None,
|
|
761
|
-
) -> None:
|
|
762
|
-
loop = self.context.get("event_loop")
|
|
763
|
-
if not loop or loop.is_closed():
|
|
764
|
-
logger.debug(
|
|
765
|
-
"progress event skipped (no event loop) step=%s status=%s",
|
|
766
|
-
step_name,
|
|
767
|
-
status,
|
|
768
|
-
)
|
|
769
|
-
return
|
|
770
|
-
|
|
771
|
-
payload: Dict[str, Any] = {
|
|
772
|
-
"event": "proxmox_container_progress",
|
|
773
|
-
"step_name": step_name,
|
|
774
|
-
"step_label": step_label,
|
|
775
|
-
"status": status,
|
|
776
|
-
"phase": phase,
|
|
777
|
-
"step_index": step_index,
|
|
778
|
-
"total_steps": total_steps,
|
|
779
|
-
"message": message,
|
|
780
|
-
}
|
|
781
|
-
if request_id:
|
|
782
|
-
payload["request_id"] = request_id
|
|
783
|
-
if details:
|
|
784
|
-
payload["details"] = details
|
|
785
|
-
|
|
786
|
-
future = asyncio.run_coroutine_threadsafe(self.send_response(payload), loop)
|
|
787
|
-
future.add_done_callback(
|
|
788
|
-
lambda fut: logger.warning(
|
|
789
|
-
"Failed to emit progress event for %s: %s", step_name, fut.exception()
|
|
790
|
-
)
|
|
791
|
-
if fut.exception()
|
|
792
|
-
else None
|
|
793
|
-
)
|
|
794
|
-
|
|
795
815
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
796
816
|
logger.info("create_proxmox_container command received")
|
|
797
817
|
request_id = message.get("request_id")
|
|
798
818
|
bootstrap_user, bootstrap_password, bootstrap_ssh_key = _get_provisioning_user_info(message)
|
|
799
819
|
bootstrap_steps = _build_bootstrap_steps(bootstrap_user, bootstrap_password, bootstrap_ssh_key)
|
|
800
|
-
total_steps = 3 + len(bootstrap_steps)
|
|
820
|
+
total_steps = 3 + len(bootstrap_steps) + 2
|
|
801
821
|
current_step_index = 1
|
|
802
822
|
|
|
803
823
|
def _run_lifecycle_step(
|
|
@@ -809,7 +829,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
809
829
|
):
|
|
810
830
|
nonlocal current_step_index
|
|
811
831
|
step_index = current_step_index
|
|
812
|
-
|
|
832
|
+
_emit_progress_event(self,
|
|
813
833
|
step_index=step_index,
|
|
814
834
|
total_steps=total_steps,
|
|
815
835
|
step_name=step_name,
|
|
@@ -822,7 +842,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
822
842
|
try:
|
|
823
843
|
result = action()
|
|
824
844
|
except Exception as exc:
|
|
825
|
-
|
|
845
|
+
_emit_progress_event(
|
|
826
846
|
step_index=step_index,
|
|
827
847
|
total_steps=total_steps,
|
|
828
848
|
step_name=step_name,
|
|
@@ -834,7 +854,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
834
854
|
details={"error": str(exc)},
|
|
835
855
|
)
|
|
836
856
|
raise
|
|
837
|
-
|
|
857
|
+
_emit_progress_event(
|
|
838
858
|
step_index=step_index,
|
|
839
859
|
total_steps=total_steps,
|
|
840
860
|
step_name=step_name,
|
|
@@ -905,25 +925,33 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
905
925
|
_start_container_step,
|
|
906
926
|
)
|
|
907
927
|
|
|
908
|
-
def _bootstrap_progress_callback(
|
|
928
|
+
def _bootstrap_progress_callback(
|
|
929
|
+
step_index: int,
|
|
930
|
+
total: int,
|
|
931
|
+
step: Dict[str, Any],
|
|
932
|
+
status: str,
|
|
933
|
+
result: Optional[Dict[str, Any]],
|
|
934
|
+
):
|
|
909
935
|
label = step.get("display_name") or _friendly_step_label(step.get("name", "bootstrap"))
|
|
936
|
+
error_summary = (result or {}).get("error_summary") or (result or {}).get("error")
|
|
937
|
+
attempt = (result or {}).get("attempt")
|
|
910
938
|
if status == "in_progress":
|
|
911
939
|
message_text = f"{label} is running…"
|
|
912
940
|
elif status == "completed":
|
|
913
941
|
message_text = f"{label} completed."
|
|
942
|
+
elif status == "retrying":
|
|
943
|
+
attempt_desc = f" (attempt {attempt})" if attempt else ""
|
|
944
|
+
message_text = f"{label} failed{attempt_desc}; retrying…"
|
|
914
945
|
else:
|
|
915
|
-
summary = (result or {}).get("error_summary") or (result or {}).get("error")
|
|
916
946
|
message_text = f"{label} failed"
|
|
917
|
-
if
|
|
918
|
-
message_text += f": {
|
|
947
|
+
if error_summary:
|
|
948
|
+
message_text += f": {error_summary}"
|
|
919
949
|
details: Dict[str, Any] = {}
|
|
920
|
-
if
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
details["error_summary"] = summary_detail
|
|
926
|
-
self._emit_progress_event(
|
|
950
|
+
if attempt:
|
|
951
|
+
details["attempt"] = attempt
|
|
952
|
+
if error_summary:
|
|
953
|
+
details["error_summary"] = error_summary
|
|
954
|
+
_emit_progress_event(
|
|
927
955
|
step_index=step_index,
|
|
928
956
|
total_steps=total,
|
|
929
957
|
step_name=step.get("name", "bootstrap"),
|
|
@@ -945,6 +973,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
945
973
|
start_index=current_step_index,
|
|
946
974
|
total_steps=total_steps,
|
|
947
975
|
)
|
|
976
|
+
current_step_index += len(bootstrap_steps)
|
|
948
977
|
|
|
949
978
|
return {
|
|
950
979
|
"event": "proxmox_container_created",
|
|
@@ -965,6 +994,112 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
965
994
|
}
|
|
966
995
|
|
|
967
996
|
|
|
997
|
+
class StartPortacodeServiceHandler(SyncHandler):
|
|
998
|
+
"""Start the Portacode service inside a newly created container."""
|
|
999
|
+
|
|
1000
|
+
@property
|
|
1001
|
+
def command_name(self) -> str:
|
|
1002
|
+
return "start_portacode_service"
|
|
1003
|
+
|
|
1004
|
+
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1005
|
+
ctid = message.get("ctid")
|
|
1006
|
+
if not ctid:
|
|
1007
|
+
raise ValueError("ctid is required")
|
|
1008
|
+
try:
|
|
1009
|
+
vmid = int(ctid)
|
|
1010
|
+
except ValueError:
|
|
1011
|
+
raise ValueError("ctid must be an integer")
|
|
1012
|
+
|
|
1013
|
+
record = _read_container_record(vmid)
|
|
1014
|
+
user = record.get("username")
|
|
1015
|
+
password = record.get("password")
|
|
1016
|
+
if not user or not password:
|
|
1017
|
+
raise RuntimeError("Container credentials unavailable")
|
|
1018
|
+
|
|
1019
|
+
start_index = int(message.get("step_index", 1))
|
|
1020
|
+
total_steps = int(message.get("total_steps", start_index + 2))
|
|
1021
|
+
request_id = message.get("request_id")
|
|
1022
|
+
|
|
1023
|
+
auth_step_name = "setup_device_authentication"
|
|
1024
|
+
auth_label = "Setting up device authentication"
|
|
1025
|
+
_emit_progress_event(
|
|
1026
|
+
self,
|
|
1027
|
+
step_index=start_index,
|
|
1028
|
+
total_steps=total_steps,
|
|
1029
|
+
step_name=auth_step_name,
|
|
1030
|
+
step_label=auth_label,
|
|
1031
|
+
status="in_progress",
|
|
1032
|
+
message="Notifying the server of the new device…",
|
|
1033
|
+
phase="service",
|
|
1034
|
+
request_id=request_id,
|
|
1035
|
+
)
|
|
1036
|
+
_emit_progress_event(
|
|
1037
|
+
self,
|
|
1038
|
+
step_index=start_index,
|
|
1039
|
+
total_steps=total_steps,
|
|
1040
|
+
step_name=auth_step_name,
|
|
1041
|
+
step_label=auth_label,
|
|
1042
|
+
status="completed",
|
|
1043
|
+
message="Authentication metadata recorded.",
|
|
1044
|
+
phase="service",
|
|
1045
|
+
request_id=request_id,
|
|
1046
|
+
)
|
|
1047
|
+
|
|
1048
|
+
install_step = start_index + 1
|
|
1049
|
+
install_label = "Launching Portacode service"
|
|
1050
|
+
_emit_progress_event(
|
|
1051
|
+
self,
|
|
1052
|
+
step_index=install_step,
|
|
1053
|
+
total_steps=total_steps,
|
|
1054
|
+
step_name="launch_portacode_service",
|
|
1055
|
+
step_label=install_label,
|
|
1056
|
+
status="in_progress",
|
|
1057
|
+
message="Running sudo portacode service install…",
|
|
1058
|
+
phase="service",
|
|
1059
|
+
request_id=request_id,
|
|
1060
|
+
)
|
|
1061
|
+
|
|
1062
|
+
cmd = f"su - {user} -c 'sudo -S portacode service install'"
|
|
1063
|
+
res = _run_pct(vmid, cmd, input_text=password + "\n")
|
|
1064
|
+
|
|
1065
|
+
if res["returncode"] != 0:
|
|
1066
|
+
_emit_progress_event(
|
|
1067
|
+
self,
|
|
1068
|
+
step_index=install_step,
|
|
1069
|
+
total_steps=total_steps,
|
|
1070
|
+
step_name="launch_portacode_service",
|
|
1071
|
+
step_label=install_label,
|
|
1072
|
+
status="failed",
|
|
1073
|
+
message=f"{install_label} failed: {res.get('stderr') or res.get('stdout')}",
|
|
1074
|
+
phase="service",
|
|
1075
|
+
request_id=request_id,
|
|
1076
|
+
details={
|
|
1077
|
+
"stderr": res.get("stderr"),
|
|
1078
|
+
"stdout": res.get("stdout"),
|
|
1079
|
+
},
|
|
1080
|
+
)
|
|
1081
|
+
raise RuntimeError(res.get("stderr") or res.get("stdout") or "Service install failed")
|
|
1082
|
+
|
|
1083
|
+
_emit_progress_event(
|
|
1084
|
+
self,
|
|
1085
|
+
step_index=install_step,
|
|
1086
|
+
total_steps=total_steps,
|
|
1087
|
+
step_name="launch_portacode_service",
|
|
1088
|
+
step_label=install_label,
|
|
1089
|
+
status="completed",
|
|
1090
|
+
message="Portacode service install finished.",
|
|
1091
|
+
phase="service",
|
|
1092
|
+
request_id=request_id,
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
return {
|
|
1096
|
+
"event": "proxmox_service_started",
|
|
1097
|
+
"success": True,
|
|
1098
|
+
"message": "Portacode service install completed",
|
|
1099
|
+
"ctid": str(vmid),
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
|
|
968
1103
|
class ConfigureProxmoxInfraHandler(SyncHandler):
|
|
969
1104
|
@property
|
|
970
1105
|
def command_name(self) -> str:
|
|
@@ -55,6 +55,7 @@ from .handlers import (
|
|
|
55
55
|
ConfigureProxmoxInfraHandler,
|
|
56
56
|
CreateProxmoxContainerHandler,
|
|
57
57
|
RevertProxmoxInfraHandler,
|
|
58
|
+
StartPortacodeServiceHandler,
|
|
58
59
|
)
|
|
59
60
|
from .handlers.project_aware_file_handlers import (
|
|
60
61
|
ProjectAwareFileWriteHandler,
|
|
@@ -478,6 +479,7 @@ class TerminalManager:
|
|
|
478
479
|
# System management handlers
|
|
479
480
|
self._command_registry.register(ConfigureProxmoxInfraHandler)
|
|
480
481
|
self._command_registry.register(CreateProxmoxContainerHandler)
|
|
482
|
+
self._command_registry.register(StartPortacodeServiceHandler)
|
|
481
483
|
self._command_registry.register(RevertProxmoxInfraHandler)
|
|
482
484
|
self._command_registry.register(UpdatePortacodeHandler)
|
|
483
485
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|