portacode 1.5.14.dev1__tar.gz → 1.5.14.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.
Files changed (437) hide show
  1. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/PKG-INFO +1 -1
  2. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/_version.py +2 -2
  3. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/codex_app_server.py +15 -5
  4. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/codex_handlers.py +135 -19
  5. portacode-1.5.14.dev3/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
  6. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tests/test_codex_app_server.py +51 -6
  7. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tests/test_codex_handlers.py +21 -5
  8. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/PKG-INFO +1 -1
  9. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/SOURCES.txt +1 -0
  10. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/.claude/agents/communication-manager.md +0 -0
  11. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/.claude/settings.local.json +0 -0
  12. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/.gitignore +0 -0
  13. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/.gitmodules +0 -0
  14. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/LICENSE +0 -0
  15. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/MANIFEST.in +0 -0
  16. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/Makefile +0 -0
  17. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/README.md +0 -0
  18. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/backup.sh +0 -0
  19. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/build_android.sh +0 -0
  20. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/connect.py +0 -0
  21. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/connect.sh +0 -0
  22. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docker-compose.yaml +0 -0
  23. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/cloudflared-domain-connect-containers-audit.md +0 -0
  24. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/creative-team-brief-portacode.md +0 -0
  25. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/device-health-alerting-plan.md +0 -0
  26. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/devops-messaging-ab-tests.md +0 -0
  27. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/homepage-dashboard-positioning-fixes.md +0 -0
  28. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/images/device-transfer-button.png +0 -0
  29. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/images/device-transfer-modal.png +0 -0
  30. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/images/pair-device-button.png +0 -0
  31. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/images/pairing-request.png +0 -0
  32. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/images/student-workspace.png +0 -0
  33. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/docs/template-guide.html +0 -0
  34. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/README.md +0 -0
  35. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/simple_device/Dockerfile +0 -0
  36. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/simple_device/README.md +0 -0
  37. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
  38. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
  39. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/simple_device/docker-compose.yaml +0 -0
  40. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/Dockerfile +0 -0
  41. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/README.md +0 -0
  42. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
  43. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
  44. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
  45. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
  46. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
  47. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
  48. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
  49. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
  50. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
  51. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
  52. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
  53. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
  54. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
  55. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
  56. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
  57. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
  58. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
  59. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
  60. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
  61. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
  62. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
  63. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
  64. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
  65. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
  66. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
  67. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
  68. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
  69. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
  70. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
  71. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
  72. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
  73. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
  74. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
  75. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
  76. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
  77. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
  78. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
  79. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
  80. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
  81. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
  82. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
  83. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
  84. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
  85. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
  86. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
  87. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
  88. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
  89. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
  90. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
  91. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
  92. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
  93. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
  94. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
  95. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
  96. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
  97. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
  98. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
  99. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
  100. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
  101. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
  102. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
  103. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
  104. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
  105. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
  106. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
  107. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
  108. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
  109. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
  110. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
  111. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
  112. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
  113. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
  114. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
  115. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
  116. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
  117. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
  118. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
  119. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
  120. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
  121. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
  122. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
  123. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
  124. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
  125. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
  126. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
  127. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
  128. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
  129. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
  130. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
  131. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
  132. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
  133. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
  134. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
  135. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
  136. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
  137. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
  138. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
  139. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
  140. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
  141. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
  142. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
  143. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
  144. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
  145. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
  146. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
  147. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
  148. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
  149. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
  150. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
  151. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
  152. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
  153. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
  154. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
  155. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
  156. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
  157. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
  158. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
  159. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
  160. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
  161. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
  162. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
  163. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
  164. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
  165. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
  166. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
  167. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
  168. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
  169. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
  170. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
  171. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
  172. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
  173. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
  174. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
  175. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
  176. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
  177. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
  178. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
  179. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
  180. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
  181. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
  182. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
  183. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
  184. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
  185. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
  186. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
  187. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
  188. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
  189. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
  190. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
  191. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
  192. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
  193. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
  194. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
  195. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
  196. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
  197. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
  198. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
  199. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
  200. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
  201. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
  202. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
  203. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
  204. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
  205. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
  206. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
  207. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
  208. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
  209. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
  210. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
  211. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
  212. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
  213. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
  214. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
  215. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
  216. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
  217. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
  218. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
  219. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
  220. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
  221. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
  222. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
  223. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
  224. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
  225. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
  226. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
  227. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
  228. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
  229. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
  230. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
  231. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
  232. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
  233. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
  234. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
  235. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
  236. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
  237. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
  238. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
  239. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
  240. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
  241. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
  242. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
  243. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
  244. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
  245. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
  246. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
  247. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
  248. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
  249. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
  250. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
  251. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
  252. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
  253. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
  254. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
  255. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
  256. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
  257. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/docker-compose.yaml +0 -0
  258. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/README.md +0 -0
  259. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
  260. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
  261. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
  262. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
  263. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
  264. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/manage.py +0 -0
  265. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
  266. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
  267. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
  268. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
  269. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
  270. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
  271. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
  272. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
  273. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
  274. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
  275. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
  276. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
  277. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/README.md +0 -0
  278. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/__init__.py +0 -0
  279. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/__main__.py +0 -0
  280. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/cli.py +0 -0
  281. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/codex_loopback_proxy.py +0 -0
  282. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/codex_prepare.py +0 -0
  283. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/README.md +0 -0
  284. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/__init__.py +0 -0
  285. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/client.py +0 -0
  286. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/README.md +0 -0
  287. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  288. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/__init__.py +0 -0
  289. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/automation_v2_handlers.py +0 -0
  290. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/base.py +0 -0
  291. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/chunked_content.py +0 -0
  292. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/cloudflare_forwarding.py +0 -0
  293. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/cloudflare_tunnel.py +0 -0
  294. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/diff_handlers.py +0 -0
  295. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/file_handlers.py +0 -0
  296. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/file_transfer_handlers.py +0 -0
  297. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
  298. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/README.md +0 -0
  299. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/__init__.py +0 -0
  300. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
  301. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/git_manager.py +0 -0
  302. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/handlers.py +0 -0
  303. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/manager.py +0 -0
  304. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/models.py +0 -0
  305. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/test_handlers.py +0 -0
  306. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state/utils.py +0 -0
  307. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/project_state_handlers.py +0 -0
  308. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/proxmox_infra.py +0 -0
  309. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/registry.py +0 -0
  310. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/runtime_user.py +0 -0
  311. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/session.py +0 -0
  312. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/system_handlers.py +0 -0
  313. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/tab_factory.py +0 -0
  314. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/terminal_handlers.py +0 -0
  315. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/test_cloudflare_forwarding.py +0 -0
  316. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/test_proxmox_infra.py +0 -0
  317. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/test_runtime_user.py +0 -0
  318. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/handlers/update_handler.py +0 -0
  319. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/multiplex.py +0 -0
  320. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/terminal.py +0 -0
  321. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/test_webmin_proxy_config.py +0 -0
  322. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/connection/webmin_proxy_config.py +0 -0
  323. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/data.py +0 -0
  324. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/exit_codes.py +0 -0
  325. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/keypair.py +0 -0
  326. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/__init__.py +0 -0
  327. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/elinks +0 -0
  328. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/gio-open +0 -0
  329. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/gnome-open +0 -0
  330. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/gvfs-open +0 -0
  331. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/kde-open +0 -0
  332. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/kfmclient +0 -0
  333. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
  334. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
  335. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/links +0 -0
  336. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/links2 +0 -0
  337. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/lynx +0 -0
  338. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/mate-open +0 -0
  339. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/netsurf +0 -0
  340. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/sensible-browser +0 -0
  341. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/w3m +0 -0
  342. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/x-www-browser +0 -0
  343. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/link_capture/bin/xdg-open +0 -0
  344. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/logging_categories.py +0 -0
  345. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/pairing.py +0 -0
  346. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/restart.py +0 -0
  347. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/service.py +0 -0
  348. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/static/js/test-ntp-clock.html +0 -0
  349. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/static/js/utils/ntp-clock.js +0 -0
  350. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/test_runtime_paths.py +0 -0
  351. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/test_service.py +0 -0
  352. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/test_terminal_exposed_services.py +0 -0
  353. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/__init__.py +0 -0
  354. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/cloudflared_login.py +0 -0
  355. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/ensure_cloudflared.py +0 -0
  356. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/ensure_pyyaml.py +0 -0
  357. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/forwarding_state.py +0 -0
  358. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/get_domain.py +0 -0
  359. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/privileged.py +0 -0
  360. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/service_install.py +0 -0
  361. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/tunneling/state.py +0 -0
  362. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/updater.py +0 -0
  363. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
  364. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/__init__.py +0 -0
  365. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/diff_apply.py +0 -0
  366. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/diff_renderer.py +0 -0
  367. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/ntp_clock.py +0 -0
  368. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode/utils/runtime_paths.py +0 -0
  369. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/dependency_links.txt +0 -0
  370. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/entry_points.txt +0 -0
  371. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/requires.txt +0 -0
  372. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode.egg-info/top_level.txt +0 -0
  373. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/.gitignore +0 -0
  374. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/README.md +0 -0
  375. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/persistent_workspace/Dockerfile +0 -0
  376. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/persistent_workspace/README.md +0 -0
  377. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/persistent_workspace/entrypoint.sh +0 -0
  378. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/persistent_workspace/manage_classroom.py +0 -0
  379. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/Dockerfile +0 -0
  380. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/README.md +0 -0
  381. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/docker-compose.yaml +0 -0
  382. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/docs/device_transfere.png +0 -0
  383. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/docs/pairing_approval.png +0 -0
  384. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/portacode_for_school/temporary_workspace/entrypoint.sh +0 -0
  385. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/pyproject.toml +0 -0
  386. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/restore.sh +0 -0
  387. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/run_tests.py +0 -0
  388. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/scripts/diagnose_codex_gateway.py +0 -0
  389. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/setup.cfg +0 -0
  390. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/setup.py +0 -0
  391. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test.sh +0 -0
  392. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/README.md +0 -0
  393. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/__init__.py +0 -0
  394. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_device_online.py +0 -0
  395. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_file_operations.py +0 -0
  396. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_git_status_ui.py +0 -0
  397. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_login_flow.py +0 -0
  398. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_navigate_testing_folder.py +0 -0
  399. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_play_store_screenshots.py +0 -0
  400. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_terminal_buffer_performance.py +0 -0
  401. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_terminal_interaction.py +0 -0
  402. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_terminal_loading_race_condition.py +0 -0
  403. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_modules/test_terminal_start.py +0 -0
  404. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_request_id.py +0 -0
  405. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/test_session_terminal_shutdown.py +0 -0
  406. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/.env.example +0 -0
  407. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/README.md +0 -0
  408. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/__init__.py +0 -0
  409. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/cli.py +0 -0
  410. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/__init__.py +0 -0
  411. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/base_test.py +0 -0
  412. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/cli_manager.py +0 -0
  413. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/hierarchical_runner.py +0 -0
  414. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/playwright_manager.py +0 -0
  415. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/runner.py +0 -0
  416. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/shared_cli_manager.py +0 -0
  417. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/core/test_discovery.py +0 -0
  418. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/testing_framework/requirements.txt +0 -0
  419. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
  420. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/UI_UX/server_occasionally_stops_communicating_with_all_devices.md +0 -0
  421. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/agent_context_management.md +0 -0
  422. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/django_server_time_sync.md +0 -0
  423. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/device_performance_degradation.md +0 -0
  424. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
  425. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/indefinite_resource_loading.md +0 -0
  426. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/portacode_service_silently_down.md +0 -0
  427. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/premature_terminal_exit.md +0 -0
  428. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/project_cpu_hotspots.md +0 -0
  429. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/terminals_exit_upon_starting.md +0 -0
  430. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/websocket_client_silently_dead.md +0 -0
  431. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
  432. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/todo/smartphone_terminal_input_frustrations.md +0 -0
  433. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/tools/generate_play_store_assets.py +0 -0
  434. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/tools/pairing_tester.py +0 -0
  435. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/tools/run_screenshot_suite.sh +0 -0
  436. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/tools/test_python_ntp_clock.py +0 -0
  437. {portacode-1.5.14.dev1 → portacode-1.5.14.dev3}/validate.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.5.14.dev1
3
+ Version: 1.5.14.dev3
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -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 = '1.5.14.dev1'
22
- __version_tuple__ = version_tuple = (1, 5, 14, 'dev1')
21
+ __version__ = version = '1.5.14.dev3'
22
+ __version_tuple__ = version_tuple = (1, 5, 14, 'dev3')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -126,8 +126,12 @@ class CodexAppServer:
126
126
  # JSON-RPC I/O
127
127
  # ------------------------------------------------------------------
128
128
  async def _initialize(self) -> None:
129
- """Send the initialize handshake and wait for its response."""
130
- response = await self._request(
129
+ """Send the initialize handshake and wait for its response.
130
+
131
+ Uses `_request_on_running_proc` so we do not re-enter `start()` while
132
+ `start()` already holds `_lock` (asyncio.Lock is not reentrant).
133
+ """
134
+ response = await self._request_on_running_proc(
131
135
  "initialize",
132
136
  {
133
137
  "clientInfo": self.client_info,
@@ -143,12 +147,18 @@ class CodexAppServer:
143
147
  ) -> Dict[str, Any]:
144
148
  """Send a JSON-RPC request and return the response object."""
145
149
  await self.start()
150
+ return await self._request_on_running_proc(method, params, timeout=timeout)
151
+
152
+ async def _request_on_running_proc(
153
+ self, method: str, params: Dict[str, Any], timeout: float = 60.0
154
+ ) -> Dict[str, Any]:
155
+ """Write a JSON-RPC request to an already-spawned app-server process."""
146
156
  assert self._proc is not None and self._proc.stdin is not None
147
157
 
148
158
  request_id = self._next_id
149
159
  self._next_id += 1
150
160
  message = {"jsonrpc": "2.0", "id": request_id, "method": method, "params": params}
151
- payload = json.dumps(message, ensure_ascii=False)
161
+ payload = json.dumps(message, ensure_ascii=False, separators=(",", ":"))
152
162
 
153
163
  loop = asyncio.get_running_loop()
154
164
  future: asyncio.Future = loop.create_future()
@@ -172,7 +182,7 @@ class CodexAppServer:
172
182
  await self.start()
173
183
  assert self._proc is not None and self._proc.stdin is not None
174
184
  message = {"jsonrpc": "2.0", "method": method, "params": params}
175
- payload = json.dumps(message, ensure_ascii=False)
185
+ payload = json.dumps(message, ensure_ascii=False, separators=(",", ":"))
176
186
  self._proc.stdin.write((payload + "\n").encode("utf-8"))
177
187
  await self._proc.stdin.drain()
178
188
 
@@ -180,7 +190,7 @@ class CodexAppServer:
180
190
  """Reply to a server->client request with a JSON-RPC error."""
181
191
  assert self._proc is not None and self._proc.stdin is not None
182
192
  response = {"jsonrpc": "2.0", "id": request_id, "error": {"code": code, "message": message}}
183
- payload = json.dumps(response, ensure_ascii=False)
193
+ payload = json.dumps(response, ensure_ascii=False, separators=(",", ":"))
184
194
  self._proc.stdin.write((payload + "\n").encode("utf-8"))
185
195
  await self._proc.stdin.drain()
186
196
 
@@ -86,20 +86,122 @@ def _project_id(message: Dict[str, Any]) -> Optional[str]:
86
86
  return message.get("project_id")
87
87
 
88
88
 
89
- class CodexStatusHandler(AsyncHandler):
89
+ def _thread_from_result(result: Dict[str, Any]) -> Dict[str, Any]:
90
+ """Normalize thread/start|resume|read results to a thread object.
91
+
92
+ Current app-server returns `{ "thread": { "id": ... } }`. Older fakes /
93
+ builds may return the thread fields at the top level.
94
+ """
95
+ if not isinstance(result, dict):
96
+ return {}
97
+ thread = result.get("thread")
98
+ if isinstance(thread, dict):
99
+ return thread
100
+ return result
101
+
102
+
103
+ def _thread_id_from_result(result: Dict[str, Any]) -> Optional[str]:
104
+ thread = _thread_from_result(result)
105
+ return thread.get("id") or result.get("id") or result.get("threadId")
106
+
107
+
108
+ def _threads_from_list_result(result: Dict[str, Any]) -> tuple[list, Optional[str]]:
109
+ """Normalize thread/list results.
110
+
111
+ Current app-server returns `{ "data": [...], "nextCursor": ... }`.
112
+ """
113
+ if not isinstance(result, dict):
114
+ return [], None
115
+ threads = result.get("data")
116
+ if threads is None:
117
+ threads = result.get("threads")
118
+ if not isinstance(threads, list):
119
+ threads = []
120
+ return threads, result.get("nextCursor")
121
+
122
+
123
+ def _items_from_read_result(result: Dict[str, Any]) -> list:
124
+ """Extract conversation items from thread/read (or legacy shapes)."""
125
+ if not isinstance(result, dict):
126
+ return []
127
+ if isinstance(result.get("items"), list):
128
+ return result["items"]
129
+ if isinstance(result.get("messages"), list):
130
+ return result["messages"]
131
+
132
+ thread = _thread_from_result(result)
133
+ turns = thread.get("turns") or result.get("turns") or []
134
+ items: list = []
135
+ if isinstance(turns, list):
136
+ for turn in turns:
137
+ if not isinstance(turn, dict):
138
+ continue
139
+ turn_items = turn.get("items")
140
+ if isinstance(turn_items, list):
141
+ items.extend(turn_items)
142
+ return items
143
+
144
+
145
+ def _turn_from_result(result: Dict[str, Any]) -> Dict[str, Any]:
146
+ if not isinstance(result, dict):
147
+ return {}
148
+ turn = result.get("turn")
149
+ if isinstance(turn, dict):
150
+ return turn
151
+ return result
152
+
153
+
154
+ class CodexAsyncHandler(AsyncHandler):
155
+ """AsyncHandler that replies to `source_client_session` per WEBSOCKET_PROTOCOL.md."""
156
+
157
+ async def handle(self, message: Dict[str, Any], reply_channel: Optional[str] = None) -> None:
158
+ try:
159
+ response = await self.execute(message)
160
+ if response is None:
161
+ return
162
+ if "request_id" in message and "request_id" not in response:
163
+ response["request_id"] = message["request_id"]
164
+
165
+ source_client_session = message.get("source_client_session")
166
+ project_id = response.get("project_id") or _project_id(message)
167
+ if project_id and "project_id" not in response:
168
+ response["project_id"] = project_id
169
+
170
+ if source_client_session:
171
+ payload = dict(response)
172
+ payload["client_sessions"] = [source_client_session]
173
+ await self.control_channel.send(payload)
174
+ return
175
+
176
+ await self.send_response(response, reply_channel, project_id)
177
+ except Exception as exc:
178
+ LOGGER.exception("handler: Error in codex handler %s: %s", self.command_name, exc)
179
+ await self.send_error(
180
+ str(exc),
181
+ reply_channel,
182
+ _project_id(message),
183
+ request_id=message.get("request_id"),
184
+ )
185
+
186
+
187
+ class CodexStatusHandler(CodexAsyncHandler):
90
188
  """Report whether Codex is installed and the app-server is healthy."""
91
189
 
190
+ @property
92
191
  def command_name(self) -> str:
93
192
  return "codex_status"
94
193
 
95
194
  async def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
96
195
  installed = bool(CodexAppServer.get_binary_path())
97
- version = CodexAppServer.version()
196
+ # Avoid blocking the asyncio loop with a sync subprocess during status.
197
+ version = None
98
198
  ready = False
99
199
  error_message: Optional[str] = None
100
200
 
101
201
  if installed:
102
202
  try:
203
+ loop = asyncio.get_running_loop()
204
+ version = await loop.run_in_executor(None, CodexAppServer.version)
103
205
  manager = _get_manager(self)
104
206
  await manager.ensure_started()
105
207
  ready = await manager.bridge.healthy()
@@ -121,9 +223,10 @@ class CodexStatusHandler(AsyncHandler):
121
223
  return payload
122
224
 
123
225
 
124
- class CodexThreadListHandler(AsyncHandler):
226
+ class CodexThreadListHandler(CodexAsyncHandler):
125
227
  """List Codex threads for a given project cwd."""
126
228
 
229
+ @property
127
230
  def command_name(self) -> str:
128
231
  return "codex_thread_list"
129
232
 
@@ -135,19 +238,23 @@ class CodexThreadListHandler(AsyncHandler):
135
238
  manager = _get_manager(self)
136
239
  await manager.ensure_started()
137
240
 
138
- params: Dict[str, Any] = {"cwd": cwd, "useStateDbOnly": True}
139
- limit = message.get("limit")
241
+ # Default sourceKinds is cli+vscode only; include appServer so IDE chats appear.
242
+ # Avoid useStateDbOnly:true — it has returned empty lists in some Codex builds.
243
+ params: Dict[str, Any] = {
244
+ "cwd": cwd,
245
+ "sourceKinds": ["cli", "vscode", "appServer"],
246
+ "limit": message.get("limit") if message.get("limit") is not None else 50,
247
+ }
140
248
  cursor = message.get("cursor")
141
- if limit is not None:
142
- params["limit"] = limit
143
249
  if cursor is not None:
144
250
  params["cursor"] = cursor
145
251
 
146
252
  result = await manager.bridge.call("thread/list", params)
253
+ threads, next_cursor = _threads_from_list_result(result)
147
254
  payload = {
148
255
  "event": "codex_thread_list",
149
- "threads": result.get("threads", []),
150
- "nextCursor": result.get("nextCursor"),
256
+ "threads": threads,
257
+ "nextCursor": next_cursor,
151
258
  }
152
259
  project_id = _project_id(message)
153
260
  if project_id:
@@ -155,9 +262,10 @@ class CodexThreadListHandler(AsyncHandler):
155
262
  return payload
156
263
 
157
264
 
158
- class CodexThreadStartHandler(AsyncHandler):
265
+ class CodexThreadStartHandler(CodexAsyncHandler):
159
266
  """Start a new Codex thread in the project directory."""
160
267
 
268
+ @property
161
269
  def command_name(self) -> str:
162
270
  return "codex_thread_start"
163
271
 
@@ -178,7 +286,8 @@ class CodexThreadStartHandler(AsyncHandler):
178
286
  params["modelProvider"] = message["modelProvider"]
179
287
 
180
288
  result = await manager.bridge.call("thread/start", params)
181
- thread_id = result.get("id") or result.get("threadId")
289
+ thread = _thread_from_result(result)
290
+ thread_id = _thread_id_from_result(result)
182
291
  if not thread_id:
183
292
  raise CodexAppServerError("thread/start did not return a thread id")
184
293
 
@@ -187,16 +296,17 @@ class CodexThreadStartHandler(AsyncHandler):
187
296
  payload = {
188
297
  "event": "codex_thread_started",
189
298
  "threadId": thread_id,
190
- "thread": result,
299
+ "thread": thread,
191
300
  }
192
301
  if project_id:
193
302
  payload["project_id"] = project_id
194
303
  return payload
195
304
 
196
305
 
197
- class CodexThreadResumeHandler(AsyncHandler):
306
+ class CodexThreadResumeHandler(CodexAsyncHandler):
198
307
  """Resume a Codex thread and return its history."""
199
308
 
309
+ @property
200
310
  def command_name(self) -> str:
201
311
  return "codex_thread_resume"
202
312
 
@@ -215,8 +325,11 @@ class CodexThreadResumeHandler(AsyncHandler):
215
325
  resume_params["cwd"] = cwd
216
326
  await manager.bridge.call("thread/resume", resume_params)
217
327
 
218
- read_result = await manager.bridge.call("thread/read", {"threadId": thread_id})
219
- items = read_result.get("items", read_result.get("messages", []))
328
+ read_result = await manager.bridge.call(
329
+ "thread/read",
330
+ {"threadId": thread_id, "includeTurns": True},
331
+ )
332
+ items = _items_from_read_result(read_result)
220
333
 
221
334
  if cwd and project_id:
222
335
  manager.record_thread(thread_id, cwd, project_id)
@@ -231,9 +344,10 @@ class CodexThreadResumeHandler(AsyncHandler):
231
344
  return payload
232
345
 
233
346
 
234
- class CodexTurnStartHandler(AsyncHandler):
347
+ class CodexTurnStartHandler(CodexAsyncHandler):
235
348
  """Send a user turn to a Codex thread."""
236
349
 
350
+ @property
237
351
  def command_name(self) -> str:
238
352
  return "codex_turn_start"
239
353
 
@@ -264,16 +378,17 @@ class CodexTurnStartHandler(AsyncHandler):
264
378
  payload = {
265
379
  "event": "codex_turn_started",
266
380
  "threadId": thread_id,
267
- "turn": result,
381
+ "turn": _turn_from_result(result),
268
382
  }
269
383
  if project_id:
270
384
  payload["project_id"] = project_id
271
385
  return payload
272
386
 
273
387
 
274
- class CodexTurnInterruptHandler(AsyncHandler):
388
+ class CodexTurnInterruptHandler(CodexAsyncHandler):
275
389
  """Interrupt a running Codex turn."""
276
390
 
391
+ @property
277
392
  def command_name(self) -> str:
278
393
  return "codex_turn_interrupt"
279
394
 
@@ -294,7 +409,7 @@ class CodexTurnInterruptHandler(AsyncHandler):
294
409
  return payload
295
410
 
296
411
 
297
- class CodexPrepareHandler(AsyncHandler):
412
+ class CodexPrepareHandler(CodexAsyncHandler):
298
413
  """Run `portacode prepare codex` on the device in the background.
299
414
 
300
415
  Streams progress as `codex_prepare_progress` events and finishes with a
@@ -302,6 +417,7 @@ class CodexPrepareHandler(AsyncHandler):
302
417
  show manual instructions when sudo is required).
303
418
  """
304
419
 
420
+ @property
305
421
  def command_name(self) -> str:
306
422
  return "codex_prepare"
307
423
 
@@ -11,11 +11,14 @@ from portacode.connection.codex_app_server import CodexAppServer, CodexAppServer
11
11
 
12
12
 
13
13
  class FakeWriteStream:
14
- def __init__(self) -> None:
14
+ def __init__(self, process: "FakeProcess | None" = None) -> None:
15
15
  self.written: list[bytes] = []
16
+ self._process = process
16
17
 
17
18
  def write(self, data: bytes) -> None:
18
19
  self.written.append(data)
20
+ if self._process is not None:
21
+ self._process._maybe_auto_respond(data)
19
22
 
20
23
  async def drain(self) -> None:
21
24
  pass
@@ -41,13 +44,38 @@ class FakeReadStream:
41
44
  class FakeProcess:
42
45
  returncode: int | None = None
43
46
 
44
- def __init__(self, responses: list[dict] | None = None) -> None:
47
+ def __init__(
48
+ self,
49
+ responses: list[dict] | None = None,
50
+ *,
51
+ auto_initialize: bool = False,
52
+ ) -> None:
45
53
  self.queue: asyncio.Queue[bytes] = asyncio.Queue()
46
54
  for response in responses or []:
47
- self.queue.put_nowait((json.dumps(response) + "\n").encode("utf-8"))
48
- self.stdin = FakeWriteStream()
55
+ self.queue.put_nowait(
56
+ (json.dumps(response, separators=(",", ":")) + "\n").encode("utf-8")
57
+ )
58
+ self.stdin = FakeWriteStream(self if auto_initialize else None)
49
59
  self.stdout = FakeReadStream(self.queue)
50
60
  self.stderr = FakeReadStream(asyncio.Queue())
61
+ self._auto_initialize = auto_initialize
62
+
63
+ def _maybe_auto_respond(self, data: bytes) -> None:
64
+ if not self._auto_initialize:
65
+ return
66
+ try:
67
+ message = json.loads(data.decode("utf-8").strip())
68
+ except Exception:
69
+ return
70
+ if message.get("method") != "initialize":
71
+ return
72
+ request_id = message.get("id")
73
+ if request_id is None:
74
+ return
75
+ self.queue.put_nowait((json.dumps(
76
+ {"jsonrpc": "2.0", "id": request_id, "result": {"protocolVersion": "v2"}},
77
+ separators=(",", ":"),
78
+ ) + "\n").encode("utf-8"))
51
79
 
52
80
  async def wait(self) -> int:
53
81
  return self.returncode or 0
@@ -85,12 +113,28 @@ async def test_initialize_handshake():
85
113
 
86
114
  @pytest.mark.asyncio
87
115
  async def test_request_response_correlation():
116
+ # Only preload the initialize response. Queuing the call response early can
117
+ # race the reader ahead of the pending-future registration.
88
118
  proc = FakeProcess([
89
119
  {"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "v2"}},
90
- {"jsonrpc": "2.0", "id": 2, "result": {"id": "th-abc", "name": "test"}},
91
120
  ])
92
121
  bridge = CodexAppServer(_process_factory=_factory_for(proc))
122
+ await bridge.start()
123
+
124
+ async def _respond_to_thread_start() -> None:
125
+ # Wait until the request is written, then enqueue the matching response.
126
+ for _ in range(50):
127
+ if any(b'"method":"thread/start"' in chunk for chunk in proc.stdin.written):
128
+ break
129
+ await asyncio.sleep(0.01)
130
+ proc.queue.put_nowait((json.dumps(
131
+ {"jsonrpc": "2.0", "id": 2, "result": {"id": "th-abc", "name": "test"}},
132
+ separators=(",", ":"),
133
+ ) + "\n").encode("utf-8"))
134
+
135
+ respond_task = asyncio.create_task(_respond_to_thread_start())
93
136
  result = await bridge.call("thread/start", {"cwd": "/tmp/proj"})
137
+ await respond_task
94
138
 
95
139
  assert result["id"] == "th-abc"
96
140
  assert any(b'"method":"thread/start"' in chunk and b'/tmp/proj' in chunk for chunk in proc.stdin.written)
@@ -148,7 +192,8 @@ async def test_missing_binary_raises():
148
192
  @pytest.mark.asyncio
149
193
  async def test_restart_after_crash():
150
194
  first = FakeProcess([{"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "v2"}}])
151
- second = FakeProcess([{"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "v2"}}])
195
+ # Auto-echo initialize with whatever request id the restarted bridge uses.
196
+ second = FakeProcess(auto_initialize=True)
152
197
 
153
198
  bridge = CodexAppServer(_process_factory=_factory_for(first, second))
154
199
  await bridge.start()
@@ -43,11 +43,20 @@ class FakeBridge:
43
43
  def __init__(self) -> None:
44
44
  self.calls: list[tuple[str, dict]] = []
45
45
  self.responses: dict[str, Any] = {
46
- "thread/start": {"id": "th-1", "name": "New chat"},
47
- "thread/list": {"threads": [{"id": "th-1", "name": "Existing chat"}], "nextCursor": None},
48
- "thread/resume": {},
49
- "thread/read": {"items": [{"id": "msg-1", "role": "user", "text": "hello"}]},
50
- "turn/start": {"id": "turn-1", "threadId": "th-1"},
46
+ # Match current Codex app-server response shapes.
47
+ "thread/start": {"thread": {"id": "th-1", "name": "New chat"}},
48
+ "thread/list": {
49
+ "data": [{"id": "th-1", "name": "Existing chat", "preview": "hi"}],
50
+ "nextCursor": None,
51
+ },
52
+ "thread/resume": {"thread": {"id": "th-1"}},
53
+ "thread/read": {
54
+ "thread": {
55
+ "id": "th-1",
56
+ "turns": [{"id": "turn-1", "items": [{"id": "msg-1", "role": "user", "text": "hello"}]}],
57
+ }
58
+ },
59
+ "turn/start": {"turn": {"id": "turn-1", "threadId": "th-1"}},
51
60
  "turn/interrupt": {},
52
61
  }
53
62
 
@@ -103,6 +112,11 @@ async def test_codex_thread_list():
103
112
  assert payload["event"] == "codex_thread_list"
104
113
  assert payload["threads"][0]["id"] == "th-1"
105
114
  assert payload["project_id"] == "p-1"
115
+ list_call = manager.bridge.calls[-1]
116
+ assert list_call[0] == "thread/list"
117
+ assert list_call[1]["cwd"] == "/tmp/proj"
118
+ assert "appServer" in list_call[1]["sourceKinds"]
119
+ assert "useStateDbOnly" not in list_call[1]
106
120
 
107
121
 
108
122
  @pytest.mark.asyncio
@@ -138,6 +152,8 @@ async def test_codex_thread_resume():
138
152
  assert payload["event"] == "codex_thread_resumed"
139
153
  assert payload["items"][0]["text"] == "hello"
140
154
  assert manager._thread_project["th-1"] == "p-1"
155
+ read_call = next(c for c in manager.bridge.calls if c[0] == "thread/read")
156
+ assert read_call[1]["includeTurns"] is True
141
157
 
142
158
 
143
159
  @pytest.mark.asyncio
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.5.14.dev1
3
+ Version: 1.5.14.dev3
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -340,6 +340,7 @@ portacode/connection/handlers/project_state/models.py
340
340
  portacode/connection/handlers/project_state/test_handlers.py
341
341
  portacode/connection/handlers/project_state/utils.py
342
342
  portacode/link_capture/__init__.py
343
+ portacode/link_capture/__pycache__/__init__.cpython-311.pyc
343
344
  portacode/link_capture/bin/elinks
344
345
  portacode/link_capture/bin/gio-open
345
346
  portacode/link_capture/bin/gnome-open
File without changes