local-operator 0.45.2__tar.gz → 0.45.4__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 (448) hide show
  1. {local_operator-0.45.2 → local_operator-0.45.4}/PKG-INFO +1 -1
  2. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/api.py +16 -0
  3. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/pass_.py +26 -4
  4. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/pruning.py +58 -1
  5. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/thresholds.py +170 -3
  6. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/tokens.py +297 -0
  7. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/incidents.py +22 -2
  8. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/discovery.py +193 -6
  9. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/registry.py +61 -0
  10. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/controller.py +30 -0
  11. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/failover.py +72 -0
  12. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/frontend_state.py +7 -0
  13. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/session.py +503 -7
  14. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/settings_io.py +33 -0
  15. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/app.py +8 -0
  16. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/model_picker.py +58 -7
  17. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/settings_view.py +1 -1
  18. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/PKG-INFO +1 -1
  19. {local_operator-0.45.2 → local_operator-0.45.4}/pyproject.toml +1 -1
  20. {local_operator-0.45.2 → local_operator-0.45.4}/LICENSE +0 -0
  21. {local_operator-0.45.2 → local_operator-0.45.4}/README.md +0 -0
  22. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/__init__.py +0 -0
  23. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_profiles.py +0 -0
  24. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/architect.md +0 -0
  25. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/coder.md +0 -0
  26. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/designer.md +0 -0
  27. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/manager.md +0 -0
  28. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/reviewer.md +0 -0
  29. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agent_seeds/scout.md +0 -0
  30. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/agents.py +0 -0
  31. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/analytics/__init__.py +0 -0
  32. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/analytics/model.py +0 -0
  33. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/analytics/recorder.py +0 -0
  34. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/analytics/store.py +0 -0
  35. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/ansi.py +0 -0
  36. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/bootstrap.py +0 -0
  37. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/__init__.py +0 -0
  38. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/backend.py +0 -0
  39. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/daemon.py +0 -0
  40. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/gen_ts.py +0 -0
  41. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/install.py +0 -0
  42. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/protocol.py +0 -0
  43. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/browser_bridge/state.py +0 -0
  44. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/callback_page.py +0 -0
  45. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/cli.py +0 -0
  46. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/cli_style.py +0 -0
  47. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/__init__.py +0 -0
  48. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/_http.py +0 -0
  49. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/fal.py +0 -0
  50. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/google_client.py +0 -0
  51. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/ollama.py +0 -0
  52. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/openrouter.py +0 -0
  53. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/radient.py +0 -0
  54. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/serpapi.py +0 -0
  55. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clients/tavily.py +0 -0
  56. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/clipboard.py +0 -0
  57. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/__init__.py +0 -0
  58. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/advisor.py +0 -0
  59. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/cutpoint.py +0 -0
  60. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/marker.py +0 -0
  61. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/png.py +0 -0
  62. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/compaction/snapcompact.py +0 -0
  63. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/config.py +0 -0
  64. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/config_watch.py +0 -0
  65. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/console.py +0 -0
  66. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/context_files.py +0 -0
  67. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/credentials.py +0 -0
  68. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/env.py +0 -0
  69. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/__init__.py +0 -0
  70. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/__init__.py +0 -0
  71. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/api.py +0 -0
  72. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/discovery.py +0 -0
  73. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/rpc.py +0 -0
  74. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/supervisor.py +0 -0
  75. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/adapters/worker.py +0 -0
  76. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/evidence/__init__.py +0 -0
  77. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/evidence/media.py +0 -0
  78. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/evidence/models.py +0 -0
  79. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/evidence/store.py +0 -0
  80. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/evidence/verify.py +0 -0
  81. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/lifecycle.py +0 -0
  82. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/protocol.py +0 -0
  83. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/receipts.py +0 -0
  84. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/__init__.py +0 -0
  85. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/durable_root.py +0 -0
  86. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/episode.py +0 -0
  87. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/guards.py +0 -0
  88. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/host_secrets.py +0 -0
  89. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/model.py +0 -0
  90. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/provider_client.py +0 -0
  91. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/rescue_sweep.py +0 -0
  92. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/responder.py +0 -0
  93. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/route_ids.py +0 -0
  94. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/evaluation/runner/secrets.py +0 -0
  95. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/exec_mode.py +0 -0
  96. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/exec_worker.py +0 -0
  97. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/fork.py +0 -0
  98. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/__init__.py +0 -0
  99. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/agents/GUIDE.md +0 -0
  100. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/browser/GUIDE.md +0 -0
  101. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/configuration/GUIDE.md +0 -0
  102. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/discovery.py +0 -0
  103. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/extensions/GUIDE.md +0 -0
  104. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/failover/GUIDE.md +0 -0
  105. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/mcp/GUIDE.md +0 -0
  106. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/mobile/GUIDE.md +0 -0
  107. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/peer-messaging/GUIDE.md +0 -0
  108. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/guides/teams/GUIDE.md +0 -0
  109. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/__init__.py +0 -0
  110. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/approval.py +0 -0
  111. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/comms.py +0 -0
  112. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/intent.py +0 -0
  113. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/jobs.py +0 -0
  114. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/loop.py +0 -0
  115. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/subagent.py +0 -0
  116. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/types.py +0 -0
  117. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/harness/wake.py +0 -0
  118. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/headless_print.py +0 -0
  119. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/helpers.py +0 -0
  120. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/imaging.py +0 -0
  121. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/jobs.py +0 -0
  122. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/jsonl.py +0 -0
  123. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/logger.py +0 -0
  124. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/__init__.py +0 -0
  125. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/auth.py +0 -0
  126. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/config.py +0 -0
  127. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/manager.py +0 -0
  128. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/resources.py +0 -0
  129. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/tool_bridge.py +0 -0
  130. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mcp/tool_cache.py +0 -0
  131. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/media.py +0 -0
  132. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/__init__.py +0 -0
  133. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/attach_client.py +0 -0
  134. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/auth.py +0 -0
  135. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/child.py +0 -0
  136. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/command_reservation.py +0 -0
  137. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/daemon.py +0 -0
  138. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/durable.py +0 -0
  139. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/install.py +0 -0
  140. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/owned.py +0 -0
  141. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/peer_client.py +0 -0
  142. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/peer_send.py +0 -0
  143. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/projection.py +0 -0
  144. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/registrant.py +0 -0
  145. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/registry.py +0 -0
  146. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/resources.py +0 -0
  147. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/seen.py +0 -0
  148. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/service.py +0 -0
  149. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/static/mark.png +0 -0
  150. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/tui_handle.py +0 -0
  151. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/types.py +0 -0
  152. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/dist/assets/index-CuRNCaFt.css +0 -0
  153. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/dist/assets/index-DkiusxCg.js +0 -0
  154. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/dist/index.html +0 -0
  155. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/dist/mark.png +0 -0
  156. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/index.html +0 -0
  157. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/package.json +0 -0
  158. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/pnpm-lock.yaml +0 -0
  159. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/pnpm-workspace.yaml +0 -0
  160. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/public/mark.png +0 -0
  161. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/scripts/generate-theme-css.mjs +0 -0
  162. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/scripts/inline-mark.mjs +0 -0
  163. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/scripts/palette-source.mjs +0 -0
  164. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/agent-view.interaction.test.tsx +0 -0
  165. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/agent-view.test.ts +0 -0
  166. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/api.ts +0 -0
  167. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/app.tsx +0 -0
  168. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/agents-sheet.tsx +0 -0
  169. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/composer.tsx +0 -0
  170. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/markdown.tsx +0 -0
  171. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/model-sheet.tsx +0 -0
  172. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/pending-card.tsx +0 -0
  173. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/row-boundary.tsx +0 -0
  174. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/spinner.tsx +0 -0
  175. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/subagents-panel.tsx +0 -0
  176. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/todos-panel.tsx +0 -0
  177. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/tool-row.tsx +0 -0
  178. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/transcript.tsx +0 -0
  179. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/ui/button.tsx +0 -0
  180. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/ui/chip.tsx +0 -0
  181. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/ui/disclosure.tsx +0 -0
  182. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/ui/sheet.tsx +0 -0
  183. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/components/working-line.tsx +0 -0
  184. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/continuation-command.test.ts +0 -0
  185. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/continuation-command.ts +0 -0
  186. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/detail-loader.test.ts +0 -0
  187. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/detail-loader.ts +0 -0
  188. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/lib/cn.ts +0 -0
  189. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/lib/format.ts +0 -0
  190. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/lib/mark.ts +0 -0
  191. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/main.tsx +0 -0
  192. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/past-sessions.fork.test.tsx +0 -0
  193. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/private-storage.test.ts +0 -0
  194. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/private-storage.ts +0 -0
  195. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/router.test.ts +0 -0
  196. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/router.ts +0 -0
  197. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/screens/agent-view.tsx +0 -0
  198. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/screens/new-session.tsx +0 -0
  199. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/screens/past-sessions.tsx +0 -0
  200. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/screens/session-list.tsx +0 -0
  201. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/screens/session-view.tsx +0 -0
  202. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/session-list.unread.test.tsx +0 -0
  203. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/session-view.pending.test.tsx +0 -0
  204. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/session-view.seen.test.tsx +0 -0
  205. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/store.test.ts +0 -0
  206. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/store.ts +0 -0
  207. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/store.unread.test.ts +0 -0
  208. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/styles/index.css +0 -0
  209. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/styles/themes.generated.css +0 -0
  210. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/test-setup.ts +0 -0
  211. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/theme.ts +0 -0
  212. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/alucard.ts +0 -0
  213. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/ayu-light.ts +0 -0
  214. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/ayu-mirage.ts +0 -0
  215. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/ayu.ts +0 -0
  216. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/catppuccin-frappe.ts +0 -0
  217. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/catppuccin-macchiato.ts +0 -0
  218. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/dracula.ts +0 -0
  219. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/dune.ts +0 -0
  220. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/duskfox.ts +0 -0
  221. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/everforest-light.ts +0 -0
  222. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/everforest.ts +0 -0
  223. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/gruvbox-light.ts +0 -0
  224. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/iceberg.ts +0 -0
  225. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/kanagawa-lotus.ts +0 -0
  226. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/kanagawa-wave.ts +0 -0
  227. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/local-operator.ts +0 -0
  228. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/monokai.ts +0 -0
  229. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/neon.ts +0 -0
  230. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/nightfox.ts +0 -0
  231. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/obsidian.ts +0 -0
  232. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/one-light.ts +0 -0
  233. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/palenight.ts +0 -0
  234. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/palette-contract.ts +0 -0
  235. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/radient.ts +0 -0
  236. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/rose-pine.ts +0 -0
  237. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/sage.ts +0 -0
  238. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/synth.ts +0 -0
  239. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/tokyo-night-day.ts +0 -0
  240. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/themes/tokyo-night.ts +0 -0
  241. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/src/types.ts +0 -0
  242. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/tsconfig.app.json +0 -0
  243. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/tsconfig.json +0 -0
  244. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/tsconfig.node.json +0 -0
  245. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/mobile/web/vite.config.ts +0 -0
  246. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/__init__.py +0 -0
  247. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/catalogue.py +0 -0
  248. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/configure.py +0 -0
  249. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/defaults.py +0 -0
  250. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/effort.py +0 -0
  251. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/effort_classifier.py +0 -0
  252. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/ids.py +0 -0
  253. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/naming.py +0 -0
  254. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/model/prices.py +0 -0
  255. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/__init__.py +0 -0
  256. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/broadcast.py +0 -0
  257. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/cmux.py +0 -0
  258. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/markers.py +0 -0
  259. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/registry.py +0 -0
  260. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/multiplexer/types.py +0 -0
  261. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/optional.py +0 -0
  262. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/org_chart.py +0 -0
  263. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/paths.py +0 -0
  264. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/proc.py +0 -0
  265. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/prompts_api.py +0 -0
  266. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/prompts_md/__init__.py +0 -0
  267. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/prompts_md/compaction_summary.md +0 -0
  268. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/prompts_md/edit_file_instructions.md +0 -0
  269. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/prompts_md/system.md +0 -0
  270. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/__init__.py +0 -0
  271. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/auth_cli.py +0 -0
  272. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/auth_store.py +0 -0
  273. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/clients.py +0 -0
  274. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/login_defaults.py +0 -0
  275. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/__init__.py +0 -0
  276. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/anthropic.py +0 -0
  277. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/callback_server.py +0 -0
  278. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/device_code.py +0 -0
  279. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/kimi.py +0 -0
  280. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/openai.py +0 -0
  281. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/pkce.py +0 -0
  282. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/qwencloud.py +0 -0
  283. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/radient.py +0 -0
  284. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/xai.py +0 -0
  285. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/oauth/zai.py +0 -0
  286. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/registry.py +0 -0
  287. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/usage.py +0 -0
  288. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/providers/usage_cache.py +0 -0
  289. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/reexec.py +0 -0
  290. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/resume.py +0 -0
  291. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/scheduler_service.py +0 -0
  292. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/__init__.py +0 -0
  293. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/app.py +0 -0
  294. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/dependencies.py +0 -0
  295. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/generate_openapi.py +0 -0
  296. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/models/__init__.py +0 -0
  297. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/models/schemas.py +0 -0
  298. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/openapi.py +0 -0
  299. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/__init__.py +0 -0
  300. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/agents.py +0 -0
  301. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/chat.py +0 -0
  302. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/config.py +0 -0
  303. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/credentials.py +0 -0
  304. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/health.py +0 -0
  305. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/jobs.py +0 -0
  306. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/models.py +0 -0
  307. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/schedules.py +0 -0
  308. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/speech.py +0 -0
  309. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/sse.py +0 -0
  310. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/static.py +0 -0
  311. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/transcription.py +0 -0
  312. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/routes/websockets.py +0 -0
  313. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/__init__.py +0 -0
  314. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/attachment_utils.py +0 -0
  315. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/event_broker.py +0 -0
  316. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/job_processor_queue.py +0 -0
  317. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/operator.py +0 -0
  318. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/speech_utils.py +0 -0
  319. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/sse.py +0 -0
  320. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/sse_publisher.py +0 -0
  321. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/server/utils/websocket_manager.py +0 -0
  322. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/__init__.py +0 -0
  323. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/attachments.py +0 -0
  324. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/goal.py +0 -0
  325. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/mcp_status.py +0 -0
  326. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/naming.py +0 -0
  327. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/peer.py +0 -0
  328. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/protocol.py +0 -0
  329. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/remote.py +0 -0
  330. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/retention.py +0 -0
  331. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/__init__.py +0 -0
  332. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/control.py +0 -0
  333. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/owned.py +0 -0
  334. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/process.py +0 -0
  335. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/registry.py +0 -0
  336. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/server.py +0 -0
  337. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/runtime/types.py +0 -0
  338. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/search_index.py +0 -0
  339. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session/transcript.py +0 -0
  340. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session_factory.py +0 -0
  341. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/session_lease.py +0 -0
  342. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/__init__.py +0 -0
  343. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/api.py +0 -0
  344. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/discovery.py +0 -0
  345. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/embeddings.py +0 -0
  346. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/index.py +0 -0
  347. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/invoke.py +0 -0
  348. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/protocol.py +0 -0
  349. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/skills/vectors.py +0 -0
  350. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/__init__.py +0 -0
  351. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/apple.py +0 -0
  352. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/cmux.py +0 -0
  353. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/fallback.py +0 -0
  354. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/ghostty.py +0 -0
  355. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/kitty.py +0 -0
  356. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/policy.py +0 -0
  357. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/registry.py +0 -0
  358. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/types.py +0 -0
  359. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/spawn/wezterm.py +0 -0
  360. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/stream.py +0 -0
  361. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/teams.py +0 -0
  362. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/terminals.py +0 -0
  363. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/__init__.py +0 -0
  364. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/agent_tool.py +0 -0
  365. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/builtin.py +0 -0
  366. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/eval.py +0 -0
  367. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/eval_worker.py +0 -0
  368. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/group_reaper.py +0 -0
  369. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/lsp.py +0 -0
  370. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/registry.py +0 -0
  371. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/spill.py +0 -0
  372. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tools/team_tool.py +0 -0
  373. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/__init__.py +0 -0
  374. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/animation.py +0 -0
  375. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/autocomplete.py +0 -0
  376. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/bindings.py +0 -0
  377. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/copy_targets.py +0 -0
  378. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/costs.py +0 -0
  379. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/events.py +0 -0
  380. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/glyphs.py +0 -0
  381. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/images.py +0 -0
  382. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/local_operator.tcss +0 -0
  383. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/markdown_theme.py +0 -0
  384. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/notify.py +0 -0
  385. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/org_layout.py +0 -0
  386. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/org_render.py +0 -0
  387. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/__init__.py +0 -0
  388. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/classics.py +0 -0
  389. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/companions.py +0 -0
  390. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/lights.py +0 -0
  391. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/modern.py +0 -0
  392. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/nature.py +0 -0
  393. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/neon.py +0 -0
  394. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/radient.py +0 -0
  395. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/palettes/rose_pine.py +0 -0
  396. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/settings.py +0 -0
  397. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/shimmer.py +0 -0
  398. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/terminal_title.py +0 -0
  399. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/theme.py +0 -0
  400. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/__init__.py +0 -0
  401. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/_copy_markdown.py +0 -0
  402. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/analytics_panel.py +0 -0
  403. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/approval.py +0 -0
  404. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/aside_panel.py +0 -0
  405. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/ask_picker.py +0 -0
  406. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/assistant.py +0 -0
  407. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/command_picker.py +0 -0
  408. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/copy_picker.py +0 -0
  409. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/editor.py +0 -0
  410. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/image_block.py +0 -0
  411. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/key_prompt.py +0 -0
  412. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/org_chart_view.py +0 -0
  413. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/overlay.py +0 -0
  414. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/session_picker.py +0 -0
  415. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/status_line.py +0 -0
  416. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/subagent_panel.py +0 -0
  417. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/subagent_view.py +0 -0
  418. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/toast.py +0 -0
  419. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/todo_panel.py +0 -0
  420. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/tool_card.py +0 -0
  421. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/transcript.py +0 -0
  422. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/usage_panel.py +0 -0
  423. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/wake_panel.py +0 -0
  424. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/tui/widgets/welcome.py +0 -0
  425. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/types.py +0 -0
  426. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/update.py +0 -0
  427. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/variables.py +0 -0
  428. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/wakes/__init__.py +0 -0
  429. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/wakes/install.py +0 -0
  430. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/wakes/store.py +0 -0
  431. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/__init__.py +0 -0
  432. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/cli.py +0 -0
  433. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/models.py +0 -0
  434. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/render.py +0 -0
  435. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/service.py +0 -0
  436. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_fetch/tool.py +0 -0
  437. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/__init__.py +0 -0
  438. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/cli.py +0 -0
  439. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/models.py +0 -0
  440. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/providers.py +0 -0
  441. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/service.py +0 -0
  442. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator/web_search/tool.py +0 -0
  443. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/SOURCES.txt +0 -0
  444. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/dependency_links.txt +0 -0
  445. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/entry_points.txt +0 -0
  446. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/requires.txt +0 -0
  447. {local_operator-0.45.2 → local_operator-0.45.4}/local_operator.egg-info/top_level.txt +0 -0
  448. {local_operator-0.45.2 → local_operator-0.45.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: local-operator
3
- Version: 0.45.2
3
+ Version: 0.45.4
4
4
  Summary: A team of proactive AI assistants that can work together behind the scenes to help you get mundane tasks done so you can focus on the fun stuff.
5
5
  Author-email: Damian Tran <damian@gominerva.com>
6
6
  License: MIT License
@@ -50,16 +50,23 @@ from .pruning import (
50
50
  _is_useless,
51
51
  compute_suffix_tokens,
52
52
  prune_tool_outputs,
53
+ shed_frames_to_wire_budget,
53
54
  )
54
55
  from .thresholds import (
56
+ DEFAULT_WIRE_BYTES_BUDGET,
57
+ DEFAULT_WIRE_BYTES_TRIGGER,
55
58
  RECOVERY_BAND,
59
+ WIRE_RECOVERY_BAND,
56
60
  CompactionSettings,
57
61
  cleared_headroom,
62
+ cleared_wire_headroom,
58
63
  compaction_context_tokens,
59
64
  effective_reserve_tokens,
60
65
  resolve_advisor_floor_tokens,
61
66
  resolve_strategy,
62
67
  resolve_threshold_tokens,
68
+ resolve_wire_bytes_budget,
69
+ resolve_wire_bytes_trigger,
63
70
  should_compact,
64
71
  )
65
72
  from .tokens import (
@@ -69,6 +76,7 @@ from .tokens import (
69
76
  clear_estimate_cache,
70
77
  estimate_messages_tokens,
71
78
  estimate_tokens,
79
+ estimate_wire_bytes,
72
80
  history_chars,
73
81
  invalidate_message_cache,
74
82
  messages_tokens_upper_bound,
@@ -87,6 +95,9 @@ __all__ = [
87
95
  "MIN_PRUNE_TOKENS",
88
96
  "PRESERVED_USER_TURN_KEY",
89
97
  "RECOVERY_BAND",
98
+ "WIRE_RECOVERY_BAND",
99
+ "DEFAULT_WIRE_BYTES_BUDGET",
100
+ "DEFAULT_WIRE_BYTES_TRIGGER",
90
101
  "SUMMARIZATION_SYSTEM_PROMPT",
91
102
  "SUPERSEDED_NOTICE",
92
103
  "TOOL_ARGS_MAX_CHARS",
@@ -96,11 +107,13 @@ __all__ = [
96
107
  "build_compaction_prompt",
97
108
  "clear_estimate_cache",
98
109
  "cleared_headroom",
110
+ "cleared_wire_headroom",
99
111
  "compaction_context_tokens",
100
112
  "compute_suffix_tokens",
101
113
  "effective_reserve_tokens",
102
114
  "estimate_messages_tokens",
103
115
  "estimate_tokens",
116
+ "estimate_wire_bytes",
104
117
  "extract_file_ops_from_messages",
105
118
  "extract_preserved_user_turns",
106
119
  "find_cut_point",
@@ -112,11 +125,14 @@ __all__ = [
112
125
  "parse_hint",
113
126
  "prepare_partitions",
114
127
  "prune_tool_outputs",
128
+ "shed_frames_to_wire_budget",
115
129
  "register_invalidator",
116
130
  "render_file_operations",
117
131
  "resolve_advisor_floor_tokens",
118
132
  "resolve_strategy",
119
133
  "resolve_threshold_tokens",
134
+ "resolve_wire_bytes_budget",
135
+ "resolve_wire_bytes_trigger",
120
136
  "serialize_conversation",
121
137
  "should_compact",
122
138
  "summarize_messages",
@@ -39,14 +39,15 @@ from .marker import (
39
39
  build_compaction_marker,
40
40
  render_compaction_marker,
41
41
  )
42
- from .pruning import prune_stale_frames, prune_tool_outputs
42
+ from .pruning import prune_stale_frames, prune_tool_outputs, shed_frames_to_wire_budget
43
43
  from .thresholds import (
44
44
  CompactionSettings,
45
45
  compaction_context_tokens,
46
46
  resolve_strategy,
47
+ resolve_wire_bytes_budget,
47
48
  should_compact,
48
49
  )
49
- from .tokens import estimate_messages_tokens
50
+ from .tokens import estimate_messages_tokens, estimate_wire_bytes
50
51
 
51
52
  logger = logging.getLogger(__name__)
52
53
 
@@ -152,11 +153,32 @@ async def run_compaction_pass(
152
153
  working, frames_dropped = prune_stale_frames(
153
154
  working, keep_recent_frames=settings.keep_recent_frames
154
155
  )
156
+ else:
157
+ # (2b) Byte shed, for the surface that did NOT opt in. A session is
158
+ # not statically one kind or the other — the session this guard was
159
+ # written for was an ordinary chat for hundreds of turns and then
160
+ # started driving a browser, without any config changing — so the
161
+ # honest discriminator is the observed byte pressure, not a static
162
+ # per-surface guess. Under budget this is one cheap scan that changes
163
+ # nothing; over budget the alternative is a request the provider
164
+ # refuses outright, taking every frame with it.
165
+ working, frames_dropped = shed_frames_to_wire_budget(
166
+ working, budget=resolve_wire_bytes_budget(settings)
167
+ )
155
168
 
156
- # (3) Trigger through the single resolver.
169
+ # (3) Trigger through the single resolver. Bytes go in as a second input
170
+ # to the SAME resolver rather than as a second predicate: an image-heavy
171
+ # history can be far under every token threshold and still be too large to
172
+ # send, and two functions free to disagree about when a pass is due is the
173
+ # drift this package forbids.
157
174
  local_estimate = estimate_messages_tokens(working)
158
175
  tokens_before = compaction_context_tokens(provider_context_tokens, local_estimate)
159
- if respect_threshold and not should_compact(tokens_before, model.context_window, settings):
176
+ if respect_threshold and not should_compact(
177
+ tokens_before,
178
+ model.context_window,
179
+ settings,
180
+ wire_bytes=estimate_wire_bytes(working),
181
+ ):
160
182
  return _refused(
161
183
  working,
162
184
  "below-threshold",
@@ -40,7 +40,7 @@ from typing import Any, Sequence
40
40
  from local_operator.harness.types import Content, ImageContent, Message, TextContent
41
41
 
42
42
  from .marker import marker_exists
43
- from .tokens import estimate_tokens, invalidate_message_cache
43
+ from .tokens import estimate_tokens, estimate_wire_bytes, invalidate_message_cache
44
44
 
45
45
  __all__ = [
46
46
  "MIN_PRUNE_TOKENS",
@@ -52,6 +52,7 @@ __all__ = [
52
52
  "count_stale_observations",
53
53
  "prune_stale_frames",
54
54
  "prune_tool_outputs",
55
+ "shed_frames_to_wire_budget",
55
56
  "shed_stale_frames",
56
57
  ]
57
58
 
@@ -157,6 +158,62 @@ def prune_stale_frames(
157
158
  return out, dropped
158
159
 
159
160
 
161
+ def shed_frames_to_wire_budget(
162
+ messages: Sequence[Message], *, budget: int
163
+ ) -> tuple[list[Message], int]:
164
+ """Replace the OLDEST frames with notices until the request fits ``budget``
165
+ bytes, keeping as many recent frames as possible.
166
+
167
+ The last-resort transport guard. Ordinary compaction decides what to keep
168
+ by *context* value; this decides by whether the provider will accept the
169
+ request at all, which is a different and strictly narrower question — so
170
+ it engages only when the payload is already over a ceiling set below the
171
+ provider's cap, and does nothing at all below it. The early return is not
172
+ an optimisation detail: it is the guarantee that every session under
173
+ budget behaves byte-identically to one without this function.
174
+
175
+ Built on :func:`prune_stale_frames` rather than as a second
176
+ frame-dropping primitive, so there is ONE definition of "which frames are
177
+ recent" and one set of copy/identity semantics. That also means no message
178
+ is ever removed — user/assistant alternation and tool pairings survive
179
+ untouched, which a transport guard running on arbitrary history must
180
+ guarantee, since it cannot know what is mid-tool-call.
181
+
182
+ The loop mirrors ``_shed_stale_turns`` in the evaluation runner's provider
183
+ client: walk the keep count DOWN and stop when a step frees nothing.
184
+ Termination is structural — ``keep`` strictly decreases toward 0, and
185
+ ``keep=0`` drops every image there is — so a payload still over budget
186
+ with no images left exits rather than spinning. That residual case is
187
+ real: a text-only history cannot be shed here, and the caller must be
188
+ prepared for "still over" rather than assuming success (this is what the
189
+ byte-side auto-continue band checks).
190
+
191
+ Sheds the FEWEST frames that fit, not a fixed count, because every frame
192
+ dropped is evidence the user may still need. Returns ``(messages,
193
+ frames_dropped)``; ``frames_dropped`` is 0 and the input list is returned
194
+ unchanged when nothing was over budget.
195
+ """
196
+ if budget <= 0:
197
+ return list(messages), 0
198
+ if estimate_wire_bytes(messages) <= budget:
199
+ return list(messages), 0
200
+
201
+ keep = count_frame_messages(messages)
202
+ working = list(messages)
203
+ dropped = 0
204
+ while keep > 0:
205
+ keep -= 1
206
+ candidate, candidate_dropped = prune_stale_frames(messages, keep_recent_frames=keep)
207
+ if candidate_dropped <= dropped:
208
+ # This step freed nothing new; another turn of the loop cannot
209
+ # either, since the keep count only shrinks.
210
+ break
211
+ working, dropped = candidate, candidate_dropped
212
+ if estimate_wire_bytes(working) <= budget:
213
+ break
214
+ return working, dropped
215
+
216
+
160
217
  def compute_suffix_tokens(messages: Sequence[Message]) -> list[int]:
161
218
  """Per-index sum of estimated tokens of all messages strictly AFTER it.
162
219
 
@@ -30,9 +30,15 @@ __all__ = [
30
30
  "DEFAULT_RESERVE_TOKENS",
31
31
  "DEFAULT_THRESHOLD_PERCENT",
32
32
  "DEFAULT_THRESHOLD_TOKENS",
33
+ "DEFAULT_WIRE_BYTES_BUDGET",
34
+ "DEFAULT_WIRE_BYTES_TRIGGER",
33
35
  "CompactionSettings",
34
36
  "RECOVERY_BAND",
37
+ "WIRE_RECOVERY_BAND",
35
38
  "cleared_headroom",
39
+ "cleared_wire_headroom",
40
+ "resolve_wire_bytes_budget",
41
+ "resolve_wire_bytes_trigger",
36
42
  "compaction_context_tokens",
37
43
  "effective_reserve_tokens",
38
44
  "resolve_advisor_floor_tokens",
@@ -58,6 +64,28 @@ DEFAULT_THRESHOLD_PERCENT = 0.80
58
64
  #: when that is a small fraction of a very large window.
59
65
  DEFAULT_THRESHOLD_TOKENS = 600_000
60
66
 
67
+ #: HARD ceiling on the serialized request, in bytes — the number the render
68
+ #: seam sheds frames to satisfy. NOT a token figure; see
69
+ #: :func:`~.tokens.estimate_wire_bytes` for why the two rulers stay apart.
70
+ #:
71
+ #: 24 MB is Anthropic's 32 MB Messages-API cap minus 25% headroom for the
72
+ #: system prompt, the tool schemas, the ~2.2% JSON envelope, and the growth
73
+ #: the NEXT request adds before another guard runs.
74
+ #:
75
+ #: Calibrated against real traffic rather than guessed: a scan of all **4,738
76
+ #: sessions** in a production session store found exactly **one** above 24 MB
77
+ #: (the session that wedged on HTTP 413), two above 16 MB, ten above 8 MB, and
78
+ #: none above 32 MB. So this budget sheds nothing that works today — it fires
79
+ #: only on the shape that was already failing outright.
80
+ DEFAULT_WIRE_BYTES_BUDGET = 24_000_000
81
+
82
+ #: SOFT trigger: fires a real compaction pass (with a summary) well before the
83
+ #: hard budget forces amputation. ~2/3 of the hard budget, which on the
84
+ #: measured store is above every session but the three largest — the point is
85
+ #: that a screenshot-heavy session compacts *properly and early* instead of
86
+ #: surviving by shedding frames at the wall.
87
+ DEFAULT_WIRE_BYTES_TRIGGER = 16_000_000
88
+
61
89
 
62
90
  class CompactionSettings(BaseModel):
63
91
  """Compaction knobs, mirrored from ``config.yml`` ``values.compaction.*``.
@@ -123,6 +151,16 @@ class CompactionSettings(BaseModel):
123
151
  # at $262. So the knob is opt-in per surface, and ``None`` means the frame
124
152
  # prune is not even consulted — ``run_compaction_pass`` with the defaults
125
153
  # is byte-identical to a pass without it, which a test pins.
154
+ #
155
+ # EXTENDED, not reversed: ``None`` now means "never prune frames for
156
+ # size-of-CONTEXT reasons", and a byte shed engages underneath it when the
157
+ # request would otherwise be REFUSED outright (``wire_bytes_budget``). The
158
+ # argument above assumes pruning frames costs the user content for no
159
+ # forced reason, which is exactly right up to the wall; at the wall the
160
+ # alternative is not "keep every frame", it is losing the whole session —
161
+ # a session that 413s loses all 42 frames, while the shed keeps 28. The
162
+ # default and the distinct-attachments reasoning are both untouched, and a
163
+ # session under budget still performs no work here at all.
126
164
  keep_recent_frames: int | None = Field(
127
165
  default=None,
128
166
  description=(
@@ -133,6 +171,36 @@ class CompactionSettings(BaseModel):
133
171
  ),
134
172
  )
135
173
 
174
+ # --- Transport size budget (BYTES, not tokens) --------------------------
175
+ #
176
+ # These two are the only knobs in this model measured in bytes, and the
177
+ # separation is deliberate: the token thresholds above answer "how much of
178
+ # the context WINDOW is occupied", these answer "will the HTTP request be
179
+ # accepted". A screenshot-heavy session can sit at 15% of a 1M window and
180
+ # still be over a provider's request cap, because a flat per-image token
181
+ # charge (correct for billing) is blind to base64 length. Never compare a
182
+ # value here against a token figure.
183
+ #
184
+ # Registered in ``settings_io.SETTINGS`` so an operator on a provider with
185
+ # a different cap can move them without editing code.
186
+ wire_bytes_budget: int = Field(
187
+ default=DEFAULT_WIRE_BYTES_BUDGET,
188
+ description=(
189
+ "Hard ceiling on the serialized request in BYTES. Older screenshots"
190
+ " are shed from the rendered history (never from the transcript) to"
191
+ " stay under it. Non-positive disables the shed."
192
+ ),
193
+ )
194
+ wire_bytes_trigger: int = Field(
195
+ default=DEFAULT_WIRE_BYTES_TRIGGER,
196
+ description=(
197
+ "Soft trigger in BYTES: a compaction pass fires once the serialized"
198
+ " request passes this, so a screenshot-heavy session summarises"
199
+ " early instead of shedding frames at the hard budget."
200
+ " Non-positive disables the byte trigger."
201
+ ),
202
+ )
203
+
136
204
  # --- Speculative compaction advisor (BETA, off by default) -------------
137
205
  #
138
206
  # Every field below is optional with an inert default, so a config written
@@ -386,6 +454,7 @@ def should_compact(
386
454
  settings: CompactionSettings,
387
455
  *,
388
456
  advisory_ok: bool = False,
457
+ wire_bytes: int = 0,
389
458
  ) -> bool:
390
459
  """Whether the current context exceeds the compaction threshold.
391
460
 
@@ -411,15 +480,79 @@ def should_compact(
411
480
  the disabled/off short-circuit — is untouched, so a future reader citing
412
481
  this as precedent should carry those constraints too.
413
482
 
414
- With ``advisory_ok`` false (its default, and what every caller but the
415
- plan gate passes) the function is byte-identical to its previous form.
483
+ ``wire_bytes`` is the second input with that posture, and it is here for
484
+ the same reason ``advisory_ok`` is: it is a different QUESTION about the
485
+ same decision ("will the request be accepted?" beside "does the context
486
+ fit the window?"), and a separate ``should_compact_for_size()`` beside
487
+ this one would be exactly the trigger drift the module docstring forbids.
488
+ So it is OR-ed into the one resolved answer, where it can only pull the
489
+ trigger EARLIER.
490
+
491
+ The byte term is what makes an image-heavy session compact at all. Its
492
+ token estimate is honest and small — 42 screenshots read as 154,690
493
+ tokens, 15.5% of a 1M window — while the serialized request is 34 MB,
494
+ past the provider's cap. No token threshold can see that, because the
495
+ per-image token charge is flat by design (see
496
+ :func:`~.tokens.estimate_wire_bytes`).
497
+
498
+ Monotonicity is preserved in BOTH numeric arguments, which the session's
499
+ cheap upper-bound pre-gate depends on: raising either can only turn a
500
+ ``False`` into a ``True``. Bytes are exact and cheap, so the pre-gate can
501
+ pass the real figure rather than a bound.
502
+
503
+ With ``advisory_ok`` false and ``wire_bytes`` 0 (their defaults, and what
504
+ every caller but the plan gate passes) the function is byte-identical to
505
+ its previous form.
416
506
  """
417
507
  if not settings.enabled or settings.strategy == "off" or window_tokens <= 0:
418
508
  return False
419
509
  threshold = resolve_threshold_tokens(window_tokens, settings)
420
510
  if advisory_ok and getattr(settings, "advisor_enabled", False):
421
511
  threshold = min(threshold, resolve_advisor_floor_tokens(window_tokens, settings))
422
- return context_tokens > threshold
512
+ if context_tokens > threshold:
513
+ return True
514
+ byte_trigger = resolve_wire_bytes_trigger(settings)
515
+ return byte_trigger > 0 and wire_bytes > byte_trigger
516
+
517
+
518
+ def resolve_wire_bytes_budget(settings: CompactionSettings) -> int:
519
+ """THE hard byte ceiling, resolved in one place.
520
+
521
+ Same discipline as :func:`resolve_threshold_tokens`: one resolver, no
522
+ caller re-deriving the number from the settings model. A non-positive
523
+ value means "no byte ceiling" and is returned as ``0`` so every caller can
524
+ test it the same way; a garbage value falls back to the default rather
525
+ than disabling the guard silently, because a typo here is the difference
526
+ between a session that recovers and one that 413s forever.
527
+ """
528
+ raw = getattr(settings, "wire_bytes_budget", DEFAULT_WIRE_BYTES_BUDGET)
529
+ try:
530
+ value = int(raw)
531
+ except (TypeError, ValueError):
532
+ logger.warning("compaction.wire_bytes_budget is not an integer; using the default")
533
+ return DEFAULT_WIRE_BYTES_BUDGET
534
+ return value if value > 0 else 0
535
+
536
+
537
+ def resolve_wire_bytes_trigger(settings: CompactionSettings) -> int:
538
+ """THE soft byte trigger, resolved in one place.
539
+
540
+ Clamped to the hard budget: a trigger ABOVE the ceiling would mean the
541
+ render seam amputates frames before a proper compaction pass ever fires,
542
+ which inverts the whole design — the soft trigger exists so the session
543
+ summarises with a model call instead of surviving by amputation. Returns
544
+ ``0`` when the byte trigger is disabled.
545
+ """
546
+ raw = getattr(settings, "wire_bytes_trigger", DEFAULT_WIRE_BYTES_TRIGGER)
547
+ try:
548
+ value = int(raw)
549
+ except (TypeError, ValueError):
550
+ logger.warning("compaction.wire_bytes_trigger is not an integer; using the default")
551
+ value = DEFAULT_WIRE_BYTES_TRIGGER
552
+ if value <= 0:
553
+ return 0
554
+ budget = resolve_wire_bytes_budget(settings)
555
+ return min(value, budget) if budget > 0 else value
423
556
 
424
557
 
425
558
  def compaction_context_tokens(provider_reported: int | None, local_estimate: int) -> int:
@@ -452,6 +585,40 @@ def cleared_headroom(residual_tokens: int, threshold_tokens: int) -> int:
452
585
  return threshold_tokens - residual_tokens
453
586
 
454
587
 
588
+ #: The byte-side twin of :data:`RECOVERY_BAND`, and it exists because that
589
+ #: constant CANNOT cover the byte trigger. ``RECOVERY_BAND`` is defined on
590
+ #: tokens against the token threshold; a pass fired by byte pressure can leave
591
+ #: the token residual comfortably inside the token band while the request is
592
+ #: still over the byte budget — the token side would then say "headroom
593
+ #: created", schedule an auto-continue, and the next turn would fire the byte
594
+ #: trigger again on a context nothing had shrunk. That is precisely the live
595
+ #: dead-loop ``RECOVERY_BAND`` was added for, arrived at through the new
596
+ #: trigger, so the guard has to be restated in the new trigger's own units.
597
+ #:
598
+ #: Same 0.8 ratio, same meaning: a pass counts as having created byte headroom
599
+ #: only when the residual request lands at or below ``0.8 x`` the soft byte
600
+ #: trigger.
601
+ WIRE_RECOVERY_BAND = 0.8
602
+
603
+
604
+ def cleared_wire_headroom(residual_bytes: int, settings: CompactionSettings) -> bool:
605
+ """Whether a pass created real BYTE headroom, for the auto-continue gate.
606
+
607
+ Returns ``True`` when the byte trigger is disabled, so a session that
608
+ never opted into byte pressure keeps exactly the token-only behaviour it
609
+ has today — this must not become a second veto on ordinary text sessions.
610
+
611
+ Otherwise the residual must sit at or below
612
+ ``WIRE_RECOVERY_BAND * trigger``. A pass that shaved a screenshot or two
613
+ and is still near the trigger has NOT recovered, and scheduling a
614
+ continuation on it re-enters the same pass next turn.
615
+ """
616
+ trigger = resolve_wire_bytes_trigger(settings)
617
+ if trigger <= 0:
618
+ return True
619
+ return residual_bytes <= WIRE_RECOVERY_BAND * trigger
620
+
621
+
455
622
  def resolve_strategy(
456
623
  settings: CompactionSettings, model: Any
457
624
  ) -> Literal["context-full", "snapcompact"]: