portacode 2.2.20.dev6__tar.gz → 2.2.20.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-2.2.20.dev6 → portacode-2.2.20.dev8}/PKG-INFO +1 -1
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/_version.py +2 -2
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/README.md +12 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +126 -15
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/browser_handlers.py +51 -3
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_browser_handlers.py +38 -6
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/.gitignore +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/LICENSE +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/MANIFEST.in +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/Makefile +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/build_android.sh +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/connect.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/connect.sh +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/cloudflared-domain-connect-containers-audit.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/creative-team-brief-portacode.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/device-health-alerting-plan.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/devops-messaging-ab-tests.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/guest-host-requests-plan.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/homepage-dashboard-positioning-fixes.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/template-engineering-roadmap.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/template-guide.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/simple_device/Dockerfile +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/simple_device/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/simple_device/docker-compose.yaml +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/Dockerfile +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/docker-compose.yaml +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/manage.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/__main__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/assets/skills/portacode-github/SKILL.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/assets/skills/portacode-github/agents/openai.yaml +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/assets/skills/portacode-github/scripts/create_repository.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/assets/skills/portacode-image/SKILL.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/assets/skills/portacode-image/agents/openai.yaml +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/browser_cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/codex_loopback_proxy.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/codex_prepare.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/codex_usage_limit.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/client.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/codex_app_server.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/guest_host_protocol.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/automation_v2_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/base.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/cloudflare_forwarding.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/cloudflare_tunnel.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/codex_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/diff_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/file_transfer_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/git_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/git_manager.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/manager.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/test_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/proxmox_infra.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/registry.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/resumable_transfer_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/runtime_user.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/session.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_cloudflare_forwarding.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_file_move_copy.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_git_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_proxmox_infra.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/test_runtime_user.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/update_handler.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/multiplex.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/terminal.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/test_guest_host_protocol.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/test_guest_host_terminal.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/test_webmin_proxy_config.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/webmin_proxy_config.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/data.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/exit_codes.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/github_credential.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/image_cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/keypair.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/__pycache__/__init__.cpython-38.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-38.pyc +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/elinks +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/gio-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/gnome-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/gvfs-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/kde-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/kfmclient +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/links +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/links2 +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/lynx +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/mate-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/netsurf +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/sensible-browser +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/w3m +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/x-www-browser +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/link_capture/bin/xdg-open +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/logging_categories.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/pairing.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/provisioning_cache.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/restart.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/service.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/singleton.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/test_runtime_paths.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/test_service.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/test_singleton.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/test_terminal_exposed_services.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_automation_v2_inputs.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_browser_cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_cli_service_logs.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_codex_app_server.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_codex_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_codex_loopback_proxy.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_codex_prepare.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_github_credential.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_image_cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_image_read_handler.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_resumable_transfer_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_system_handlers.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_terminal_periodic_system_info.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tests/test_terminal_session_shell.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/cloudflared_login.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/ensure_cloudflared.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/ensure_pyyaml.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/forwarding_state.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/get_domain.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/privileged.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/service_install.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/tunneling/state.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/updater.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/diff_apply.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/diff_renderer.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/ntp_clock.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/utils/runtime_paths.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/requires.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode.egg-info/top_level.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/pyproject.toml +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/run_tests.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/scripts/diagnose_codex_gateway.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/setup.cfg +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/setup.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test.sh +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_device_online.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_file_operations.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_git_status_ui.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_login_flow.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_play_store_screenshots.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_modules/test_terminal_start.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_request_id.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/test_session_terminal_shutdown.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/.env.example +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/README.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/cli.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/__init__.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/base_test.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/cli_manager.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/runner.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/core/test_discovery.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/testing_framework/requirements.txt +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/UI_UX/server_occasionally_stops_communicating_with_all_devices.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/agent_context_management.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/django_server_time_sync.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/portacode_service_silently_down.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/project_cpu_hotspots.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/websocket_client_silently_dead.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/todo/smartphone_terminal_input_frustrations.md +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/tools/generate_play_store_assets.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/tools/pairing_tester.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/tools/run_screenshot_suite.sh +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/tools/test_python_ntp_clock.py +0 -0
- {portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/validate.sh +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.2.20.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 2, 20, '
|
|
21
|
+
__version__ = version = '2.2.20.dev8'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 2, 20, 'dev8')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -43,6 +43,18 @@ The handler system consists of:
|
|
|
43
43
|
- Provides system resource information
|
|
44
44
|
- Returns CPU, memory, and disk usage data
|
|
45
45
|
|
|
46
|
+
### Browser Handlers (`browser_handlers.py`)
|
|
47
|
+
|
|
48
|
+
1. **`BrowserConfigHandler`** - `browser_config`
|
|
49
|
+
- Reads or atomically persists runtime-user browser viewport and recording dimensions
|
|
50
|
+
- Returns `browser_config_response`; the same effective values appear in `system_info.info.browser_config`
|
|
51
|
+
|
|
52
|
+
2. **`BrowserRunHandler`** - `browser_run`
|
|
53
|
+
- Runs up to 30 Playwright navigation, interaction, assertion, read, bounded DOM, and screenshot steps in a named persistent profile
|
|
54
|
+
- Applies saved dimensions unless the request supplies per-run overrides and returns `browser_run_response`
|
|
55
|
+
- Returns screenshots inline, a device-side `video_path` for recordings, and uses the standard chunk framing for large responses
|
|
56
|
+
- Adds polished cursor, pacing, focus, ripple, typing, and desktop zoom effects only while recording video; non-recorded automation stays fast
|
|
57
|
+
|
|
46
58
|
## Adding New Handlers
|
|
47
59
|
|
|
48
60
|
### 1. Asynchronous Handlers
|
{portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
@@ -119,6 +119,8 @@ This document describes the complete protocol for communicating with devices thr
|
|
|
119
119
|
- [`terminal_exec`](#terminal_exec)
|
|
120
120
|
- [System Actions](#system-actions)
|
|
121
121
|
- [`system_info`](#system_info)
|
|
122
|
+
- [`browser_config`](#browser_config)
|
|
123
|
+
- [`browser_run`](#browser_run)
|
|
122
124
|
- [`update_portacode_cli`](#update_portacode_cli)
|
|
123
125
|
- [`clock_sync_request`](#clock_sync_request)
|
|
124
126
|
- [File Actions](#file-actions)
|
|
@@ -171,6 +173,8 @@ This document describes the complete protocol for communicating with devices thr
|
|
|
171
173
|
- [`terminal_list`](#terminal_list-event)
|
|
172
174
|
- [System Events](#system-events)
|
|
173
175
|
- [`system_info`](#system_info-event)
|
|
176
|
+
- [`browser_config_response`](#browser_config_response)
|
|
177
|
+
- [`browser_run_response`](#browser_run_response)
|
|
174
178
|
- [`update_portacode_response`](#update_portacode_response)
|
|
175
179
|
- [`clock_sync_response`](#clock_sync_response)
|
|
176
180
|
- [File Events](#file-events)
|
|
@@ -429,6 +433,96 @@ This action does not require any payload fields.
|
|
|
429
433
|
|
|
430
434
|
* On success, the device will respond with a [`system_info`](#system_info-event) event.
|
|
431
435
|
|
|
436
|
+
### `browser_config`
|
|
437
|
+
|
|
438
|
+
Reads or atomically updates the runtime user's persistent browser dimensions.
|
|
439
|
+
Handled by [`BrowserConfigHandler`](./browser_handlers.py). Omitting `config`
|
|
440
|
+
performs a read without changing the saved values.
|
|
441
|
+
|
|
442
|
+
**Payload Fields:**
|
|
443
|
+
|
|
444
|
+
* `config` (object, optional): Sections to merge into the saved configuration.
|
|
445
|
+
* `viewport` (object, optional): `width` and/or `height` for browser pages.
|
|
446
|
+
* `video` (object, optional): `width` and/or `height` for recordings.
|
|
447
|
+
* Every supplied dimension must be an integer from 240 through 1920. Unknown
|
|
448
|
+
sections and fields are rejected.
|
|
449
|
+
|
|
450
|
+
**Responses:**
|
|
451
|
+
|
|
452
|
+
* On success, the device responds with
|
|
453
|
+
[`browser_config_response`](#browser_config_response).
|
|
454
|
+
* The resulting configuration is also reported at
|
|
455
|
+
`system_info.info.browser_config` and becomes the default for later runs.
|
|
456
|
+
|
|
457
|
+
Example read:
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{"cmd":"browser_config"}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Example update:
|
|
464
|
+
|
|
465
|
+
```json
|
|
466
|
+
{
|
|
467
|
+
"cmd": "browser_config",
|
|
468
|
+
"config": {
|
|
469
|
+
"viewport": {"width": 390, "height": 844},
|
|
470
|
+
"video": {"width": 390, "height": 844}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### `browser_run`
|
|
476
|
+
|
|
477
|
+
Runs a bounded Playwright batch in a persistent, runtime-user-scoped Chromium
|
|
478
|
+
profile. Handled by [`BrowserRunHandler`](./browser_handlers.py). A safe logical
|
|
479
|
+
`session_id` preserves cookies and local storage between calls.
|
|
480
|
+
|
|
481
|
+
**Payload Fields:**
|
|
482
|
+
|
|
483
|
+
* `session_id` (string, optional): Profile name containing only letters,
|
|
484
|
+
numbers, dot, dash, or underscore; defaults to `default`.
|
|
485
|
+
* `start_url` (string, optional): Initial page to load.
|
|
486
|
+
* `steps` (array, optional): At most 30 ordered operations: `goto`, `click`,
|
|
487
|
+
`fill`, `press`, `select`, `check`, `uncheck`, `wait`, `assert`, `read`,
|
|
488
|
+
`dom`, or `screenshot`. Locators support CSS (`css` or `selector`) and the
|
|
489
|
+
semantic `role`/`name`, `label`, `text`, and `testid` forms, with optional
|
|
490
|
+
`nth`. A `dom` step returns bounded `outerHTML` for `selector` (or `body`),
|
|
491
|
+
with `max_chars` clamped to 200–20000.
|
|
492
|
+
* `timeout_ms` (integer, optional): Per-operation timeout, clamped to
|
|
493
|
+
250–30000 milliseconds.
|
|
494
|
+
* `viewport` (object, optional): Per-run `width`/`height` override. Missing
|
|
495
|
+
fields retain the saved viewport values; dimensions must be 240–1920.
|
|
496
|
+
* `video` (object, optional): Per-run recording-size override with the same
|
|
497
|
+
merge and dimension rules. It does not enable recording by itself.
|
|
498
|
+
* `record_video` (boolean, optional): Record the run and return its device-side
|
|
499
|
+
path. Recorded runs have a 180-second action deadline.
|
|
500
|
+
* `final_screenshot` (boolean, optional): Capture the final viewport; defaults
|
|
501
|
+
to true.
|
|
502
|
+
* `screenshot_on_failure` (boolean, optional): Capture the viewport at a failed
|
|
503
|
+
step; defaults to true.
|
|
504
|
+
* `image_quality` (integer, optional): JPEG quality, clamped to 30–85.
|
|
505
|
+
|
|
506
|
+
Saved `browser_config` values are applied first and per-run `viewport`/`video`
|
|
507
|
+
fields override them. Screenshots use the active viewport; a `full_page`
|
|
508
|
+
screenshot may be taller than it. Recordings always keep the configured video
|
|
509
|
+
frame size and aspect ratio.
|
|
510
|
+
|
|
511
|
+
When video recording is enabled, the device automatically adds presentation
|
|
512
|
+
pacing: a virtual cursor, smooth movement and scrolling, target highlighting,
|
|
513
|
+
click ripples, human-paced non-password typing, pauses, and desktop zoom. This
|
|
514
|
+
layer is intentionally disabled for non-recorded automation, so screenshots,
|
|
515
|
+
DOM inspection, reads, assertions, and ordinary browser use remain fast.
|
|
516
|
+
|
|
517
|
+
**Responses:**
|
|
518
|
+
|
|
519
|
+
* The device responds with
|
|
520
|
+
[`browser_run_response`](#browser_run_response), including failures that
|
|
521
|
+
have a useful failure screenshot.
|
|
522
|
+
* Large responses use the standard chunk envelope with `browser_chunked=true`;
|
|
523
|
+
concatenate `chunk_content` in chunk order and parse the resulting JSON as
|
|
524
|
+
the ordinary response.
|
|
525
|
+
|
|
432
526
|
### `setup_proxmox_infra`
|
|
433
527
|
|
|
434
528
|
Configures a Proxmox node for Portacode infrastructure usage (API token validation, automatic storage/template detection, bridge/NAT setup, and connectivity verification). Handled by [`ConfigureProxmoxInfraHandler`](./proxmox_infra.py).
|
|
@@ -1419,6 +1513,9 @@ Provides system information in response to a `system_info` action. Handled by [`
|
|
|
1419
1513
|
* `available` (boolean): True when Playwright knows an executable path.
|
|
1420
1514
|
* `executable_path` (string|null): Absolute path to the browser binary when known.
|
|
1421
1515
|
* `error` (string|null): Any warning message captured while probing Playwright.
|
|
1516
|
+
* `browser_config` (object): Persistent defaults used by browser automation:
|
|
1517
|
+
* `viewport` (object): Browser page `width` and `height` in pixels.
|
|
1518
|
+
* `video` (object): Recorded video `width` and `height` in pixels.
|
|
1422
1519
|
* `proxmox` (object): Detection hints for Proxmox VE nodes:
|
|
1423
1520
|
* `is_proxmox_node` (boolean): True when Proxmox artifacts (e.g., `/etc/proxmox-release`) exist.
|
|
1424
1521
|
* `version` (string|null): Raw contents of `/etc/proxmox-release` when readable.
|
|
@@ -2141,23 +2238,37 @@ Confirms the result of a git commit operation.
|
|
|
2141
2238
|
* `error` (string, optional): Error message if the operation failed.
|
|
2142
2239
|
* `commit_hash` (string, optional): The SHA hash of the new commit if successful.
|
|
2143
2240
|
|
|
2144
|
-
###
|
|
2241
|
+
### <a name="browser_config_response"></a>`browser_config_response`
|
|
2145
2242
|
|
|
2146
|
-
|
|
2243
|
+
Returns the complete effective configuration after a `browser_config` read or
|
|
2244
|
+
update.
|
|
2245
|
+
|
|
2246
|
+
* `config` (object): `viewport` and `video` objects, each containing integer
|
|
2247
|
+
`width` and `height` values.
|
|
2248
|
+
|
|
2249
|
+
### <a name="browser_run_response"></a>`browser_run_response`
|
|
2147
2250
|
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
`
|
|
2152
|
-
`
|
|
2153
|
-
`
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2251
|
+
Returns the browser batch result.
|
|
2252
|
+
|
|
2253
|
+
* `success` (boolean): True only when every browser step passed.
|
|
2254
|
+
* `ok` (boolean): Playwright batch result; currently equivalent to `success`.
|
|
2255
|
+
* `session_id` (string): Profile used for the run.
|
|
2256
|
+
* `steps` (array): Compact outcomes with step index `i`, `op`, `ok`, and an
|
|
2257
|
+
optional returned `value` or bounded `error`.
|
|
2258
|
+
* `url` and `title` (string, success only): Final page identity.
|
|
2259
|
+
* `screenshots` (array): JPEG captures with `step`, base64 `data`,
|
|
2260
|
+
`mime_type`, and optional `failure=true`.
|
|
2261
|
+
* `video_path` (string, recorded runs): Absolute path on the device. Video
|
|
2262
|
+
bytes are not sent over the control channel.
|
|
2263
|
+
* `error` (string, failed runs): Bounded failure detail. A failed run remains
|
|
2264
|
+
a normal `browser_run_response` with `success=false`, preserving completed
|
|
2265
|
+
step results and any failure screenshot.
|
|
2266
|
+
|
|
2267
|
+
For chunked responses, each envelope also contains `browser_chunked=true`, a
|
|
2268
|
+
shared `transfer_id`, chunk metadata, and `chunk_content` holding a slice of the
|
|
2269
|
+
serialized complete response.
|
|
2270
|
+
|
|
2271
|
+
### Client Session Events
|
|
2161
2272
|
|
|
2162
2273
|
### <a name="request_client_sessions"></a>`request_client_sessions`
|
|
2163
2274
|
|
{portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/portacode/connection/handlers/browser_handlers.py
RENAMED
|
@@ -104,7 +104,23 @@ def update_browser_config(updates: dict, message: dict | None = None) -> dict:
|
|
|
104
104
|
_RUNNER = r"""
|
|
105
105
|
const fs = require('fs');
|
|
106
106
|
const readline = require('readline');
|
|
107
|
-
const
|
|
107
|
+
const playwrightCandidates = JSON.parse(process.env.PORTACODE_PLAYWRIGHT_CANDIDATES || '["playwright"]');
|
|
108
|
+
let chromium;
|
|
109
|
+
const playwrightErrors = [];
|
|
110
|
+
for (const candidate of playwrightCandidates) {
|
|
111
|
+
try {
|
|
112
|
+
const loaded = require(candidate);
|
|
113
|
+
const executable = loaded.chromium.executablePath();
|
|
114
|
+
if (process.env.PORTACODE_BROWSER_EXECUTABLE || (fs.existsSync(executable) && fs.statSync(executable).isFile())) {
|
|
115
|
+
chromium = loaded.chromium;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
playwrightErrors.push(`${candidate}: browser executable not found at ${executable}`);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
playwrightErrors.push(`${candidate}: ${error}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!chromium) throw new Error(`Unable to find a usable Playwright installation. ${playwrightErrors.join('; ')}`);
|
|
108
124
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
109
125
|
const locator = (p,s) => {
|
|
110
126
|
let l;
|
|
@@ -287,6 +303,19 @@ def _playwright_js_package() -> str | None:
|
|
|
287
303
|
return None
|
|
288
304
|
|
|
289
305
|
|
|
306
|
+
def _playwright_js_candidates() -> list[str]:
|
|
307
|
+
"""Return browser packages in managed, Node, then Python-driver order."""
|
|
308
|
+
candidates = []
|
|
309
|
+
managed = Path("/opt/portacode-playwright/node_modules/playwright")
|
|
310
|
+
if (managed / "package.json").is_file():
|
|
311
|
+
candidates.append(str(managed))
|
|
312
|
+
candidates.append("playwright")
|
|
313
|
+
bundled = _playwright_js_package()
|
|
314
|
+
if bundled and bundled not in candidates:
|
|
315
|
+
candidates.append(bundled)
|
|
316
|
+
return candidates
|
|
317
|
+
|
|
318
|
+
|
|
290
319
|
class _BrowserWorker:
|
|
291
320
|
def __init__(self, *, user: str, session_id: str, argv: list[str], env: dict[str, str]):
|
|
292
321
|
self.user = user
|
|
@@ -487,9 +516,28 @@ class BrowserRunHandler(AsyncHandler):
|
|
|
487
516
|
env = dict(os.environ)
|
|
488
517
|
env["NODE_PATH"] = await _node_path()
|
|
489
518
|
env.setdefault("PLAYWRIGHT_BROWSERS_PATH", "/opt/ms-playwright")
|
|
490
|
-
|
|
491
|
-
|
|
519
|
+
env["PORTACODE_PLAYWRIGHT_CANDIDATES"] = json.dumps(_playwright_js_candidates())
|
|
520
|
+
if executable:
|
|
521
|
+
env["PORTACODE_BROWSER_EXECUTABLE"] = executable
|
|
492
522
|
argv = wrap_argv_for_user([_node_executable(), "-e", _RUNNER], user, login=False)
|
|
523
|
+
existing_worker = _WORKERS.get((user, session_id))
|
|
524
|
+
session_is_live = bool(
|
|
525
|
+
existing_worker
|
|
526
|
+
and (existing_worker.process is None or existing_worker.process.returncode is None)
|
|
527
|
+
)
|
|
528
|
+
if not message.get("start_url") and not session_is_live:
|
|
529
|
+
return {
|
|
530
|
+
"event": "browser_run_response",
|
|
531
|
+
"success": False,
|
|
532
|
+
"ok": False,
|
|
533
|
+
"session_id": session_id,
|
|
534
|
+
"error": (
|
|
535
|
+
f"Browser session {session_id!r} is not active. "
|
|
536
|
+
"Provide start_url to create or restore it."
|
|
537
|
+
),
|
|
538
|
+
"screenshots": [],
|
|
539
|
+
"steps": [],
|
|
540
|
+
}
|
|
493
541
|
worker = await _worker_for(
|
|
494
542
|
user=user, session_id=session_id, argv=argv, env=env,
|
|
495
543
|
)
|
|
@@ -92,10 +92,24 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
92
92
|
"/opt/venv/playwright/driver/package",
|
|
93
93
|
)
|
|
94
94
|
|
|
95
|
+
def test_playwright_candidates_prefer_managed_then_node_then_python(self):
|
|
96
|
+
with (
|
|
97
|
+
patch.object(browser_handlers.Path, "is_file", side_effect=[True, True]),
|
|
98
|
+
patch.object(browser_handlers, "_playwright_js_package", return_value="/opt/venv/playwright/driver/package"),
|
|
99
|
+
):
|
|
100
|
+
self.assertEqual(
|
|
101
|
+
browser_handlers._playwright_js_candidates(),
|
|
102
|
+
[
|
|
103
|
+
"/opt/portacode-playwright/node_modules/playwright",
|
|
104
|
+
"playwright",
|
|
105
|
+
"/opt/venv/playwright/driver/package",
|
|
106
|
+
],
|
|
107
|
+
)
|
|
108
|
+
|
|
95
109
|
async def test_reuses_worker_for_same_runtime_user_and_session(self):
|
|
96
110
|
worker = AsyncMock()
|
|
97
111
|
worker.run.return_value = {"ok": True, "steps": [], "screenshots": []}
|
|
98
|
-
message = {"session_id": "safe", "steps": [], "final_screenshot": False}
|
|
112
|
+
message = {"session_id": "safe", "start_url": "about:blank", "steps": [], "final_screenshot": False}
|
|
99
113
|
with (
|
|
100
114
|
patch.object(browser_handlers, "get_default_runtime_user", return_value="tester"),
|
|
101
115
|
patch.object(browser_handlers, "get_runtime_user_home", return_value="/tmp"),
|
|
@@ -118,8 +132,8 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
118
132
|
self.assertEqual(keys, [("tester", "safe"), ("tester", "safe")])
|
|
119
133
|
self.assertEqual(worker.run.await_count, 2)
|
|
120
134
|
self.assertEqual(
|
|
121
|
-
get_worker.await_args_list[0].kwargs["env"]["
|
|
122
|
-
"/bundled/playwright/package",
|
|
135
|
+
json.loads(get_worker.await_args_list[0].kwargs["env"]["PORTACODE_PLAYWRIGHT_CANDIDATES"]),
|
|
136
|
+
["playwright", "/bundled/playwright/package"],
|
|
123
137
|
)
|
|
124
138
|
|
|
125
139
|
async def test_failed_browser_run_is_not_reported_as_successful(self):
|
|
@@ -138,11 +152,27 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
138
152
|
patch.object(browser_handlers, "_worker_for", AsyncMock(return_value=worker)),
|
|
139
153
|
):
|
|
140
154
|
result = await self.handler.execute(
|
|
141
|
-
{"session_id": "failure", "steps": [], "final_screenshot": False}
|
|
155
|
+
{"session_id": "failure", "start_url": "about:blank", "steps": [], "final_screenshot": False}
|
|
142
156
|
)
|
|
143
157
|
self.assertFalse(result["success"])
|
|
144
158
|
self.assertEqual(result["error"], "expected text")
|
|
145
159
|
|
|
160
|
+
async def test_missing_session_requires_start_url(self):
|
|
161
|
+
browser_handlers._WORKERS.clear()
|
|
162
|
+
with (
|
|
163
|
+
patch.object(browser_handlers, "get_default_runtime_user", return_value="tester"),
|
|
164
|
+
patch.object(browser_handlers, "get_runtime_user_home", return_value="/tmp"),
|
|
165
|
+
patch.object(browser_handlers, "mkdir_with_owner"),
|
|
166
|
+
patch.object(browser_handlers, "wrap_argv_for_user", return_value=["node"]),
|
|
167
|
+
patch.object(browser_handlers, "_node_path", AsyncMock(return_value="/modules")),
|
|
168
|
+
patch.object(browser_handlers, "_node_executable", return_value="/bundled/node"),
|
|
169
|
+
patch.object(browser_handlers, "_playwright_js_package", return_value=None),
|
|
170
|
+
):
|
|
171
|
+
result = await self.handler.execute({"session_id": "lost", "steps": []})
|
|
172
|
+
self.assertFalse(result["success"])
|
|
173
|
+
self.assertIn("Provide start_url", result["error"])
|
|
174
|
+
self.assertEqual(result["screenshots"], [])
|
|
175
|
+
|
|
146
176
|
async def test_worker_registry_separates_users_and_sessions(self):
|
|
147
177
|
browser_handlers._WORKERS.clear()
|
|
148
178
|
first = await browser_handlers._worker_for(
|
|
@@ -240,8 +270,8 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
240
270
|
patch.object(browser_handlers, "_playwright_js_package", return_value=None),
|
|
241
271
|
patch.object(browser_handlers, "_worker_for", AsyncMock(return_value=worker)),
|
|
242
272
|
):
|
|
243
|
-
await self.handler.execute({"session_id":"fast","steps":[],"record_video":False})
|
|
244
|
-
await self.handler.execute({"session_id":"demo","steps":[],"record_video":True})
|
|
273
|
+
await self.handler.execute({"session_id":"fast","start_url":"about:blank","steps":[],"record_video":False})
|
|
274
|
+
await self.handler.execute({"session_id":"demo","start_url":"about:blank","steps":[],"record_video":True})
|
|
245
275
|
self.assertFalse(worker.run.await_args_list[0].args[0]["demo"])
|
|
246
276
|
self.assertTrue(worker.run.await_args_list[1].args[0]["demo"])
|
|
247
277
|
|
|
@@ -267,6 +297,7 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
267
297
|
})
|
|
268
298
|
await self.handler.execute({
|
|
269
299
|
"session_id": "mobile", "steps": [], "record_video": True,
|
|
300
|
+
"start_url": "about:blank",
|
|
270
301
|
"final_screenshot": False,
|
|
271
302
|
})
|
|
272
303
|
saved = json.loads(
|
|
@@ -294,6 +325,7 @@ class BrowserRunHandlerTests(unittest.IsolatedAsyncioTestCase):
|
|
|
294
325
|
):
|
|
295
326
|
await self.handler.execute({
|
|
296
327
|
"session_id": "override", "steps": [], "record_video": True,
|
|
328
|
+
"start_url": "about:blank",
|
|
297
329
|
"viewport": {"width": 430}, "video": {"height": 932},
|
|
298
330
|
})
|
|
299
331
|
run_config = worker.run.await_args.args[0]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/cloudflared-domain-connect-containers-audit.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-2.2.20.dev6 → portacode-2.2.20.dev8}/docs/homepage-dashboard-positioning-fixes.md
RENAMED
|
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
|