codex-autorunner 0.1.2__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. {codex_autorunner-0.1.2/src/codex_autorunner.egg-info → codex_autorunner-1.0.0}/PKG-INFO +18 -21
  2. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/README.md +17 -20
  3. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/pyproject.toml +6 -1
  4. codex_autorunner-1.0.0/src/codex_autorunner/__main__.py +4 -0
  5. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/client.py +68 -35
  6. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/logging.py +21 -5
  7. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/run_prompt.py +1 -0
  8. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/runtime.py +118 -30
  9. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/supervisor.py +36 -48
  10. codex_autorunner-1.0.0/src/codex_autorunner/agents/registry.py +258 -0
  11. codex_autorunner-1.0.0/src/codex_autorunner/api.py +25 -0
  12. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/bootstrap.py +16 -35
  13. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/cli.py +157 -139
  14. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/about_car.py +44 -32
  15. codex_autorunner-1.0.0/src/codex_autorunner/core/adapter_utils.py +21 -0
  16. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/app_server_logging.py +7 -3
  17. codex_autorunner-1.0.0/src/codex_autorunner/core/app_server_prompts.py +145 -0
  18. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/app_server_threads.py +15 -26
  19. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/codex_runner.py +6 -0
  20. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/config.py +390 -100
  21. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/docs.py +10 -2
  22. codex_autorunner-1.0.0/src/codex_autorunner/core/drafts.py +82 -0
  23. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/engine.py +278 -262
  24. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/__init__.py +25 -0
  25. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/controller.py +178 -0
  26. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/definition.py +82 -0
  27. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/models.py +75 -0
  28. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/runtime.py +351 -0
  29. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/store.py +485 -0
  30. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/transition.py +133 -0
  31. codex_autorunner-1.0.0/src/codex_autorunner/core/flows/worker_process.py +242 -0
  32. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/hub.py +15 -9
  33. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/locks.py +4 -0
  34. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/prompt.py +15 -7
  35. codex_autorunner-1.0.0/src/codex_autorunner/core/redaction.py +29 -0
  36. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/review_context.py +5 -8
  37. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/run_index.py +6 -0
  38. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/runner_process.py +5 -2
  39. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/state.py +0 -88
  40. codex_autorunner-1.0.0/src/codex_autorunner/core/static_assets.py +55 -0
  41. codex_autorunner-1.0.0/src/codex_autorunner/core/supervisor_utils.py +67 -0
  42. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/update.py +20 -11
  43. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/update_runner.py +2 -0
  44. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/utils.py +29 -2
  45. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/discovery.py +2 -4
  46. codex_autorunner-1.0.0/src/codex_autorunner/flows/ticket_flow/__init__.py +3 -0
  47. codex_autorunner-1.0.0/src/codex_autorunner/flows/ticket_flow/definition.py +91 -0
  48. codex_autorunner-1.0.0/src/codex_autorunner/integrations/agents/__init__.py +27 -0
  49. codex_autorunner-1.0.0/src/codex_autorunner/integrations/agents/agent_backend.py +142 -0
  50. codex_autorunner-1.0.0/src/codex_autorunner/integrations/agents/codex_backend.py +307 -0
  51. codex_autorunner-1.0.0/src/codex_autorunner/integrations/agents/opencode_backend.py +325 -0
  52. codex_autorunner-1.0.0/src/codex_autorunner/integrations/agents/run_event.py +71 -0
  53. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/app_server/client.py +576 -92
  54. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/app_server/supervisor.py +59 -33
  55. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/adapter.py +141 -167
  56. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/api_schemas.py +120 -0
  57. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/config.py +175 -0
  58. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/constants.py +16 -1
  59. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/dispatch.py +17 -0
  60. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/doctor.py +47 -0
  61. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/callbacks.py +0 -4
  62. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
  63. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
  64. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
  65. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/handlers/commands/flows.py +227 -0
  66. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
  67. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
  68. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
  69. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands_runtime.py +133 -475
  70. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands_spec.py +11 -4
  71. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/messages.py +120 -9
  72. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/helpers.py +88 -16
  73. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/outbox.py +366 -0
  74. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/progress_stream.py +3 -10
  75. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/service.py +214 -40
  76. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/state.py +100 -2
  77. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/ticket_flow_bridge.py +322 -0
  78. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/transport.py +36 -3
  79. codex_autorunner-1.0.0/src/codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
  80. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/manifest.py +2 -0
  81. codex_autorunner-1.0.0/src/codex_autorunner/plugin_api.py +22 -0
  82. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/__init__.py +23 -14
  83. codex_autorunner-1.0.0/src/codex_autorunner/routes/analytics.py +239 -0
  84. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/base.py +81 -109
  85. codex_autorunner-1.0.0/src/codex_autorunner/routes/file_chat.py +836 -0
  86. codex_autorunner-1.0.0/src/codex_autorunner/routes/flows.py +980 -0
  87. codex_autorunner-1.0.0/src/codex_autorunner/routes/messages.py +459 -0
  88. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/system.py +6 -1
  89. codex_autorunner-1.0.0/src/codex_autorunner/routes/usage.py +87 -0
  90. codex_autorunner-1.0.0/src/codex_autorunner/routes/workspace.py +271 -0
  91. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/server.py +2 -1
  92. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/agentControls.js +1 -0
  93. codex_autorunner-1.0.0/src/codex_autorunner/static/agentEvents.js +248 -0
  94. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/app.js +25 -22
  95. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/autoRefresh.js +29 -1
  96. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/bootstrap.js +1 -0
  97. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/bus.js +1 -0
  98. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/cache.js +1 -0
  99. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/constants.js +20 -4
  100. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/dashboard.js +162 -196
  101. codex_autorunner-1.0.0/src/codex_autorunner/static/diffRenderer.js +37 -0
  102. codex_autorunner-1.0.0/src/codex_autorunner/static/docChatCore.js +324 -0
  103. codex_autorunner-1.0.0/src/codex_autorunner/static/docChatStorage.js +65 -0
  104. codex_autorunner-1.0.0/src/codex_autorunner/static/docChatVoice.js +65 -0
  105. codex_autorunner-1.0.0/src/codex_autorunner/static/docEditor.js +133 -0
  106. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/env.js +1 -0
  107. codex_autorunner-1.0.0/src/codex_autorunner/static/eventSummarizer.js +166 -0
  108. codex_autorunner-1.0.0/src/codex_autorunner/static/fileChat.js +182 -0
  109. codex_autorunner-1.0.0/src/codex_autorunner/static/health.js +155 -0
  110. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/hub.js +41 -118
  111. codex_autorunner-1.0.0/src/codex_autorunner/static/index.html +909 -0
  112. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/liveUpdates.js +1 -0
  113. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/loader.js +1 -0
  114. codex_autorunner-1.0.0/src/codex_autorunner/static/messages.js +470 -0
  115. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/mobileCompact.js +2 -1
  116. codex_autorunner-1.0.0/src/codex_autorunner/static/settings.js +154 -0
  117. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/styles.css +7567 -3865
  118. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/tabs.js +28 -5
  119. codex_autorunner-1.0.0/src/codex_autorunner/static/terminal.js +26 -0
  120. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/terminalManager.js +34 -59
  121. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketChatActions.js +333 -0
  122. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketChatEvents.js +16 -0
  123. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketChatStorage.js +16 -0
  124. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketChatStream.js +264 -0
  125. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketEditor.js +750 -0
  126. codex_autorunner-1.0.0/src/codex_autorunner/static/ticketVoice.js +9 -0
  127. codex_autorunner-1.0.0/src/codex_autorunner/static/tickets.js +1315 -0
  128. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/utils.js +32 -3
  129. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/voice.js +1 -0
  130. codex_autorunner-1.0.0/src/codex_autorunner/static/workspace.js +672 -0
  131. codex_autorunner-1.0.0/src/codex_autorunner/static/workspaceApi.js +53 -0
  132. codex_autorunner-1.0.0/src/codex_autorunner/static/workspaceFileBrowser.js +504 -0
  133. codex_autorunner-1.0.0/src/codex_autorunner/tickets/__init__.py +20 -0
  134. codex_autorunner-1.0.0/src/codex_autorunner/tickets/agent_pool.py +377 -0
  135. codex_autorunner-1.0.0/src/codex_autorunner/tickets/files.py +85 -0
  136. codex_autorunner-1.0.0/src/codex_autorunner/tickets/frontmatter.py +55 -0
  137. codex_autorunner-1.0.0/src/codex_autorunner/tickets/lint.py +102 -0
  138. codex_autorunner-1.0.0/src/codex_autorunner/tickets/models.py +95 -0
  139. codex_autorunner-1.0.0/src/codex_autorunner/tickets/outbox.py +232 -0
  140. codex_autorunner-1.0.0/src/codex_autorunner/tickets/replies.py +179 -0
  141. codex_autorunner-1.0.0/src/codex_autorunner/tickets/runner.py +823 -0
  142. codex_autorunner-1.0.0/src/codex_autorunner/tickets/spec_ingest.py +77 -0
  143. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/app.py +269 -91
  144. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/middleware.py +3 -4
  145. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/schemas.py +89 -109
  146. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/static_assets.py +1 -44
  147. codex_autorunner-1.0.0/src/codex_autorunner/workspace/__init__.py +40 -0
  148. codex_autorunner-1.0.0/src/codex_autorunner/workspace/paths.py +319 -0
  149. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0/src/codex_autorunner.egg-info}/PKG-INFO +18 -21
  150. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner.egg-info/SOURCES.txt +78 -55
  151. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_about_car_terminal_context.py +3 -3
  152. codex_autorunner-1.0.0/tests/test_agent_run_events.py +347 -0
  153. codex_autorunner-1.0.0/tests/test_agents_plugins.py +67 -0
  154. codex_autorunner-1.0.0/tests/test_api_contract.py +47 -0
  155. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_app_server_client.py +39 -2
  156. codex_autorunner-1.0.0/tests/test_app_server_prompts.py +36 -0
  157. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_auth_middleware.py +1 -3
  158. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_base_path_static.py +8 -10
  159. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_codex_app_server_integration.py +3 -1
  160. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_config_resolution.py +2 -2
  161. codex_autorunner-1.0.0/tests/test_core_web_boundary.py +18 -0
  162. codex_autorunner-1.0.0/tests/test_file_chat_drafts.py +115 -0
  163. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_hub_supervisor.py +0 -8
  164. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_opencode_agent_config.py +4 -4
  165. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_opencode_client.py +23 -1
  166. codex_autorunner-1.0.0/tests/test_opencode_event_formatter.py +28 -0
  167. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_opencode_runtime.py +104 -0
  168. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_patch_utils.py +16 -8
  169. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_prompt.py +3 -5
  170. codex_autorunner-1.0.0/tests/test_redaction.py +60 -0
  171. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_request_logging.py +2 -2
  172. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_review_context.py +8 -8
  173. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_runner_controller.py +30 -1
  174. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_static_asset_cache.py +21 -22
  175. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_adapter.py +415 -0
  176. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_bot_config.py +61 -0
  177. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_bot_integration.py +1 -1
  178. codex_autorunner-1.0.0/tests/test_telegram_codex_feature_flags.py +67 -0
  179. codex_autorunner-1.0.0/tests/test_telegram_outbox.py +303 -0
  180. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_review_opencode.py +2 -0
  181. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_state.py +17 -0
  182. codex_autorunner-1.0.0/tests/test_telegram_trigger_mode.py +45 -0
  183. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_turn_queue.py +1 -0
  184. codex_autorunner-1.0.0/tests/test_ticket_flow_approval_config.py +125 -0
  185. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_transcribe_endpoint.py +6 -6
  186. codex_autorunner-1.0.0/tests/test_workspace_functional.py +378 -0
  187. codex_autorunner-1.0.0/tests/test_workspace_paths.py +42 -0
  188. codex_autorunner-0.1.2/src/codex_autorunner/agents/execution/policy.py +0 -292
  189. codex_autorunner-0.1.2/src/codex_autorunner/agents/factory.py +0 -52
  190. codex_autorunner-0.1.2/src/codex_autorunner/agents/orchestrator.py +0 -358
  191. codex_autorunner-0.1.2/src/codex_autorunner/agents/registry.py +0 -130
  192. codex_autorunner-0.1.2/src/codex_autorunner/core/app_server_prompts.py +0 -378
  193. codex_autorunner-0.1.2/src/codex_autorunner/core/doc_chat.py +0 -1446
  194. codex_autorunner-0.1.2/src/codex_autorunner/core/snapshot.py +0 -580
  195. codex_autorunner-0.1.2/src/codex_autorunner/integrations/github/chatops.py +0 -268
  196. codex_autorunner-0.1.2/src/codex_autorunner/integrations/github/pr_flow.py +0 -1314
  197. codex_autorunner-0.1.2/src/codex_autorunner/integrations/telegram/outbox.py +0 -195
  198. codex_autorunner-0.1.2/src/codex_autorunner/routes/docs.py +0 -381
  199. codex_autorunner-0.1.2/src/codex_autorunner/routes/github.py +0 -327
  200. codex_autorunner-0.1.2/src/codex_autorunner/routes/runs.py +0 -250
  201. codex_autorunner-0.1.2/src/codex_autorunner/spec_ingest.py +0 -812
  202. codex_autorunner-0.1.2/src/codex_autorunner/static/docChatActions.js +0 -287
  203. codex_autorunner-0.1.2/src/codex_autorunner/static/docChatEvents.js +0 -300
  204. codex_autorunner-0.1.2/src/codex_autorunner/static/docChatRender.js +0 -205
  205. codex_autorunner-0.1.2/src/codex_autorunner/static/docChatStream.js +0 -361
  206. codex_autorunner-0.1.2/src/codex_autorunner/static/docs.js +0 -20
  207. codex_autorunner-0.1.2/src/codex_autorunner/static/docsClipboard.js +0 -69
  208. codex_autorunner-0.1.2/src/codex_autorunner/static/docsCrud.js +0 -257
  209. codex_autorunner-0.1.2/src/codex_autorunner/static/docsDocUpdates.js +0 -62
  210. codex_autorunner-0.1.2/src/codex_autorunner/static/docsDrafts.js +0 -16
  211. codex_autorunner-0.1.2/src/codex_autorunner/static/docsElements.js +0 -69
  212. codex_autorunner-0.1.2/src/codex_autorunner/static/docsInit.js +0 -285
  213. codex_autorunner-0.1.2/src/codex_autorunner/static/docsParse.js +0 -160
  214. codex_autorunner-0.1.2/src/codex_autorunner/static/docsSnapshot.js +0 -87
  215. codex_autorunner-0.1.2/src/codex_autorunner/static/docsSpecIngest.js +0 -263
  216. codex_autorunner-0.1.2/src/codex_autorunner/static/docsState.js +0 -127
  217. codex_autorunner-0.1.2/src/codex_autorunner/static/docsThreadRegistry.js +0 -44
  218. codex_autorunner-0.1.2/src/codex_autorunner/static/docsUi.js +0 -153
  219. codex_autorunner-0.1.2/src/codex_autorunner/static/docsVoice.js +0 -56
  220. codex_autorunner-0.1.2/src/codex_autorunner/static/github.js +0 -504
  221. codex_autorunner-0.1.2/src/codex_autorunner/static/index.html +0 -980
  222. codex_autorunner-0.1.2/src/codex_autorunner/static/logs.js +0 -678
  223. codex_autorunner-0.1.2/src/codex_autorunner/static/review.js +0 -157
  224. codex_autorunner-0.1.2/src/codex_autorunner/static/runs.js +0 -418
  225. codex_autorunner-0.1.2/src/codex_autorunner/static/settings.js +0 -341
  226. codex_autorunner-0.1.2/src/codex_autorunner/static/snapshot.js +0 -124
  227. codex_autorunner-0.1.2/src/codex_autorunner/static/state.js +0 -94
  228. codex_autorunner-0.1.2/src/codex_autorunner/static/terminal.js +0 -12
  229. codex_autorunner-0.1.2/src/codex_autorunner/static/todoPreview.js +0 -27
  230. codex_autorunner-0.1.2/src/codex_autorunner/workspace.py +0 -16
  231. codex_autorunner-0.1.2/tests/test_agent_policy.py +0 -258
  232. codex_autorunner-0.1.2/tests/test_api_contract.py +0 -42
  233. codex_autorunner-0.1.2/tests/test_app_server_prompts.py +0 -84
  234. codex_autorunner-0.1.2/tests/test_chatops.py +0 -38
  235. codex_autorunner-0.1.2/tests/test_cli_snapshot.py +0 -37
  236. codex_autorunner-0.1.2/tests/test_doc_chat.py +0 -508
  237. codex_autorunner-0.1.2/tests/test_doc_chat_ui.py +0 -231
  238. codex_autorunner-0.1.2/tests/test_docs_todos.py +0 -148
  239. codex_autorunner-0.1.2/tests/test_docs_validation.py +0 -18
  240. codex_autorunner-0.1.2/tests/test_github_context_hook.py +0 -154
  241. codex_autorunner-0.1.2/tests/test_github_service.py +0 -76
  242. codex_autorunner-0.1.2/tests/test_github_sync_pr_agentic.py +0 -212
  243. codex_autorunner-0.1.2/tests/test_orchestrator.py +0 -600
  244. codex_autorunner-0.1.2/tests/test_pr_flow.py +0 -191
  245. codex_autorunner-0.1.2/tests/test_snapshot_api.py +0 -70
  246. codex_autorunner-0.1.2/tests/test_snapshot_core.py +0 -52
  247. codex_autorunner-0.1.2/tests/test_snapshot_incremental.py +0 -136
  248. codex_autorunner-0.1.2/tests/test_spec_ingest.py +0 -26
  249. codex_autorunner-0.1.2/tests/test_telegram_outbox.py +0 -67
  250. codex_autorunner-0.1.2/tests/test_telegram_pr_flow.py +0 -129
  251. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/LICENSE +0 -0
  252. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/setup.cfg +0 -0
  253. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/__init__.py +0 -0
  254. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/__init__.py +0 -0
  255. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/base.py +0 -0
  256. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/codex/__init__.py +0 -0
  257. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/codex/harness.py +0 -0
  258. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/__init__.py +0 -0
  259. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/agent_config.py +0 -0
  260. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/events.py +0 -0
  261. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/opencode/harness.py +0 -0
  262. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/agents/types.py +0 -0
  263. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/codex_cli.py +0 -0
  264. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/codex_runner.py +0 -0
  265. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/__init__.py +0 -0
  266. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/app_server_events.py +0 -0
  267. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/circuit_breaker.py +0 -0
  268. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/exceptions.py +0 -0
  269. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/git_utils.py +0 -0
  270. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/injected_context.py +0 -0
  271. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/logging_utils.py +0 -0
  272. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/notifications.py +0 -0
  273. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/optional_dependencies.py +0 -0
  274. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/patch_utils.py +0 -0
  275. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/path_utils.py +0 -0
  276. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/prompts.py +0 -0
  277. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/request_context.py +0 -0
  278. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/retry.py +0 -0
  279. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/review.py +0 -0
  280. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/runner_controller.py +0 -0
  281. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/sqlite_utils.py +0 -0
  282. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/text_delta_coalescer.py +0 -0
  283. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/core/usage.py +0 -0
  284. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/housekeeping.py +0 -0
  285. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/__init__.py +0 -0
  286. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/app_server/__init__.py +0 -0
  287. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/app_server/env.py +0 -0
  288. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/github/__init__.py +0 -0
  289. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/github/service.py +0 -0
  290. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/__init__.py +0 -0
  291. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/commands_registry.py +0 -0
  292. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/__init__.py +0 -0
  293. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/approvals.py +0 -0
  294. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/approvals.py +0 -0
  295. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/shared.py +0 -0
  296. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/commands/voice.py +0 -0
  297. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/questions.py +0 -0
  298. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/selections.py +0 -0
  299. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/handlers/utils.py +0 -0
  300. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/notifications.py +0 -0
  301. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/overflow.py +0 -0
  302. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/rendering.py +0 -0
  303. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/retry.py +0 -0
  304. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/runtime.py +0 -0
  305. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/types.py +0 -0
  306. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/integrations/telegram/voice.py +0 -0
  307. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/agents.py +0 -0
  308. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/app_server.py +0 -0
  309. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/repos.py +0 -0
  310. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/review.py +0 -0
  311. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/sessions.py +0 -0
  312. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/settings.py +0 -0
  313. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/shared.py +0 -0
  314. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/terminal_images.py +0 -0
  315. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/routes/voice.py +0 -0
  316. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/LICENSE.xterm +0 -0
  317. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic-ext.woff2 +0 -0
  318. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic.woff2 +0 -0
  319. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-greek.woff2 +0 -0
  320. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin-ext.woff2 +0 -0
  321. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin.woff2 +0 -0
  322. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-vietnamese.woff2 +0 -0
  323. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic-ext.woff2 +0 -0
  324. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic.woff2 +0 -0
  325. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-greek.woff2 +0 -0
  326. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin-ext.woff2 +0 -0
  327. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin.woff2 +0 -0
  328. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-vietnamese.woff2 +0 -0
  329. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic-ext.woff2 +0 -0
  330. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic.woff2 +0 -0
  331. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-greek.woff2 +0 -0
  332. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin-ext.woff2 +0 -0
  333. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin.woff2 +0 -0
  334. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-vietnamese.woff2 +0 -0
  335. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/fonts/jetbrains-mono/OFL.txt +0 -0
  336. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/xterm-addon-fit.js +0 -0
  337. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/xterm.css +0 -0
  338. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/static/vendor/xterm.js +0 -0
  339. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/__init__.py +0 -0
  340. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/capture.py +0 -0
  341. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/config.py +0 -0
  342. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/provider.py +0 -0
  343. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/providers/__init__.py +0 -0
  344. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/providers/openai_whisper.py +0 -0
  345. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/resolver.py +0 -0
  346. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/voice/service.py +0 -0
  347. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/__init__.py +0 -0
  348. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/hub_jobs.py +0 -0
  349. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/pty_session.py +0 -0
  350. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/runner_manager.py +0 -0
  351. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/static_refresh.py +0 -0
  352. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner/web/terminal_sessions.py +0 -0
  353. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner.egg-info/dependency_links.txt +0 -0
  354. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner.egg-info/entry_points.txt +0 -0
  355. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner.egg-info/requires.txt +0 -0
  356. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/src/codex_autorunner.egg-info/top_level.txt +0 -0
  357. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_agents_registry.py +0 -0
  358. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_app_server_event_formatter.py +0 -0
  359. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_app_server_events.py +0 -0
  360. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_app_server_supervisor.py +0 -0
  361. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_app_server_thread_registry.py +0 -0
  362. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_base_path.py +0 -0
  363. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_cli_init.py +0 -0
  364. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_cli_sessions.py +0 -0
  365. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_cli_status.py +0 -0
  366. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_codex_cli_flags.py +0 -0
  367. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_codex_runner.py +0 -0
  368. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_engine_app_server.py +0 -0
  369. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_engine_end_review.py +0 -0
  370. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_engine_logs.py +0 -0
  371. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_housekeeping.py +0 -0
  372. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_hub_create.py +0 -0
  373. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_hub_foundation.py +0 -0
  374. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_hub_terminal_sessions.py +0 -0
  375. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_hub_ui_escape.py +0 -0
  376. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_lock_utils.py +0 -0
  377. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_logging_utils.py +0 -0
  378. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_notifications.py +0 -0
  379. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_opencode_integration.py +0 -0
  380. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_opencode_review_arguments.py +0 -0
  381. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_optional_dependencies.py +0 -0
  382. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_origin_middleware.py +0 -0
  383. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_review_service.py +0 -0
  384. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_sse_streams.py +0 -0
  385. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_state_lock.py +0 -0
  386. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_state_sessions.py +0 -0
  387. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_static.py +0 -0
  388. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_system_update_check.py +0 -0
  389. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_system_update_worker.py +0 -0
  390. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_bot_lock.py +0 -0
  391. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_cache_cleanup.py +0 -0
  392. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_command_registry.py +0 -0
  393. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_fast_ack.py +0 -0
  394. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_handlers_callbacks.py +0 -0
  395. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_handlers_messages.py +0 -0
  396. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_interrupt_status.py +0 -0
  397. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_media_batch_failure.py +0 -0
  398. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_opencode_context_cache.py +0 -0
  399. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_opencode_usage.py +0 -0
  400. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_overflow.py +0 -0
  401. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_paths_compatible.py +0 -0
  402. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_progress_stream.py +0 -0
  403. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_status_rate_limits.py +0 -0
  404. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_task_tracking.py +0 -0
  405. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_thread_paths.py +0 -0
  406. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_topic_queue.py +0 -0
  407. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_transport.py +0 -0
  408. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_update_dedupe.py +0 -0
  409. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_telegram_whisper_disclaimer.py +0 -0
  410. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_terminal_idle_timeout.py +0 -0
  411. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_terminal_input_dedupe.py +0 -0
  412. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_usage.py +0 -0
  413. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_capture.py +0 -0
  414. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_config.py +0 -0
  415. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_service.py +0 -0
  416. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_ui.py +0 -0
  417. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_whisper_mime_types.py +0 -0
  418. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_voice_whisper_provider.py +0 -0
  419. {codex_autorunner-0.1.2 → codex_autorunner-1.0.0}/tests/test_workspace_helpers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-autorunner
3
- Version: 0.1.2
3
+ Version: 1.0.0
4
4
  Summary: Codex autorunner CLI per DESIGN-V1
5
5
  Author: Codex
6
6
  License: MIT License
@@ -65,11 +65,17 @@ Dynamic: license-file
65
65
  # codex-autorunner
66
66
  [![PyPI](https://img.shields.io/pypi/v/codex-autorunner.svg)](https://pypi.org/project/codex-autorunner/)
67
67
 
68
- An opinionated autorunner that uses the Codex CLI to work on large tasks via a simple loop. On each loop we feed the Codex instance the last one's final output along with core documents.
69
- 1. TODO - Tracks long-horizon tasks
70
- 2. PROGRESS - High level overview of what's been done already that may be relevant for future agents
71
- 3. OPINIONS - Guidelines for how we should approach implementation
72
- 4. SPEC - Source-of-truth requirements and scope for large features/projects
68
+ An opinionated autorunner that uses the Codex app-server as the primary execution backend with OpenCode support to work on large tasks via a simple loop. On each loop we feed the Codex instance the last one's final output along with core documents.
69
+
70
+ In the current model, the primary work surface is **tickets**:
71
+
72
+ - `.codex-autorunner/tickets/TICKET-###.md`
73
+
74
+ Optionally, you can maintain lightweight **workspace docs** (auto-created on write; missing is OK):
75
+
76
+ - `.codex-autorunner/workspace/active_context.md`
77
+ - `.codex-autorunner/workspace/decisions.md`
78
+ - `.codex-autorunner/workspace/spec.md`
73
79
 
74
80
  ## Sneak Peak
75
81
  Run multiple agents on many repositories, with git worktree support
@@ -81,8 +87,7 @@ See the progress of your long running tasks with a high level overview
81
87
  Dive deep into specific agent execution with a rich but readable log
82
88
  ![Desktop logs](docs/screenshots/car-desktop-logs.png)
83
89
 
84
- All memory and opinions are markdown files! Edit them directly or chat with the document!
85
- ![Desktop TODO](docs/screenshots/car-desktop-todo.png)
90
+ Tickets and workspace docs are markdown files. Edit them directly or use the web UI’s file chat to iterate with the agent.
86
91
 
87
92
  Use codex CLI directly for multi-shot problem solving or `/review`
88
93
  ![Desktop terminal](docs/screenshots/car-desktop-terminal.png)
@@ -92,11 +97,10 @@ Mobile-first experience, code on the go with Whisper support (BYOK)
92
97
 
93
98
  ## What it does
94
99
  - Initializes a repo with Codex-friendly docs and config.
95
- - Runs Codex in a loop against the repo, streaming logs.
100
+ - Runs Codex app-server in a loop against the repo, streaming logs via OpenCode runtime.
96
101
  - Tracks state, logs, and config under `.codex-autorunner/`.
97
- - Exposes a power-user HTTP API and web UI for docs, logs, runner control, and a Codex TUI terminal.
102
+ - Exposes a power-user HTTP API and web UI for tickets, workspace docs, file chat, logs, runner control, and a Codex TUI terminal.
98
103
  - Optionally runs a Telegram bot for interactive, user-in-the-loop Codex sessions.
99
- - Generates a pasteable repo snapshot (`.codex-autorunner/SNAPSHOT.md`) for sharing with other LLM chats.
100
104
 
101
105
  CLI commands are available as `codex-autorunner` or the shorter `car`.
102
106
 
@@ -166,7 +170,7 @@ If you set a base path, prefix all checks with it.
166
170
 
167
171
  ## Quick start
168
172
  1) Install (editable): `pip install -e .`
169
- 2) Initialize (hub + repo): `codex-autorunner init --git-init` (or `car init --git-init` if you prefer short). This creates the hub config at `.codex-autorunner/config.yml`, plus state/log files and the docs under `.codex-autorunner/`.
173
+ 2) Initialize (hub + repo): `codex-autorunner init --git-init` (or `car init --git-init` if you prefer short). This creates the hub config at `.codex-autorunner/config.yml`, plus state/log files and starter content under `.codex-autorunner/` (tickets and optional workspace docs).
170
174
  3) Run once: `codex-autorunner once` / `car once`
171
175
  4) Continuous loop: `codex-autorunner run` / `car run`
172
176
  5) If stuck: `codex-autorunner kill` then `codex-autorunner resume` (or the `car` equivalents)
@@ -231,19 +235,12 @@ If you set `server.auth_token_env`, the API requires `Authorization: Bearer <tok
231
235
  - `run` / `once` — run the loop (continuous or single iteration).
232
236
  - `resume` — clear stale lock/state and restart; `--once` for a single run.
233
237
  - `kill` — SIGTERM the running loop and mark state error.
234
- - `status` — show current state and outstanding TODO count.
238
+ - `status` — show current state.
235
239
  - `sessions` — list terminal sessions (server-backed when available).
236
240
  - `stop-session` — stop a terminal session by repo (`--repo`) or id (`--session`).
237
241
  - `log` — view logs (tail or specific run).
238
- - `edit` — open TODO/PROGRESS/OPINIONS/SPEC in `$EDITOR`.
239
- - `ingest-spec` — generate TODO/PROGRESS/OPINIONS from SPEC using Codex (use `--force` to overwrite).
240
- - `clear-docs` — reset TODO/PROGRESS/OPINIONS to empty templates (type CLEAR to confirm).
241
- - `snapshot` — generate/update `.codex-autorunner/SNAPSHOT.md` (incremental by default when one exists; use `--from-scratch` to regenerate).
242
+ - `edit` — open `active_context|decisions|spec` in `$EDITOR`.
242
243
  - `serve` — start the HTTP API (FastAPI) on host/port from config (defaults 127.0.0.1:4173).
243
244
 
244
- ## Snapshot (repo briefing)
245
- - Web UI: open the Snapshot tab. If no snapshot exists, you’ll see “Generate snapshot”; otherwise you’ll see “Update snapshot (incremental)” and “Regenerate snapshot (from scratch)”, plus “Copy to clipboard”.
246
- - CLI: `codex-autorunner snapshot` (or `car snapshot`) writes `.codex-autorunner/SNAPSHOT.md` and `.codex-autorunner/snapshot_state.json`.
247
-
248
245
  ## Star history
249
246
  [![Star History Chart](https://api.star-history.com/svg?repos=Git-on-my-level/codex-autorunner&type=Date)](https://star-history.com/#Git-on-my-level/codex-autorunner&Date)
@@ -1,11 +1,17 @@
1
1
  # codex-autorunner
2
2
  [![PyPI](https://img.shields.io/pypi/v/codex-autorunner.svg)](https://pypi.org/project/codex-autorunner/)
3
3
 
4
- An opinionated autorunner that uses the Codex CLI to work on large tasks via a simple loop. On each loop we feed the Codex instance the last one's final output along with core documents.
5
- 1. TODO - Tracks long-horizon tasks
6
- 2. PROGRESS - High level overview of what's been done already that may be relevant for future agents
7
- 3. OPINIONS - Guidelines for how we should approach implementation
8
- 4. SPEC - Source-of-truth requirements and scope for large features/projects
4
+ An opinionated autorunner that uses the Codex app-server as the primary execution backend with OpenCode support to work on large tasks via a simple loop. On each loop we feed the Codex instance the last one's final output along with core documents.
5
+
6
+ In the current model, the primary work surface is **tickets**:
7
+
8
+ - `.codex-autorunner/tickets/TICKET-###.md`
9
+
10
+ Optionally, you can maintain lightweight **workspace docs** (auto-created on write; missing is OK):
11
+
12
+ - `.codex-autorunner/workspace/active_context.md`
13
+ - `.codex-autorunner/workspace/decisions.md`
14
+ - `.codex-autorunner/workspace/spec.md`
9
15
 
10
16
  ## Sneak Peak
11
17
  Run multiple agents on many repositories, with git worktree support
@@ -17,8 +23,7 @@ See the progress of your long running tasks with a high level overview
17
23
  Dive deep into specific agent execution with a rich but readable log
18
24
  ![Desktop logs](docs/screenshots/car-desktop-logs.png)
19
25
 
20
- All memory and opinions are markdown files! Edit them directly or chat with the document!
21
- ![Desktop TODO](docs/screenshots/car-desktop-todo.png)
26
+ Tickets and workspace docs are markdown files. Edit them directly or use the web UI’s file chat to iterate with the agent.
22
27
 
23
28
  Use codex CLI directly for multi-shot problem solving or `/review`
24
29
  ![Desktop terminal](docs/screenshots/car-desktop-terminal.png)
@@ -28,11 +33,10 @@ Mobile-first experience, code on the go with Whisper support (BYOK)
28
33
 
29
34
  ## What it does
30
35
  - Initializes a repo with Codex-friendly docs and config.
31
- - Runs Codex in a loop against the repo, streaming logs.
36
+ - Runs Codex app-server in a loop against the repo, streaming logs via OpenCode runtime.
32
37
  - Tracks state, logs, and config under `.codex-autorunner/`.
33
- - Exposes a power-user HTTP API and web UI for docs, logs, runner control, and a Codex TUI terminal.
38
+ - Exposes a power-user HTTP API and web UI for tickets, workspace docs, file chat, logs, runner control, and a Codex TUI terminal.
34
39
  - Optionally runs a Telegram bot for interactive, user-in-the-loop Codex sessions.
35
- - Generates a pasteable repo snapshot (`.codex-autorunner/SNAPSHOT.md`) for sharing with other LLM chats.
36
40
 
37
41
  CLI commands are available as `codex-autorunner` or the shorter `car`.
38
42
 
@@ -102,7 +106,7 @@ If you set a base path, prefix all checks with it.
102
106
 
103
107
  ## Quick start
104
108
  1) Install (editable): `pip install -e .`
105
- 2) Initialize (hub + repo): `codex-autorunner init --git-init` (or `car init --git-init` if you prefer short). This creates the hub config at `.codex-autorunner/config.yml`, plus state/log files and the docs under `.codex-autorunner/`.
109
+ 2) Initialize (hub + repo): `codex-autorunner init --git-init` (or `car init --git-init` if you prefer short). This creates the hub config at `.codex-autorunner/config.yml`, plus state/log files and starter content under `.codex-autorunner/` (tickets and optional workspace docs).
106
110
  3) Run once: `codex-autorunner once` / `car once`
107
111
  4) Continuous loop: `codex-autorunner run` / `car run`
108
112
  5) If stuck: `codex-autorunner kill` then `codex-autorunner resume` (or the `car` equivalents)
@@ -167,19 +171,12 @@ If you set `server.auth_token_env`, the API requires `Authorization: Bearer <tok
167
171
  - `run` / `once` — run the loop (continuous or single iteration).
168
172
  - `resume` — clear stale lock/state and restart; `--once` for a single run.
169
173
  - `kill` — SIGTERM the running loop and mark state error.
170
- - `status` — show current state and outstanding TODO count.
174
+ - `status` — show current state.
171
175
  - `sessions` — list terminal sessions (server-backed when available).
172
176
  - `stop-session` — stop a terminal session by repo (`--repo`) or id (`--session`).
173
177
  - `log` — view logs (tail or specific run).
174
- - `edit` — open TODO/PROGRESS/OPINIONS/SPEC in `$EDITOR`.
175
- - `ingest-spec` — generate TODO/PROGRESS/OPINIONS from SPEC using Codex (use `--force` to overwrite).
176
- - `clear-docs` — reset TODO/PROGRESS/OPINIONS to empty templates (type CLEAR to confirm).
177
- - `snapshot` — generate/update `.codex-autorunner/SNAPSHOT.md` (incremental by default when one exists; use `--from-scratch` to regenerate).
178
+ - `edit` — open `active_context|decisions|spec` in `$EDITOR`.
178
179
  - `serve` — start the HTTP API (FastAPI) on host/port from config (defaults 127.0.0.1:4173).
179
180
 
180
- ## Snapshot (repo briefing)
181
- - Web UI: open the Snapshot tab. If no snapshot exists, you’ll see “Generate snapshot”; otherwise you’ll see “Update snapshot (incremental)” and “Regenerate snapshot (from scratch)”, plus “Copy to clipboard”.
182
- - CLI: `codex-autorunner snapshot` (or `car snapshot`) writes `.codex-autorunner/SNAPSHOT.md` and `.codex-autorunner/snapshot_state.json`.
183
-
184
181
  ## Star history
185
182
  [![Star History Chart](https://api.star-history.com/svg?repos=Git-on-my-level/codex-autorunner&type=Date)](https://star-history.com/#Git-on-my-level/codex-autorunner&Date)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codex-autorunner"
3
- version = "0.1.2"
3
+ version = "1.0.0"
4
4
  description = "Codex autorunner CLI per DESIGN-V1"
5
5
  readme = "README.md"
6
6
  license = {file = "LICENSE"}
@@ -86,6 +86,11 @@ markers = [
86
86
  "integration: marks tests as integration tests that require external dependencies (deselect with '-m \"not integration\"')",
87
87
  "timeout(seconds): per-test timeout (provided by pytest-timeout)",
88
88
  ]
89
+ filterwarnings = [
90
+ # Cancelled auto-restart tasks can emit noisy unraisable warnings when the event
91
+ # loop shuts down; we explicitly clean these up, so silence the residual notice.
92
+ "ignore::pytest.PytestUnraisableExceptionWarning",
93
+ ]
89
94
 
90
95
  [tool.ruff]
91
96
  line-length = 88
@@ -0,0 +1,4 @@
1
+ from .cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()
@@ -4,6 +4,7 @@ import asyncio
4
4
  import dataclasses
5
5
  import json
6
6
  import logging
7
+ import re
7
8
  from typing import Any, AsyncIterator, Iterable, Optional
8
9
 
9
10
  import httpx
@@ -48,7 +49,18 @@ def _normalize_sse_event(event: SSEEvent) -> SSEEvent:
48
49
  payload_obj = None
49
50
 
50
51
  if isinstance(payload_obj, dict) and isinstance(payload_obj.get("payload"), dict):
51
- payload_obj = payload_obj["payload"]
52
+ outer = payload_obj
53
+ inner = dict(outer.get("payload") or {})
54
+ if "type" not in inner and isinstance(outer.get("type"), str):
55
+ inner["type"] = outer["type"]
56
+ for key in ("sessionID", "sessionId", "session_id"):
57
+ if key in outer and key not in inner:
58
+ inner[key] = outer[key]
59
+ if "session" in outer and "session" not in inner:
60
+ inner["session"] = outer["session"]
61
+ if "properties" in outer and "properties" not in inner:
62
+ inner["properties"] = outer["properties"]
63
+ payload_obj = inner
52
64
 
53
65
  if isinstance(payload_obj, dict):
54
66
  payload_type = payload_obj.get("type")
@@ -505,49 +517,70 @@ class OpenCodeClient:
505
517
 
506
518
  async def fetch_openapi_spec(self) -> dict[str, Any]:
507
519
  """Fetch OpenAPI spec from /doc endpoint for capability negotiation."""
508
- async with self._client.stream("GET", "/doc") as response:
509
- response.raise_for_status()
510
- content = response.content
511
- try:
512
- spec = json.loads(content) if content else {}
513
- log_event(
514
- self._logger,
515
- logging.INFO,
516
- "opencode.openapi.fetched",
517
- paths=len(spec.get("paths", {})) if isinstance(spec, dict) else 0,
518
- has_components=(
519
- "components" in spec if isinstance(spec, dict) else False
520
- ),
521
- )
522
- return spec
523
- except Exception as exc:
524
- log_event(
525
- self._logger,
526
- logging.WARNING,
527
- "opencode.openapi.parse_failed",
528
- exc=exc,
529
- )
530
- raise OpenCodeProtocolError(
531
- f"Failed to parse OpenAPI spec: {exc}",
532
- status_code=response.status_code,
533
- content_type=(
534
- response.headers.get("content-type") if response else None
535
- ),
536
- ) from exc
520
+ response = await self._client.get("/doc")
521
+ response.raise_for_status()
522
+ content = response.content
523
+ try:
524
+ spec = json.loads(content) if content else {}
525
+ log_event(
526
+ self._logger,
527
+ logging.INFO,
528
+ "opencode.openapi.fetched",
529
+ paths=len(spec.get("paths", {})) if isinstance(spec, dict) else 0,
530
+ has_components=(
531
+ "components" in spec if isinstance(spec, dict) else False
532
+ ),
533
+ )
534
+ return spec
535
+ except Exception as exc:
536
+ log_event(
537
+ self._logger,
538
+ logging.WARNING,
539
+ "opencode.openapi.parse_failed",
540
+ exc=exc,
541
+ )
542
+ raise OpenCodeProtocolError(
543
+ f"Failed to parse OpenAPI spec: {exc}",
544
+ status_code=response.status_code,
545
+ content_type=(
546
+ response.headers.get("content-type") if response else None
547
+ ),
548
+ ) from exc
537
549
 
538
550
  def has_endpoint(
539
551
  self, openapi_spec: dict[str, Any], method: str, path: str
540
552
  ) -> bool:
541
- """Check if endpoint is available in OpenAPI spec."""
553
+ """Check if endpoint is available in OpenAPI spec.
554
+
555
+ The OpenAPI spec sometimes uses different template parameter names (e.g.,
556
+ `{sessionID}` vs `{session_id}`). We normalize templates before matching so
557
+ capability detection does not depend on placeholder spelling.
558
+ """
542
559
  if not isinstance(openapi_spec, dict):
543
560
  return False
544
561
  paths = openapi_spec.get("paths", {})
545
562
  if not isinstance(paths, dict):
546
563
  return False
547
- path_info = paths.get(path)
548
- if not isinstance(path_info, dict):
549
- return False
550
- return method in path_info
564
+
565
+ target = _normalize_template_path(path)
566
+ method = method.lower()
567
+
568
+ for candidate_path, info in paths.items():
569
+ if not isinstance(info, dict):
570
+ continue
571
+ if _normalize_template_path(candidate_path) != target:
572
+ continue
573
+ if method in info:
574
+ return True
575
+ return False
576
+
577
+
578
+ def _normalize_template_path(path: str) -> str:
579
+ """Collapse template placeholders to a canonical form.
580
+
581
+ Example: `/session/{sessionID}/prompt_async` -> `/session/{}/prompt_async`
582
+ """
583
+ return re.sub(r"{[^/]+}", "{}", path)
551
584
 
552
585
 
553
586
  __all__ = ["OpenCodeClient", "OpenCodeProtocolError", "OpenCodeApiProfile"]
@@ -66,11 +66,6 @@ class OpenCodeEventFormatter:
66
66
  for line in complete_lines:
67
67
  if line.strip():
68
68
  lines.append(f"**{line.strip()}**")
69
-
70
- remaining = coalescer.get_buffer()
71
- if remaining and remaining.strip():
72
- lines.append(f"**{remaining.strip()}**")
73
- coalescer.clear()
74
69
  return lines
75
70
 
76
71
  def _format_tool_part(self, part: dict[str, Any]) -> list[str]:
@@ -120,6 +115,27 @@ class OpenCodeEventFormatter:
120
115
  lines.append("exec")
121
116
  lines.append(f"tool: {tool_name}")
122
117
 
118
+ input_preview: Optional[str] = None
119
+ for key in ("input", "command", "cmd", "script"):
120
+ value = part.get(key)
121
+ if isinstance(value, str) and value.strip():
122
+ input_preview = value.strip()
123
+ break
124
+ if input_preview is None:
125
+ args = part.get("args") or part.get("arguments") or part.get("params")
126
+ if isinstance(args, dict):
127
+ for key in ("command", "cmd", "script", "input"):
128
+ value = args.get(key)
129
+ if isinstance(value, str) and value.strip():
130
+ input_preview = value.strip()
131
+ break
132
+ elif isinstance(args, str) and args.strip():
133
+ input_preview = args.strip()
134
+ if input_preview:
135
+ if len(input_preview) > 240:
136
+ input_preview = input_preview[:240] + "…"
137
+ lines.append(f"input: {input_preview}")
138
+
123
139
  return lines
124
140
 
125
141
  def _format_patch_part(self, part: dict[str, Any]) -> list[str]:
@@ -112,6 +112,7 @@ async def run_opencode_prompt(
112
112
  client,
113
113
  session_id=session_id,
114
114
  workspace_path=config.workspace_root,
115
+ model_payload=model_payload,
115
116
  permission_policy=permission_policy,
116
117
  should_stop=should_stop,
117
118
  ready_event=ready_event,
@@ -15,6 +15,7 @@ from typing import (
15
15
  Callable,
16
16
  MutableMapping,
17
17
  Optional,
18
+ cast,
18
19
  )
19
20
 
20
21
  import httpx
@@ -127,17 +128,19 @@ def extract_session_id(
127
128
  return value
128
129
  properties = payload.get("properties")
129
130
  if isinstance(properties, dict):
130
- value = properties.get("sessionID")
131
- if isinstance(value, str) and value:
132
- return value
133
- part = properties.get("part")
134
- if isinstance(part, dict):
135
- value = part.get("sessionID")
131
+ for key in ("sessionID", "sessionId", "session_id"):
132
+ value = properties.get(key)
136
133
  if isinstance(value, str) and value:
137
134
  return value
135
+ part = properties.get("part")
136
+ if isinstance(part, dict):
137
+ for key in ("sessionID", "sessionId", "session_id"):
138
+ value = part.get(key)
139
+ if isinstance(value, str) and value:
140
+ return value
138
141
  session = payload.get("session")
139
142
  if isinstance(session, dict):
140
- return extract_session_id(session, allow_fallback_id=allow_fallback_id)
143
+ return extract_session_id(session, allow_fallback_id=True)
141
144
  return None
142
145
 
143
146
 
@@ -676,7 +679,7 @@ async def opencode_missing_env(
676
679
  providers = [entry for entry in payload if isinstance(entry, dict)]
677
680
  for provider in providers:
678
681
  pid = provider.get("id") or provider.get("providerID")
679
- if pid != provider_id:
682
+ if not pid or pid != provider_id:
680
683
  continue
681
684
  if _provider_has_auth(pid, workspace_root):
682
685
  return []
@@ -732,6 +735,7 @@ async def collect_opencode_output_from_events(
732
735
  events: Optional[AsyncIterator[SSEEvent]] = None,
733
736
  *,
734
737
  session_id: str,
738
+ model_payload: Optional[dict[str, str]] = None,
735
739
  progress_session_ids: Optional[set[str]] = None,
736
740
  permission_policy: str = PERMISSION_ALLOW,
737
741
  permission_handler: Optional[PermissionHandler] = None,
@@ -759,13 +763,16 @@ async def collect_opencode_output_from_events(
759
763
  last_usage_total: Optional[int] = None
760
764
  last_context_window: Optional[int] = None
761
765
  part_types: dict[str, str] = {}
762
- seen_question_request_ids: set[tuple[str, str]] = set()
766
+ seen_question_request_ids: set[tuple[Optional[str], str]] = set()
763
767
  logged_permission_errors: set[str] = set()
764
768
  normalized_question_policy = _normalize_question_policy(question_policy)
765
769
  logger = logging.getLogger(__name__)
766
770
  providers_cache: Optional[list[dict[str, Any]]] = None
767
771
  context_window_cache: dict[str, Optional[int]] = {}
768
772
  session_model_ids: Optional[tuple[Optional[str], Optional[str]]] = None
773
+ default_model_ids = (
774
+ _extract_model_ids(model_payload) if isinstance(model_payload, dict) else None
775
+ )
769
776
 
770
777
  def _message_id_from_info(info: Any) -> Optional[str]:
771
778
  if not isinstance(info, dict):
@@ -843,15 +850,19 @@ async def collect_opencode_output_from_events(
843
850
  nonlocal session_model_ids
844
851
  if session_model_ids is not None:
845
852
  return session_model_ids
846
- if session_fetcher is None:
847
- session_model_ids = (None, None)
848
- return session_model_ids
849
- try:
850
- payload = await session_fetcher()
851
- except Exception:
852
- session_model_ids = (None, None)
853
- return session_model_ids
854
- session_model_ids = _extract_model_ids(payload)
853
+ resolved_ids: Optional[tuple[Optional[str], Optional[str]]] = None
854
+ if session_fetcher is not None:
855
+ try:
856
+ payload = await session_fetcher()
857
+ resolved_ids = _extract_model_ids(payload)
858
+ except Exception:
859
+ resolved_ids = None
860
+ # If we failed to resolve model ids from the session (including the empty
861
+ # tuple case), fall back to the caller-provided model payload so we can
862
+ # still backfill usage metadata.
863
+ if not resolved_ids or all(value is None for value in resolved_ids):
864
+ resolved_ids = default_model_ids
865
+ session_model_ids = resolved_ids or (None, None)
855
866
  return session_model_ids
856
867
 
857
868
  async def _resolve_context_window_from_providers(
@@ -946,7 +957,7 @@ async def collect_opencode_output_from_events(
946
957
  await aclose()
947
958
 
948
959
  stream_iter = _new_stream().__aiter__()
949
- last_event_at = time.monotonic()
960
+ last_relevant_event_at = time.monotonic()
950
961
  last_primary_completion_at: Optional[float] = None
951
962
  reconnect_attempts = 0
952
963
  can_reconnect = (
@@ -981,6 +992,7 @@ async def collect_opencode_output_from_events(
981
992
  session_id=session_id,
982
993
  exc=exc,
983
994
  )
995
+ idle_seconds = now - last_relevant_event_at
984
996
  if _status_is_idle(status_type):
985
997
  log_event(
986
998
  logger,
@@ -988,7 +1000,7 @@ async def collect_opencode_output_from_events(
988
1000
  "opencode.stream.stalled.session_idle",
989
1001
  session_id=session_id,
990
1002
  status_type=status_type,
991
- idle_seconds=now - last_event_at,
1003
+ idle_seconds=idle_seconds,
992
1004
  )
993
1005
  if not text_parts and pending_text:
994
1006
  _flush_all_pending_text()
@@ -1000,7 +1012,7 @@ async def collect_opencode_output_from_events(
1000
1012
  "opencode.stream.stalled.after_completion",
1001
1013
  session_id=session_id,
1002
1014
  status_type=status_type,
1003
- idle_seconds=now - last_event_at,
1015
+ idle_seconds=idle_seconds,
1004
1016
  )
1005
1017
  if not can_reconnect:
1006
1018
  break
@@ -1015,7 +1027,7 @@ async def collect_opencode_output_from_events(
1015
1027
  logging.WARNING,
1016
1028
  "opencode.stream.stalled.reconnecting",
1017
1029
  session_id=session_id,
1018
- idle_seconds=now - last_event_at,
1030
+ idle_seconds=idle_seconds,
1019
1031
  backoff_seconds=backoff,
1020
1032
  status_type=status_type,
1021
1033
  attempts=reconnect_attempts,
@@ -1023,21 +1035,86 @@ async def collect_opencode_output_from_events(
1023
1035
  await _close_stream(stream_iter)
1024
1036
  await asyncio.sleep(backoff)
1025
1037
  stream_iter = _new_stream().__aiter__()
1038
+ last_relevant_event_at = now
1026
1039
  continue
1027
- last_event_at = time.monotonic()
1040
+ now = time.monotonic()
1028
1041
  raw = event.data or ""
1029
1042
  try:
1030
1043
  payload = json.loads(raw) if raw else {}
1031
1044
  except json.JSONDecodeError:
1032
1045
  payload = {}
1033
1046
  event_session_id = extract_session_id(payload)
1034
- if not event_session_id:
1035
- continue
1036
- if progress_session_ids is None:
1037
- if event_session_id != session_id:
1038
- continue
1039
- elif event_session_id not in progress_session_ids:
1047
+ is_relevant = False
1048
+ if event_session_id:
1049
+ if progress_session_ids is None:
1050
+ is_relevant = event_session_id == session_id
1051
+ else:
1052
+ is_relevant = event_session_id in progress_session_ids
1053
+ if not is_relevant:
1054
+ if (
1055
+ stall_timeout_seconds is not None
1056
+ and now - last_relevant_event_at > stall_timeout_seconds
1057
+ ):
1058
+ idle_seconds = now - last_relevant_event_at
1059
+ last_relevant_event_at = now
1060
+ status_type = None
1061
+ if session_fetcher is not None:
1062
+ try:
1063
+ payload = await session_fetcher()
1064
+ status_type = _extract_status_type(payload)
1065
+ except Exception as exc:
1066
+ log_event(
1067
+ logger,
1068
+ logging.WARNING,
1069
+ "opencode.session.poll_failed",
1070
+ session_id=session_id,
1071
+ exc=exc,
1072
+ )
1073
+ if _status_is_idle(status_type):
1074
+ log_event(
1075
+ logger,
1076
+ logging.INFO,
1077
+ "opencode.stream.stalled.session_idle",
1078
+ session_id=session_id,
1079
+ status_type=status_type,
1080
+ idle_seconds=idle_seconds,
1081
+ )
1082
+ if not text_parts and pending_text:
1083
+ _flush_all_pending_text()
1084
+ break
1085
+ if last_primary_completion_at is not None:
1086
+ log_event(
1087
+ logger,
1088
+ logging.INFO,
1089
+ "opencode.stream.stalled.after_completion",
1090
+ session_id=session_id,
1091
+ status_type=status_type,
1092
+ idle_seconds=idle_seconds,
1093
+ )
1094
+ if not can_reconnect:
1095
+ break
1096
+ backoff_index = min(
1097
+ reconnect_attempts,
1098
+ len(_OPENCODE_STREAM_RECONNECT_BACKOFF_SECONDS) - 1,
1099
+ )
1100
+ backoff = _OPENCODE_STREAM_RECONNECT_BACKOFF_SECONDS[backoff_index]
1101
+ reconnect_attempts += 1
1102
+ log_event(
1103
+ logger,
1104
+ logging.WARNING,
1105
+ "opencode.stream.stalled.reconnecting",
1106
+ session_id=session_id,
1107
+ idle_seconds=idle_seconds,
1108
+ backoff_seconds=backoff,
1109
+ status_type=status_type,
1110
+ attempts=reconnect_attempts,
1111
+ )
1112
+ await _close_stream(stream_iter)
1113
+ await asyncio.sleep(backoff)
1114
+ stream_iter = _new_stream().__aiter__()
1040
1115
  continue
1116
+ last_relevant_event_at = now
1117
+ reconnect_attempts = 0
1041
1118
  is_primary_session = event_session_id == session_id
1042
1119
  if event.event == "question.asked":
1043
1120
  request_id, props = _extract_question_request(payload)
@@ -1419,6 +1496,7 @@ async def collect_opencode_output(
1419
1496
  *,
1420
1497
  session_id: str,
1421
1498
  workspace_path: str,
1499
+ model_payload: Optional[dict[str, str]] = None,
1422
1500
  progress_session_ids: Optional[set[str]] = None,
1423
1501
  permission_policy: str = PERMISSION_ALLOW,
1424
1502
  permission_handler: Optional[PermissionHandler] = None,
@@ -1427,6 +1505,7 @@ async def collect_opencode_output(
1427
1505
  should_stop: Optional[Callable[[], bool]] = None,
1428
1506
  ready_event: Optional[Any] = None,
1429
1507
  part_handler: Optional[PartHandler] = None,
1508
+ stall_timeout_seconds: Optional[float] = _OPENCODE_STREAM_STALL_TIMEOUT_SECONDS,
1430
1509
  ) -> OpenCodeTurnOutput:
1431
1510
  async def _respond(request_id: str, reply: str) -> None:
1432
1511
  await client.respond_permission(request_id=request_id, reply=reply)
@@ -1438,14 +1517,21 @@ async def collect_opencode_output(
1438
1517
  await client.reject_question(request_id)
1439
1518
 
1440
1519
  def _stream_factory() -> AsyncIterator[SSEEvent]:
1441
- return client.stream_events(directory=workspace_path, ready_event=ready_event)
1520
+ return cast(
1521
+ AsyncIterator[SSEEvent],
1522
+ client.stream_events(directory=workspace_path, ready_event=ready_event),
1523
+ )
1442
1524
 
1443
1525
  async def _fetch_session() -> Any:
1444
1526
  statuses = await client.session_status(directory=workspace_path)
1445
1527
  if isinstance(statuses, dict):
1446
1528
  session_status = statuses.get(session_id)
1529
+ if session_status is None:
1530
+ return {"status": {"type": "idle"}}
1447
1531
  if isinstance(session_status, dict):
1448
1532
  return {"status": session_status}
1533
+ if isinstance(session_status, str):
1534
+ return {"status": session_status}
1449
1535
  return {"status": {}}
1450
1536
 
1451
1537
  async def _fetch_providers() -> Any:
@@ -1465,8 +1551,10 @@ async def collect_opencode_output(
1465
1551
  reject_question=_reject_question,
1466
1552
  part_handler=part_handler,
1467
1553
  event_stream_factory=_stream_factory,
1554
+ model_payload=model_payload,
1468
1555
  session_fetcher=_fetch_session,
1469
1556
  provider_fetcher=_fetch_providers,
1557
+ stall_timeout_seconds=stall_timeout_seconds,
1470
1558
  )
1471
1559
 
1472
1560