portacode 1.4.15.dev1__tar.gz → 1.4.15.dev3__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.15.dev1 → portacode-1.4.15.dev3}/PKG-INFO +1 -1
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/_version.py +2 -2
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +15 -8
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/__init__.py +6 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/proxmox_infra.py +101 -29
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/.claude/agents/communication-manager.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/.claude/settings.local.json +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/.gitignore +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/.gitmodules +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/LICENSE +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/MANIFEST.in +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/Makefile +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/backup.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/connect.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/connect.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docker-compose.yaml +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docs/images/device-transfer-button.png +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docs/images/device-transfer-modal.png +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docs/images/pair-device-button.png +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docs/images/pairing-request.png +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/docs/images/student-workspace.png +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/simple_device/Dockerfile +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/simple_device/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/simple_device/docker-compose.yaml +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/Dockerfile +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/docker-compose.yaml +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/manage.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/__main__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/cli.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/client.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/base.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/diff_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/git_manager.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/manager.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/registry.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/session.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/test_proxmox_infra.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/update_handler.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/multiplex.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/terminal.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/data.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/keypair.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/elinks +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/gio-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/gnome-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/gvfs-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/kde-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/kfmclient +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/links +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/links2 +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/lynx +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/mate-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/netsurf +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/sensible-browser +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/w3m +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/x-www-browser +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/link_capture/bin/xdg-open +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/logging_categories.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/pairing.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/service.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/utils/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/utils/diff_apply.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/utils/diff_renderer.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/utils/ntp_clock.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/requires.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode.egg-info/top_level.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/pyproject.toml +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/restore.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/run_tests.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/setup.cfg +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/setup.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_device_online.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_file_operations.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_git_status_ui.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_login_flow.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_play_store_screenshots.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_modules/test_terminal_start.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/test_request_id.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/.env.example +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/README.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/cli.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/__init__.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/base_test.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/cli_manager.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/runner.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/core/test_discovery.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/testing_framework/requirements.txt +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/agent_context_management.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/django_server_time_sync.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/portacode_service_silently_down.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/project_cpu_hotspots.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/todo/smartphone_terminal_input_frustrations.md +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/tools/generate_play_store_assets.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/tools/pairing_tester.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/tools/run_screenshot_suite.sh +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/tools/test_python_ntp_clock.py +0 -0
- {portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/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.15.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4, 15, '
|
|
31
|
+
__version__ = version = '1.4.15.dev3'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 15, 'dev3')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
{portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
@@ -420,12 +420,12 @@ Creates or updates a Cloudflare tunnel in front of a managed container. The cont
|
|
|
420
420
|
|
|
421
421
|
* `ctid` (string, required): Identifier of the container.
|
|
422
422
|
* `container_port` (integer, required): Port inside the container to expose through Cloudflare.
|
|
423
|
-
* `cloudflare_url` (string,
|
|
423
|
+
* `cloudflare_url` (string, optional): Hostname (e.g., `app.example.com`) that the tunnel should serve. Leave blank to let Cloudflare create a quick tunnel (`*.cfargotunnel.com`) automatically.
|
|
424
424
|
* `protocol` (string, optional): One of `http`, `https`, or `tcp` (defaults to `http`).
|
|
425
425
|
|
|
426
426
|
**Responses:**
|
|
427
427
|
|
|
428
|
-
* Emits a [`cloudflare_tunnel_created`](#cloudflare_tunnel_created-event) event with the tunnel metadata.
|
|
428
|
+
* Emits a [`cloudflare_tunnel_created`](#cloudflare_tunnel_created-event) event with the tunnel metadata, the refreshed infra snapshot, and the optional `device_id` so dashboards can refresh the CT list.
|
|
429
429
|
* Emits an [`error`](#error) event on failure.
|
|
430
430
|
|
|
431
431
|
### `update_cloudflare_tunnel`
|
|
@@ -436,12 +436,12 @@ Refreshes the tunnel configuration for an existing tunnel (different port, URL,
|
|
|
436
436
|
|
|
437
437
|
* `ctid` (string, required): Identifier of the container.
|
|
438
438
|
* `container_port` (integer, optional): New container port.
|
|
439
|
-
* `cloudflare_url` (string, optional): New hostname.
|
|
439
|
+
* `cloudflare_url` (string, optional): New hostname (leave blank to keep the current hostname or let Cloudflare assign a quick tunnel).
|
|
440
440
|
* `protocol` (string, optional): New protocol (`http`, `https`, or `tcp`).
|
|
441
441
|
|
|
442
442
|
**Responses:**
|
|
443
443
|
|
|
444
|
-
* Emits a [`cloudflare_tunnel_updated`](#cloudflare_tunnel_updated-event) event with the refreshed tunnel metadata
|
|
444
|
+
* Emits a [`cloudflare_tunnel_updated`](#cloudflare_tunnel_updated-event) event with the refreshed tunnel metadata, the refreshed infra snapshot, and the optional `device_id`.
|
|
445
445
|
* Emits an [`error`](#error) event on failure.
|
|
446
446
|
|
|
447
447
|
### `remove_cloudflare_tunnel`
|
|
@@ -454,7 +454,7 @@ Stops and removes any tunnel metadata associated with a container.
|
|
|
454
454
|
|
|
455
455
|
**Responses:**
|
|
456
456
|
|
|
457
|
-
* Emits a [`cloudflare_tunnel_removed`](#cloudflare_tunnel_removed-event) event
|
|
457
|
+
* Emits a [`cloudflare_tunnel_removed`](#cloudflare_tunnel_removed-event) event with the refreshed infra snapshot and optional `device_id`.
|
|
458
458
|
* Emits an [`error`](#error) event on failure.
|
|
459
459
|
|
|
460
460
|
### `proxmox_container_created`
|
|
@@ -1272,8 +1272,10 @@ Submitted after a successful `create_cloudflare_tunnel` action.
|
|
|
1272
1272
|
* `event` (string): `cloudflare_tunnel_created`.
|
|
1273
1273
|
* `ctid` (string): Container ID associated with the tunnel.
|
|
1274
1274
|
* `success` (boolean): True when the tunnel is running.
|
|
1275
|
-
* `
|
|
1276
|
-
* `
|
|
1275
|
+
* `device_id` (string, optional): Mirrors the `device_id` supplied with the command, letting dashboards refresh that device immediately.
|
|
1276
|
+
* `message` (string): Summary text; when a hostname was assigned (including Quick Tunnel), the host is appended (e.g., `Created ... -> example.com`).
|
|
1277
|
+
* `tunnel` (object): Tunnel metadata matching the manager view. When using Cloudflare Quick Tunnel (no hostname supplied), `tunnel.url` holds the autogenerated `*.cfargotunnel.com` hostname.
|
|
1278
|
+
* `infra` (object): Snapshot produced by `get_infra_snapshot`, including the refreshed `managed_containers` list.
|
|
1277
1279
|
|
|
1278
1280
|
### `cloudflare_tunnel_updated`
|
|
1279
1281
|
|
|
@@ -1284,8 +1286,10 @@ Sent when `update_cloudflare_tunnel` completes.
|
|
|
1284
1286
|
* `event` (string): `cloudflare_tunnel_updated`.
|
|
1285
1287
|
* `ctid` (string): Container ID associated with the tunnel.
|
|
1286
1288
|
* `success` (boolean): True on success.
|
|
1287
|
-
* `
|
|
1289
|
+
* `device_id` (string, optional): Mirrors the command's `device_id`.
|
|
1290
|
+
* `message` (string): Summary text; includes the new hostname when one was assigned or changed.
|
|
1288
1291
|
* `tunnel` (object): Updated tunnel metadata.
|
|
1292
|
+
* `infra` (object): Snapshot produced by `get_infra_snapshot` so dashboards can refresh the managed container list.
|
|
1289
1293
|
|
|
1290
1294
|
### `cloudflare_tunnel_removed`
|
|
1291
1295
|
|
|
@@ -1296,7 +1300,10 @@ Sent after a tunnel has been removed from a container record.
|
|
|
1296
1300
|
* `event` (string): `cloudflare_tunnel_removed`.
|
|
1297
1301
|
* `ctid` (string): Container ID that no longer has a tunnel.
|
|
1298
1302
|
* `success` (boolean): True on success.
|
|
1303
|
+
* `device_id` (string, optional): Mirrors the command's `device_id`.
|
|
1299
1304
|
* `message` (string): Summary text.
|
|
1305
|
+
* `tunnel` (null): Always `null` to explicitly clear the stored tunnel metadata.
|
|
1306
|
+
* `infra` (object): The refreshed snapshot so dashboards see the updated container list.
|
|
1300
1307
|
|
|
1301
1308
|
### <a name="clock_sync_response"></a>`clock_sync_response`
|
|
1302
1309
|
|
|
@@ -43,12 +43,15 @@ from .project_state_handlers import (
|
|
|
43
43
|
)
|
|
44
44
|
from .proxmox_infra import (
|
|
45
45
|
ConfigureProxmoxInfraHandler,
|
|
46
|
+
CreateCloudflareTunnelHandler,
|
|
46
47
|
CreateProxmoxContainerHandler,
|
|
47
48
|
RevertProxmoxInfraHandler,
|
|
48
49
|
StartPortacodeServiceHandler,
|
|
49
50
|
StartProxmoxContainerHandler,
|
|
50
51
|
StopProxmoxContainerHandler,
|
|
52
|
+
RemoveCloudflareTunnelHandler,
|
|
51
53
|
RemoveProxmoxContainerHandler,
|
|
54
|
+
UpdateCloudflareTunnelHandler,
|
|
52
55
|
)
|
|
53
56
|
|
|
54
57
|
__all__ = [
|
|
@@ -62,6 +65,7 @@ __all__ = [
|
|
|
62
65
|
"TerminalListHandler",
|
|
63
66
|
"SystemInfoHandler",
|
|
64
67
|
"ConfigureProxmoxInfraHandler",
|
|
68
|
+
"CreateCloudflareTunnelHandler",
|
|
65
69
|
"CreateProxmoxContainerHandler",
|
|
66
70
|
# File operation handlers (optional - register as needed)
|
|
67
71
|
"FileReadHandler",
|
|
@@ -91,7 +95,9 @@ __all__ = [
|
|
|
91
95
|
"StartPortacodeServiceHandler",
|
|
92
96
|
"StartProxmoxContainerHandler",
|
|
93
97
|
"StopProxmoxContainerHandler",
|
|
98
|
+
"RemoveCloudflareTunnelHandler",
|
|
94
99
|
"RemoveProxmoxContainerHandler",
|
|
100
|
+
"UpdateCloudflareTunnelHandler",
|
|
95
101
|
"UpdatePortacodeHandler",
|
|
96
102
|
"RevertProxmoxInfraHandler",
|
|
97
103
|
]
|
{portacode-1.4.15.dev1 → portacode-1.4.15.dev3}/portacode/connection/handlers/proxmox_infra.py
RENAMED
|
@@ -8,6 +8,8 @@ import logging
|
|
|
8
8
|
import os
|
|
9
9
|
import secrets
|
|
10
10
|
import shlex
|
|
11
|
+
import re
|
|
12
|
+
import select
|
|
11
13
|
import shutil
|
|
12
14
|
import stat
|
|
13
15
|
import subprocess
|
|
@@ -637,19 +639,19 @@ def _launch_container_tunnel(proxmox: Any, node: str, vmid: int, tunnel: Dict[st
|
|
|
637
639
|
port = int(tunnel.get("container_port") or 0)
|
|
638
640
|
if not port:
|
|
639
641
|
raise ValueError("container_port is required to create a tunnel.")
|
|
640
|
-
|
|
641
|
-
if not hostname:
|
|
642
|
-
raise ValueError("cloudflare_url is required to expose the tunnel.")
|
|
642
|
+
requested_hostname = tunnel.get("url") or None
|
|
643
643
|
protocol = (tunnel.get("protocol") or "http").lower()
|
|
644
644
|
ip_address = _resolve_container_ip(proxmox, node, vmid)
|
|
645
645
|
target_url = f"{protocol}://{ip_address}:{port}"
|
|
646
646
|
name = tunnel.get("name") or _build_tunnel_name(vmid, port)
|
|
647
647
|
_stop_cloudflare_process(name)
|
|
648
|
-
proc = _start_cloudflare_process(name,
|
|
648
|
+
proc, assigned_url = _start_cloudflare_process(name, target_url, hostname=requested_hostname)
|
|
649
|
+
if not assigned_url:
|
|
650
|
+
raise RuntimeError("Failed to determine Cloudflare hostname for the tunnel.")
|
|
649
651
|
updated = {
|
|
650
652
|
"name": name,
|
|
651
653
|
"container_port": port,
|
|
652
|
-
"url":
|
|
654
|
+
"url": assigned_url,
|
|
653
655
|
"protocol": protocol,
|
|
654
656
|
"status": "running",
|
|
655
657
|
"pid": proc.pid,
|
|
@@ -671,13 +673,14 @@ def _stop_container_tunnel(vmid: int) -> None:
|
|
|
671
673
|
return
|
|
672
674
|
name = tunnel.get("name") or _build_tunnel_name(vmid, int(tunnel.get("container_port") or 0))
|
|
673
675
|
stopped = _stop_cloudflare_process(name)
|
|
674
|
-
if stopped
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
676
|
+
if not stopped and tunnel.get("status") == "stopped":
|
|
677
|
+
return
|
|
678
|
+
tunnel_update = {
|
|
679
|
+
**tunnel,
|
|
680
|
+
"status": "stopped",
|
|
681
|
+
"pid": None,
|
|
682
|
+
"last_updated": datetime.utcnow().isoformat() + "Z",
|
|
683
|
+
}
|
|
681
684
|
_update_container_tunnel(vmid, tunnel_update)
|
|
682
685
|
|
|
683
686
|
|
|
@@ -827,25 +830,67 @@ def _get_cloudflared_binary() -> str:
|
|
|
827
830
|
return binary
|
|
828
831
|
|
|
829
832
|
|
|
830
|
-
def
|
|
833
|
+
def _drain_stream(stream: Optional[Any]) -> None:
|
|
834
|
+
if stream is None:
|
|
835
|
+
return
|
|
836
|
+
try:
|
|
837
|
+
for _ in iter(stream.readline, ""):
|
|
838
|
+
continue
|
|
839
|
+
except Exception:
|
|
840
|
+
pass
|
|
841
|
+
finally:
|
|
842
|
+
try:
|
|
843
|
+
stream.close()
|
|
844
|
+
except Exception:
|
|
845
|
+
pass
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
def _await_quick_tunnel_url(proc: subprocess.Popen, timeout: float = 15.0) -> Optional[str]:
|
|
849
|
+
if not proc.stdout:
|
|
850
|
+
return None
|
|
851
|
+
cf_re = re.compile(r"https://[A-Za-z0-9\-.]+\.cfargotunnel\.com")
|
|
852
|
+
deadline = time.time() + timeout
|
|
853
|
+
while time.time() < deadline:
|
|
854
|
+
ready, _, _ = select.select([proc.stdout], [], [], 1)
|
|
855
|
+
if not ready:
|
|
856
|
+
continue
|
|
857
|
+
line = proc.stdout.readline()
|
|
858
|
+
if not line:
|
|
859
|
+
continue
|
|
860
|
+
match = cf_re.search(line)
|
|
861
|
+
if match:
|
|
862
|
+
return match.group(0)
|
|
863
|
+
return None
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
def _start_cloudflare_process(name: str, target_url: str, hostname: Optional[str] = None) -> Tuple[subprocess.Popen, Optional[str]]:
|
|
831
867
|
binary = _get_cloudflared_binary()
|
|
832
868
|
cmd = [
|
|
833
869
|
binary,
|
|
834
870
|
"tunnel",
|
|
835
|
-
"--hostname",
|
|
836
|
-
hostname,
|
|
837
871
|
"--url",
|
|
838
872
|
target_url,
|
|
839
873
|
"--no-autoupdate",
|
|
840
874
|
]
|
|
875
|
+
if hostname:
|
|
876
|
+
cmd.extend(["--hostname", hostname])
|
|
877
|
+
stdout_target = subprocess.DEVNULL
|
|
878
|
+
else:
|
|
879
|
+
stdout_target = subprocess.PIPE
|
|
841
880
|
proc = subprocess.Popen(
|
|
842
881
|
cmd,
|
|
843
|
-
stdout=
|
|
844
|
-
stderr=subprocess.
|
|
882
|
+
stdout=stdout_target,
|
|
883
|
+
stderr=subprocess.PIPE,
|
|
884
|
+
text=True,
|
|
845
885
|
)
|
|
846
886
|
with _CLOUDFLARE_TUNNELS_LOCK:
|
|
847
887
|
_CLOUDFLARE_TUNNEL_PROCESSES[name] = proc
|
|
848
|
-
|
|
888
|
+
assigned_url = hostname
|
|
889
|
+
if not hostname:
|
|
890
|
+
assigned_url = _await_quick_tunnel_url(proc)
|
|
891
|
+
threading.Thread(target=_drain_stream, args=(proc.stdout,), daemon=True).start()
|
|
892
|
+
threading.Thread(target=_drain_stream, args=(proc.stderr,), daemon=True).start()
|
|
893
|
+
return proc, assigned_url
|
|
849
894
|
|
|
850
895
|
|
|
851
896
|
def _stop_cloudflare_process(name: str) -> bool:
|
|
@@ -1884,8 +1929,7 @@ class CreateCloudflareTunnelHandler(SyncHandler):
|
|
|
1884
1929
|
if container_port <= 0:
|
|
1885
1930
|
raise ValueError("container_port is required and must be greater than zero.")
|
|
1886
1931
|
hostname = (message.get("cloudflare_url") or message.get("hostname") or "").strip()
|
|
1887
|
-
|
|
1888
|
-
raise ValueError("cloudflare_url is required.")
|
|
1932
|
+
hostname = hostname or None
|
|
1889
1933
|
protocol = (message.get("protocol") or "http").strip().lower()
|
|
1890
1934
|
if protocol not in {"http", "https", "tcp"}:
|
|
1891
1935
|
raise ValueError("protocol must be one of http, https, or tcp.")
|
|
@@ -1899,17 +1943,28 @@ class CreateCloudflareTunnelHandler(SyncHandler):
|
|
|
1899
1943
|
raise RuntimeError("Container must be running to create a tunnel.")
|
|
1900
1944
|
tunnel = {
|
|
1901
1945
|
"container_port": container_port,
|
|
1902
|
-
"url": hostname,
|
|
1903
1946
|
"protocol": protocol,
|
|
1904
1947
|
}
|
|
1948
|
+
if hostname:
|
|
1949
|
+
tunnel["url"] = hostname
|
|
1905
1950
|
created = _launch_container_tunnel(proxmox, node, vmid, tunnel)
|
|
1906
|
-
|
|
1951
|
+
infra = get_infra_snapshot()
|
|
1952
|
+
host_url = created.get("url")
|
|
1953
|
+
response_message = f"Created Cloudflare tunnel for container {vmid}."
|
|
1954
|
+
if host_url:
|
|
1955
|
+
response_message = f"{response_message[:-1]} -> {host_url}."
|
|
1956
|
+
response = {
|
|
1907
1957
|
"event": "cloudflare_tunnel_created",
|
|
1908
1958
|
"ctid": str(vmid),
|
|
1909
1959
|
"success": True,
|
|
1910
|
-
"message":
|
|
1960
|
+
"message": response_message,
|
|
1911
1961
|
"tunnel": created,
|
|
1962
|
+
"infra": infra,
|
|
1912
1963
|
}
|
|
1964
|
+
device_id = message.get("device_id")
|
|
1965
|
+
if device_id:
|
|
1966
|
+
response["device_id"] = device_id
|
|
1967
|
+
return response
|
|
1913
1968
|
|
|
1914
1969
|
|
|
1915
1970
|
class UpdateCloudflareTunnelHandler(SyncHandler):
|
|
@@ -1934,24 +1989,34 @@ class UpdateCloudflareTunnelHandler(SyncHandler):
|
|
|
1934
1989
|
if container_port <= 0:
|
|
1935
1990
|
raise ValueError("container_port must be greater than zero.")
|
|
1936
1991
|
hostname = (message.get("cloudflare_url") or tunnel.get("url") or "").strip()
|
|
1937
|
-
|
|
1938
|
-
raise ValueError("cloudflare_url is required.")
|
|
1992
|
+
hostname = hostname or None
|
|
1939
1993
|
protocol = (message.get("protocol") or tunnel.get("protocol") or "http").strip().lower()
|
|
1940
1994
|
if protocol not in {"http", "https", "tcp"}:
|
|
1941
1995
|
raise ValueError("protocol must be one of http, https, or tcp.")
|
|
1942
1996
|
updated_tunnel = {
|
|
1943
1997
|
"container_port": container_port,
|
|
1944
|
-
"url": hostname,
|
|
1945
1998
|
"protocol": protocol,
|
|
1946
1999
|
}
|
|
2000
|
+
if hostname:
|
|
2001
|
+
updated_tunnel["url"] = hostname
|
|
1947
2002
|
result = _launch_container_tunnel(proxmox, node, vmid, updated_tunnel)
|
|
1948
|
-
|
|
2003
|
+
infra = get_infra_snapshot()
|
|
2004
|
+
host_url = result.get("url")
|
|
2005
|
+
response_message = f"Updated Cloudflare tunnel for container {vmid}."
|
|
2006
|
+
if host_url:
|
|
2007
|
+
response_message = f"{response_message[:-1]} -> {host_url}."
|
|
2008
|
+
response = {
|
|
1949
2009
|
"event": "cloudflare_tunnel_updated",
|
|
1950
2010
|
"ctid": str(vmid),
|
|
1951
2011
|
"success": True,
|
|
1952
|
-
"message":
|
|
2012
|
+
"message": response_message,
|
|
1953
2013
|
"tunnel": result,
|
|
2014
|
+
"infra": infra,
|
|
1954
2015
|
}
|
|
2016
|
+
device_id = message.get("device_id")
|
|
2017
|
+
if device_id:
|
|
2018
|
+
response["device_id"] = device_id
|
|
2019
|
+
return response
|
|
1955
2020
|
|
|
1956
2021
|
|
|
1957
2022
|
class RemoveCloudflareTunnelHandler(SyncHandler):
|
|
@@ -1964,12 +2029,19 @@ class RemoveCloudflareTunnelHandler(SyncHandler):
|
|
|
1964
2029
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1965
2030
|
vmid = _parse_ctid(message)
|
|
1966
2031
|
_remove_container_tunnel_state(vmid)
|
|
1967
|
-
|
|
2032
|
+
infra = get_infra_snapshot()
|
|
2033
|
+
response = {
|
|
1968
2034
|
"event": "cloudflare_tunnel_removed",
|
|
1969
2035
|
"ctid": str(vmid),
|
|
1970
2036
|
"success": True,
|
|
1971
2037
|
"message": f"Removed Cloudflare tunnel state for container {vmid}.",
|
|
2038
|
+
"tunnel": None,
|
|
2039
|
+
"infra": infra,
|
|
1972
2040
|
}
|
|
2041
|
+
device_id = message.get("device_id")
|
|
2042
|
+
if device_id:
|
|
2043
|
+
response["device_id"] = device_id
|
|
2044
|
+
return response
|
|
1973
2045
|
|
|
1974
2046
|
|
|
1975
2047
|
class ConfigureProxmoxInfraHandler(SyncHandler):
|
|
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
|
|
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
|