monkeybot 3.0.2__tar.gz → 3.0.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 (652) hide show
  1. {monkeybot-3.0.2 → monkeybot-3.0.4}/.github/workflows/ci.yml +1 -1
  2. {monkeybot-3.0.2 → monkeybot-3.0.4}/CHANGELOG.md +27 -0
  3. {monkeybot-3.0.2 → monkeybot-3.0.4}/PKG-INFO +8 -1
  4. {monkeybot-3.0.2 → monkeybot-3.0.4}/README.md +7 -0
  5. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/skills/monkeybot/SKILL.md +3 -1
  6. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/skills/monkeybot/references/config-sections.md +1 -1
  7. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_local_shell.py +7 -43
  8. monkeybot-3.0.4/cli/src/monkeybot_cli/commands/run_cmd.py +197 -0
  9. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/extras_catalog.py +2 -1
  10. monkeybot-3.0.4/cli/src/monkeybot_cli/process_tree.py +44 -0
  11. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/providers.py +11 -0
  12. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold.py +1 -0
  13. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/env.example +4 -1
  14. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +13 -1
  15. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_local_shell.py +16 -15
  16. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_extras_catalog.py +5 -0
  17. monkeybot-3.0.4/cli/tests/test_run_cmd.py +277 -0
  18. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_scaffold.py +1 -0
  19. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/features.md +27 -2
  20. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/sse-gateway-ui.md +2 -2
  21. {monkeybot-3.0.2 → monkeybot-3.0.4}/pyproject.toml +1 -1
  22. monkeybot-3.0.4/src/monkeybot/computer/__init__.py +116 -0
  23. monkeybot-3.0.4/src/monkeybot/computer/approvals.py +194 -0
  24. monkeybot-3.0.4/src/monkeybot/computer/permissions.py +220 -0
  25. monkeybot-3.0.4/src/monkeybot/computer/safety.py +683 -0
  26. monkeybot-3.0.4/src/monkeybot/computer/tools.py +406 -0
  27. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/store.py +16 -6
  28. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/bootstrap.py +7 -1
  29. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/runtime_env.py +2 -0
  30. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/settings.py +17 -5
  31. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/validation.py +8 -12
  32. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/__init__.py +12 -1
  33. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/__init__.py +2 -0
  34. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/config.py +15 -0
  35. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/layout.py +23 -0
  36. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/llm/usage.py +18 -2
  37. monkeybot-3.0.4/src/monkeybot/core/path_safety.py +82 -0
  38. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/backends.py +3 -1
  39. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/firestore.indexes.json +8 -0
  40. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/firestore.py +47 -16
  41. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/history.py +56 -18
  42. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/postgres.py +64 -24
  43. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/sqlite.py +7 -2
  44. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/transcript.py +22 -7
  45. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/usage.py +47 -16
  46. monkeybot-3.0.4/src/monkeybot/core/persistence/usage_buckets.py +77 -0
  47. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/loop_usage.py +6 -1
  48. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/realtime_loop.py +174 -99
  49. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/tool_batch.py +23 -1
  50. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/tool_dispatch.py +40 -19
  51. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/turn_loop.py +64 -9
  52. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/subagents/subagent_worker.py +3 -0
  53. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/core_tool_executor.py +15 -2
  54. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/permission.py +68 -4
  55. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/sandbox_executor.py +21 -1
  56. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/spill_inventory.py +115 -28
  57. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/workspace_service.py +17 -0
  58. monkeybot-3.0.4/src/monkeybot/gateway/pending_response_bus.py +8 -0
  59. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/app.py +2 -0
  60. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/deps.py +3 -0
  61. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/routes.py +22 -2
  62. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/session.py +14 -6
  63. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/app.py +52 -19
  64. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/loop_port.py +4 -1
  65. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/models.py +23 -2
  66. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/routes.py +38 -21
  67. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/session_bus.py +32 -18
  68. monkeybot-3.0.4/src/monkeybot/providers/_bedrock_converse.py +604 -0
  69. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/_openai_compat.py +327 -27
  70. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/_utils.py +94 -26
  71. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/bedrock.py +64 -4
  72. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/model_capabilities.py +22 -11
  73. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/ollama.py +86 -16
  74. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/pricing.py +13 -4
  75. monkeybot-3.0.4/tests/computer/test_approvals.py +191 -0
  76. monkeybot-3.0.4/tests/computer/test_computer_tools.py +317 -0
  77. monkeybot-3.0.4/tests/computer/test_package_init.py +72 -0
  78. monkeybot-3.0.4/tests/computer/test_path_policy.py +368 -0
  79. monkeybot-3.0.4/tests/computer/test_permissions.py +342 -0
  80. monkeybot-3.0.4/tests/computer/test_subagent_exclusion.py +34 -0
  81. monkeybot-3.0.4/tests/computer/test_wiring.py +174 -0
  82. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_agent_layout.py +42 -1
  83. monkeybot-3.0.4/tests/core/test_attachment_store.py +43 -0
  84. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_config_extensions.py +22 -0
  85. monkeybot-3.0.4/tests/core/test_firestore_usage.py +72 -0
  86. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_history.py +40 -0
  87. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_config.py +23 -19
  88. monkeybot-3.0.4/tests/core/test_layout.py +47 -0
  89. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_loop.py +353 -0
  90. monkeybot-3.0.4/tests/core/test_path_safety.py +59 -0
  91. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_permission.py +99 -0
  92. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_realtime_loop.py +245 -28
  93. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_runtime_env.py +23 -0
  94. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_sandbox_executor.py +47 -0
  95. monkeybot-3.0.4/tests/core/test_spill_inventory.py +248 -0
  96. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_transcript.py +12 -0
  97. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_usage.py +109 -3
  98. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_workspace_symlinks.py +53 -0
  99. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_create_session_model.py +2 -2
  100. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_routes.py +41 -2
  101. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_session_bus.py +16 -0
  102. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_transcript_wiring.py +1 -1
  103. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_pending_response_endpoints.py +45 -0
  104. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_resolve_provider.py +30 -2
  105. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_anthropic_cache.py +9 -9
  106. monkeybot-3.0.4/tests/providers/test_bedrock_converse.py +605 -0
  107. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_model_capabilities.py +7 -0
  108. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_ollama.py +102 -0
  109. monkeybot-3.0.4/tests/providers/test_openai_compat_usage.py +1195 -0
  110. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_pricing.py +8 -0
  111. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_sampling.py +4 -4
  112. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_sonnet5_sampling.py +78 -0
  113. monkeybot-3.0.4/tests/web_search/__init__.py +0 -0
  114. {monkeybot-3.0.2 → monkeybot-3.0.4}/uv.lock +1 -1
  115. monkeybot-3.0.2/cli/src/monkeybot_cli/commands/run_cmd.py +0 -63
  116. monkeybot-3.0.2/cli/tests/test_run_cmd.py +0 -90
  117. monkeybot-3.0.2/src/monkeybot/core/path_safety.py +0 -11
  118. monkeybot-3.0.2/tests/core/test_spill_inventory.py +0 -81
  119. monkeybot-3.0.2/tests/providers/test_openai_compat_usage.py +0 -514
  120. {monkeybot-3.0.2 → monkeybot-3.0.4}/.dockerignore +0 -0
  121. {monkeybot-3.0.2 → monkeybot-3.0.4}/.github/workflows/live-eval-smoke.yml +0 -0
  122. {monkeybot-3.0.2 → monkeybot-3.0.4}/.github/workflows/prepare-release.yml +0 -0
  123. {monkeybot-3.0.2 → monkeybot-3.0.4}/.github/workflows/publish-release.yml +0 -0
  124. {monkeybot-3.0.2 → monkeybot-3.0.4}/.gitignore +0 -0
  125. {monkeybot-3.0.2 → monkeybot-3.0.4}/.pre-commit-config.yaml +0 -0
  126. {monkeybot-3.0.2 → monkeybot-3.0.4}/BACKLOG.md +0 -0
  127. {monkeybot-3.0.2 → monkeybot-3.0.4}/CONTRIBUTING.md +0 -0
  128. {monkeybot-3.0.2 → monkeybot-3.0.4}/LICENSE +0 -0
  129. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/pyproject.toml +0 -0
  130. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/__init__.py +0 -0
  131. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_file_index.py +0 -0
  132. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_renderer.py +0 -0
  133. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_session.py +0 -0
  134. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_status_bar.py +0 -0
  135. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_theme.py +0 -0
  136. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_tool_display.py +0 -0
  137. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_tui.py +0 -0
  138. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/chat_tui_widgets.py +0 -0
  139. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/__init__.py +0 -0
  140. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/chat.py +0 -0
  141. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/doctor.py +0 -0
  142. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/loop.py +0 -0
  143. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/new.py +0 -0
  144. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/refresh.py +0 -0
  145. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/talk.py +0 -0
  146. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/commands/validate.py +0 -0
  147. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/compat.py +0 -0
  148. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/config_resolve.py +0 -0
  149. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/exit_commands.py +0 -0
  150. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/gateway_health.py +0 -0
  151. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/main.py +0 -0
  152. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/opensandbox_lifecycle.py +0 -0
  153. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/output.py +0 -0
  154. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/__init__.py +0 -0
  155. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/audio_io.py +0 -0
  156. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/client.py +0 -0
  157. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/gateway_manager.py +0 -0
  158. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/push_to_talk.py +0 -0
  159. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/session.py +0 -0
  160. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/session_controller.py +0 -0
  161. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/talk_ui.py +0 -0
  162. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/realtime/wire_encode.py +0 -0
  163. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/runtime_python.py +0 -0
  164. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/AGENT.md +0 -0
  165. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/Dockerfile +0 -0
  166. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/__init__.py +0 -0
  167. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/browser/SKILL.md +0 -0
  168. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/command_allowlist.yaml +0 -0
  169. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/dockerignore +0 -0
  170. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/image-generator/SKILL.md +0 -0
  171. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/image-generator/generate_image.py +0 -0
  172. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/loop/SKILL.md +0 -0
  173. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/mcp.json +0 -0
  174. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/opensandbox.docker.toml +0 -0
  175. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +0 -0
  176. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/scaffold_defaults/permissions.yaml +0 -0
  177. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/session_controller.py +0 -0
  178. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/src/monkeybot_cli/terminal_markdown.py +0 -0
  179. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_continue.py +0 -0
  180. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_e2e.py +0 -0
  181. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_errors.py +0 -0
  182. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_file_index.py +0 -0
  183. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_grounding.py +0 -0
  184. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_renderer_parity.py +0 -0
  185. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_session.py +0 -0
  186. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_status_bar.py +0 -0
  187. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_theme.py +0 -0
  188. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_tool_display.py +0 -0
  189. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_chat_tui.py +0 -0
  190. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_cli.py +0 -0
  191. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_config_resolve.py +0 -0
  192. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_doctor.py +0 -0
  193. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_gateway_health.py +0 -0
  194. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_opensandbox_lifecycle.py +0 -0
  195. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_realtime_session_controller.py +0 -0
  196. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_runtime_python.py +0 -0
  197. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/tests/test_terminal_markdown.py +0 -0
  198. {monkeybot-3.0.2 → monkeybot-3.0.4}/cli/uv.lock +0 -0
  199. {monkeybot-3.0.2 → monkeybot-3.0.4}/docker/Dockerfile +0 -0
  200. {monkeybot-3.0.2 → monkeybot-3.0.4}/docker/docker-compose.sandbox.yml +0 -0
  201. {monkeybot-3.0.2 → monkeybot-3.0.4}/docker/opensandbox.docker.toml +0 -0
  202. {monkeybot-3.0.2 → monkeybot-3.0.4}/docker/sandbox.Dockerfile +0 -0
  203. {monkeybot-3.0.2 → monkeybot-3.0.4}/docker-compose.yml +0 -0
  204. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/agent-layout.md +0 -0
  205. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/assets/logo.png +0 -0
  206. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/browser-mcp.md +0 -0
  207. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/cloud-deployment-design.md +0 -0
  208. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/deploy-aws-agentcore.md +0 -0
  209. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/deploy-pattern-a-container.md +0 -0
  210. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/deploy-pattern-b-serverless.md +0 -0
  211. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/deploy-pattern-c-agent-platform.md +0 -0
  212. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/deploy-pattern-d-realtime.md +0 -0
  213. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/getting-started.md +0 -0
  214. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/knowledge-layer-fixes.md +0 -0
  215. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/live-evals.md +0 -0
  216. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/mcp.md +0 -0
  217. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/memory-graph-split-plan.md +0 -0
  218. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/migrations/agent-scope-namespacing.md +0 -0
  219. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/migrations/memory-outbox.sql +0 -0
  220. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/observability-runbook.md +0 -0
  221. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/otel-collector.example.yaml +0 -0
  222. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/progressive-loop-tools.md +0 -0
  223. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/progressive-mcp-tools.md +0 -0
  224. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/skills.md +0 -0
  225. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/spill-dynamic-design.md +0 -0
  226. {monkeybot-3.0.2 → monkeybot-3.0.4}/docs/workspace-index-design.md +0 -0
  227. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/TEST_COVERAGE.md +0 -0
  228. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/assertions.py +0 -0
  229. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/diff.py +0 -0
  230. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/eval_config.yaml +0 -0
  231. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/models.py +0 -0
  232. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/persistence.py +0 -0
  233. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/report.py +0 -0
  234. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/runner.py +0 -0
  235. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenario_loader.py +0 -0
  236. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/context/summarization_trigger.yaml +0 -0
  237. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/mcp/get_prompt.yaml +0 -0
  238. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/mcp/list_resources.yaml +0 -0
  239. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/mcp/tool_invoke.yaml +0 -0
  240. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/memory/recall_cross_session.yaml +0 -0
  241. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/memory/recall_single_session.yaml +0 -0
  242. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/multi_turn/task_tracking.yaml +0 -0
  243. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/skills/skill_invocation.yaml +0 -0
  244. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/subagents/dispatch_complete.yaml +0 -0
  245. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/tools/core_read.yaml +0 -0
  246. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/tools/core_read_error.yaml +0 -0
  247. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/tools/core_run_command.yaml +0 -0
  248. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/tools/core_run_command_sandbox.yaml +0 -0
  249. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scenarios/tools/core_write.yaml +0 -0
  250. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/scorer.py +0 -0
  251. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/.env.example +0 -0
  252. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/.gitignore +0 -0
  253. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/fixture_mcp_server.py +0 -0
  254. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/monkeybot_config/AGENT.md +0 -0
  255. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/monkeybot_config/command_allowlist.yaml +0 -0
  256. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/monkeybot_config/mcp.json +0 -0
  257. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/monkeybot_config/monkeybot.yaml +0 -0
  258. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/monkeybot_config/permissions.yaml +0 -0
  259. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/pyproject.toml +0 -0
  260. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/skills/browser/SKILL.md +0 -0
  261. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/uv.lock +0 -0
  262. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/workspace/.gitkeep +0 -0
  263. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/smoke_agent/workspace/skills/browser/playbooks/.gitkeep +0 -0
  264. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/suites/smoke.yaml +0 -0
  265. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_assertions.py +0 -0
  266. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_diff.py +0 -0
  267. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_judge.py +0 -0
  268. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_report.py +0 -0
  269. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_runner_sse.py +0 -0
  270. {monkeybot-3.0.2 → monkeybot-3.0.4}/evals/test_scorer.py +0 -0
  271. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/README.md +0 -0
  272. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/agentcore/handler.py +0 -0
  273. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/agentcore/runtime_app.py +0 -0
  274. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/agentengine/handler.py +0 -0
  275. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/cloud-functions/main.py +0 -0
  276. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/lambda/handler.py +0 -0
  277. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/browser/SKILL.md +0 -0
  278. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/browser/playbooks/.gitkeep +0 -0
  279. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/diagnostics/README.md +0 -0
  280. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/diagnostics/SKILL.md +0 -0
  281. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/diagnostics/__init__.py +0 -0
  282. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/diagnostics/diagnostics.py +0 -0
  283. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/image-generator/SKILL.md +0 -0
  284. {monkeybot-3.0.2 → monkeybot-3.0.4}/examples/skills/image-generator/generate_image.py +0 -0
  285. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/pyproject.toml +0 -0
  286. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/scripts/agentcore_smoke.py +0 -0
  287. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/__init__.py +0 -0
  288. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/agentcore.py +0 -0
  289. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/assets/NOTICE.md +0 -0
  290. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/assets/dom_tree.js +0 -0
  291. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/assets/pa_driver.js +0 -0
  292. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/dom_indexing.py +0 -0
  293. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/playbooks.py +0 -0
  294. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/playwright_helpers.py +0 -0
  295. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/screenshots.py +0 -0
  296. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/src/browser_mcp/server.py +0 -0
  297. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_agentcore.py +0 -0
  298. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_dom_indexing.py +0 -0
  299. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_in_app_cdp.py +0 -0
  300. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_indexed_tools.py +0 -0
  301. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_playbooks.py +0 -0
  302. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_playwright_helpers.py +0 -0
  303. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_screenshots.py +0 -0
  304. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/tests/test_server_shutdown.py +0 -0
  305. {monkeybot-3.0.2 → monkeybot-3.0.4}/integrations/browser-mcp/uv.lock +0 -0
  306. {monkeybot-3.0.2 → monkeybot-3.0.4}/pytest.ini +0 -0
  307. {monkeybot-3.0.2 → monkeybot-3.0.4}/scripts/create_schema.py +0 -0
  308. {monkeybot-3.0.2 → monkeybot-3.0.4}/scripts/precommit-pytest.sh +0 -0
  309. {monkeybot-3.0.2 → monkeybot-3.0.4}/scripts/release.py +0 -0
  310. {monkeybot-3.0.2 → monkeybot-3.0.4}/scripts/smoke_global_cli.sh +0 -0
  311. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/__init__.py +0 -0
  312. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/__init__.py +0 -0
  313. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/__main__.py +0 -0
  314. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/audio_io.py +0 -0
  315. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/gateway_manager.py +0 -0
  316. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/main.py +0 -0
  317. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/push_to_talk.py +0 -0
  318. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/cli/realtime_client.py +0 -0
  319. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/__init__.py +0 -0
  320. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/__init__.py +0 -0
  321. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/catalog.py +0 -0
  322. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/config.py +0 -0
  323. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/freeze.py +0 -0
  324. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/resolve.py +0 -0
  325. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/text.py +0 -0
  326. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/attachments/tools.py +0 -0
  327. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/__init__.py +0 -0
  328. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/realtime_config.py +0 -0
  329. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/config/yaml_loader.py +0 -0
  330. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/campaign_context.py +0 -0
  331. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/common.py +0 -0
  332. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/epoch.py +0 -0
  333. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/tool_output_policy.py +0 -0
  334. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/tool_result_ingress.py +0 -0
  335. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/context/tool_shapers.py +0 -0
  336. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/hooks/__init__.py +0 -0
  337. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/captions.py +0 -0
  338. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/chunking.py +0 -0
  339. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/__init__.py +0 -0
  340. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/base.py +0 -0
  341. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/factory.py +0 -0
  342. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/gemini.py +0 -0
  343. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/nvidia.py +0 -0
  344. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/openai_compat.py +0 -0
  345. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/embeddings/sanitize.py +0 -0
  346. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/evidence_guard.py +0 -0
  347. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/extractors.py +0 -0
  348. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/fusion.py +0 -0
  349. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/hook.py +0 -0
  350. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/indexer.py +0 -0
  351. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/links.py +0 -0
  352. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/salience.py +0 -0
  353. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/sqlite_index.py +0 -0
  354. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/subsystem.py +0 -0
  355. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/tool.py +0 -0
  356. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/knowledge/types.py +0 -0
  357. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/llm/__init__.py +0 -0
  358. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/llm/provider.py +0 -0
  359. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/llm/realtime_provider.py +0 -0
  360. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/lockfile_names.py +0 -0
  361. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/logging_utils.py +0 -0
  362. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/mcp/__init__.py +0 -0
  363. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/mcp/mcp_client.py +0 -0
  364. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/mcp/ports_mcp.py +0 -0
  365. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/__init__.py +0 -0
  366. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/config.py +0 -0
  367. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/hook.py +0 -0
  368. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/ids.py +0 -0
  369. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/ingest.py +0 -0
  370. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/migrate_layout.py +0 -0
  371. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/observability.py +0 -0
  372. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/outbox.py +0 -0
  373. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/palace.py +0 -0
  374. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/subsystem.py +0 -0
  375. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/uri.py +0 -0
  376. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/memory/writer.py +0 -0
  377. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/messages/__init__.py +0 -0
  378. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/messages/convert_provider.py +0 -0
  379. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/messages/tool_integrity.py +0 -0
  380. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/messages/transform_context.py +0 -0
  381. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/__init__.py +0 -0
  382. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/db.py +0 -0
  383. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/durable_runs.py +0 -0
  384. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/errors.py +0 -0
  385. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/firestore_scheduled_loops.py +0 -0
  386. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/runs.py +0 -0
  387. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/scheduled_loops.py +0 -0
  388. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/session_turn_locks.py +0 -0
  389. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/sqlite_backend.py +0 -0
  390. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/sqlite_vector.py +0 -0
  391. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/thread_summary.py +0 -0
  392. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/persistence/transcript_analyzer.py +0 -0
  393. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/prompts/__init__.py +0 -0
  394. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/prompts/harness_prompt.py +0 -0
  395. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/prompts/headings.py +0 -0
  396. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/prompts/prompt.py +0 -0
  397. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/__init__.py +0 -0
  398. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/context_budget.py +0 -0
  399. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/doom_loop.py +0 -0
  400. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/events.py +0 -0
  401. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/history_compaction.py +0 -0
  402. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/input_admission.py +0 -0
  403. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/loop.py +0 -0
  404. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/loop_hooks.py +0 -0
  405. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/loop_messages.py +0 -0
  406. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/loop_ports.py +0 -0
  407. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/provider_stream_mapper.py +0 -0
  408. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/runtime/utterance_buffer.py +0 -0
  409. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/subagents/__init__.py +0 -0
  410. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/subagents/progress_publish.py +0 -0
  411. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/subagents/subagent_proto.py +0 -0
  412. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/subagents/worker_pool.py +0 -0
  413. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/testing/__init__.py +0 -0
  414. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/testing/mocks_provider.py +0 -0
  415. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/testing/mocks_realtime_provider.py +0 -0
  416. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/__init__.py +0 -0
  417. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/fs_isolation.py +0 -0
  418. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/inspector.py +0 -0
  419. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/loop_inspector.py +0 -0
  420. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/patch.py +0 -0
  421. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/terminal.py +0 -0
  422. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/text_normalize.py +0 -0
  423. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/tool_hint.py +0 -0
  424. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/tool_kind.py +0 -0
  425. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/tools/types.py +0 -0
  426. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/types/__init__.py +0 -0
  427. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/types/content_blocks.py +0 -0
  428. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/types/interfaces.py +0 -0
  429. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/types/types_tools.py +0 -0
  430. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/__init__.py +0 -0
  431. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/factory.py +0 -0
  432. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/gcs.py +0 -0
  433. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/local.py +0 -0
  434. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/protocol.py +0 -0
  435. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace/s3.py +0 -0
  436. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/core/workspace_layout.py +0 -0
  437. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/__init__.py +0 -0
  438. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/bootstrap.py +0 -0
  439. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/main.py +0 -0
  440. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/__init__.py +0 -0
  441. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/errors.py +0 -0
  442. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/guardrails.py +0 -0
  443. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/manager.py +0 -0
  444. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/metrics.py +0 -0
  445. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime/wire.py +0 -0
  446. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/realtime_main.py +0 -0
  447. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/__init__.py +0 -0
  448. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/reply_body.py +0 -0
  449. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/scheduler_routes.py +0 -0
  450. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/scheduler_wiring.py +0 -0
  451. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/sse.py +0 -0
  452. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/gateway/sse/workspace_layout.py +0 -0
  453. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/__init__.py +0 -0
  454. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/_state.py +0 -0
  455. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/instrumentation.py +0 -0
  456. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/propagation.py +0 -0
  457. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/spans.py +0 -0
  458. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/observability/sqlite_exporter.py +0 -0
  459. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/__init__.py +0 -0
  460. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/claude.py +0 -0
  461. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/gemini.py +0 -0
  462. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/gemini_live.py +0 -0
  463. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/huggingface.py +0 -0
  464. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/nvidia.py +0 -0
  465. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/openai.py +0 -0
  466. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/openrouter.py +0 -0
  467. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/sampling.py +0 -0
  468. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/providers/vertex_claude.py +0 -0
  469. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scaffold/__init__.py +0 -0
  470. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/__init__.py +0 -0
  471. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/__main__.py +0 -0
  472. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/engine.py +0 -0
  473. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/http_invoker.py +0 -0
  474. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/interval.py +0 -0
  475. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/tick_result.py +0 -0
  476. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/scheduler/worker.py +0 -0
  477. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/subagents/__init__.py +0 -0
  478. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/subagents/worker/__init__.py +0 -0
  479. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/subagents/worker/__main__.py +0 -0
  480. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/todo_list/__init__.py +0 -0
  481. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/todo_list/store.py +0 -0
  482. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/todo_list/tool.py +0 -0
  483. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/__init__.py +0 -0
  484. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/backends/__init__.py +0 -0
  485. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/backends/duckduckgo.py +0 -0
  486. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/backends/firecrawl.py +0 -0
  487. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/backends/tavily.py +0 -0
  488. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/protocol.py +0 -0
  489. {monkeybot-3.0.2 → monkeybot-3.0.4}/src/monkeybot/web_search/tool.py +0 -0
  490. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/__init__.py +0 -0
  491. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/acceptance/test_observability_acceptance.py +0 -0
  492. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/cli/__init__.py +0 -0
  493. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/cli/test_gateway_manager.py +0 -0
  494. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/cli/test_main.py +0 -0
  495. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/cli/test_push_to_talk.py +0 -0
  496. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/cli/test_realtime_client.py +0 -0
  497. {monkeybot-3.0.2/tests/gateway/realtime → monkeybot-3.0.4/tests/computer}/__init__.py +0 -0
  498. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/conftest.py +0 -0
  499. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/__init__.py +0 -0
  500. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/fixtures/bitbucket_dc_style_pr.diff +0 -0
  501. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/memory/helpers.py +0 -0
  502. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/memory/in_memory_palace.py +0 -0
  503. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/memory/test_mempalace.py +0 -0
  504. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/memory/test_review_fixes.py +0 -0
  505. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_attachment_freeze.py +0 -0
  506. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_bootstrap.py +0 -0
  507. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_content_blocks.py +0 -0
  508. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_context.py +0 -0
  509. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_context_budget.py +0 -0
  510. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_context_epoch.py +0 -0
  511. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_core_tool_executor.py +0 -0
  512. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_doom_loop.py +0 -0
  513. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_durable_events.py +0 -0
  514. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_durable_runs.py +0 -0
  515. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_empty_completion.py +0 -0
  516. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_events.py +0 -0
  517. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_evidence_guard.py +0 -0
  518. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_firestore_history.py +0 -0
  519. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_firestore_scheduled_loops.py +0 -0
  520. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_fs_isolation.py +0 -0
  521. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_gemini_history_replay.py +0 -0
  522. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_harness_prompt.py +0 -0
  523. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_history_compaction_split.py +0 -0
  524. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_hooks.py +0 -0
  525. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_input_admission.py +0 -0
  526. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_inspector.py +0 -0
  527. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_chunking.py +0 -0
  528. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_chunking_rank.py +0 -0
  529. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_embeddings.py +0 -0
  530. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_fts.py +0 -0
  531. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_fusion.py +0 -0
  532. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_fusion_ann.py +0 -0
  533. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_hook.py +0 -0
  534. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_indexer.py +0 -0
  535. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_links.py +0 -0
  536. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_media.py +0 -0
  537. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_salience.py +0 -0
  538. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_single_writer.py +0 -0
  539. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_subsystem.py +0 -0
  540. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_knowledge_vectors.py +0 -0
  541. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_logging_utils.py +0 -0
  542. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_loop_hooks.py +0 -0
  543. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_loop_observability.py +0 -0
  544. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_loop_transcript.py +0 -0
  545. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_mcp_client.py +0 -0
  546. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_memory_layout_migrate.py +0 -0
  547. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_message_pipeline.py +0 -0
  548. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_mocks_realtime_provider.py +0 -0
  549. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_patch.py +0 -0
  550. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_pricing.py +0 -0
  551. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_progress_publish.py +0 -0
  552. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_prompt.py +0 -0
  553. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_provider_contract.py +0 -0
  554. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_provider_stream_mapper.py +0 -0
  555. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_replace_fuzzy.py +0 -0
  556. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_run_command_parse.py +0 -0
  557. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_runs.py +0 -0
  558. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_scheduled_loops.py +0 -0
  559. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_session_turn_locks.py +0 -0
  560. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_settlement.py +0 -0
  561. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_spill_dynamic.py +0 -0
  562. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_storage_backends.py +0 -0
  563. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_subagent_proto.py +0 -0
  564. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_subagent_trace_propagation.py +0 -0
  565. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_subagent_worker_paths.py +0 -0
  566. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_terminal.py +0 -0
  567. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_thread_summary_wire.py +0 -0
  568. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_tool_def_schema.py +0 -0
  569. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_tool_integrity.py +0 -0
  570. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_tool_result_ingress.py +0 -0
  571. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_tool_shapers.py +0 -0
  572. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_transcript_analyzer.py +0 -0
  573. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_truncated_tool_batch.py +0 -0
  574. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_usage_migration.py +0 -0
  575. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_utterance_buffer.py +0 -0
  576. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_worker_pool.py +0 -0
  577. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_workspace_layout.py +0 -0
  578. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/test_workspace_write_scope.py +0 -0
  579. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/workspace/test_factory.py +0 -0
  580. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/workspace/test_local_storage.py +0 -0
  581. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/core/workspace/test_protocol_contract.py +0 -0
  582. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/__init__.py +0 -0
  583. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/eval_hook.py +0 -0
  584. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenario_runner.py +0 -0
  585. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/context_curation.yaml +0 -0
  586. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/memory_write_inject.yaml +0 -0
  587. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/subagent_roundtrip.yaml +0 -0
  588. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_glob_grep.yaml +0 -0
  589. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_load_file.yaml +0 -0
  590. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_loops.yaml +0 -0
  591. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_read.yaml +0 -0
  592. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_replace_apply_patch.yaml +0 -0
  593. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_run_command.yaml +0 -0
  594. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_search_knowledge.yaml +0 -0
  595. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_search_memory.yaml +0 -0
  596. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_todo_list.yaml +0 -0
  597. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_web_search.yaml +0 -0
  598. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/tool_write.yaml +0 -0
  599. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/scenarios/turn_completion.yaml +0 -0
  600. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/test_agent_behavior.py +0 -0
  601. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/evals/test_memory_knowledge_routing.py +0 -0
  602. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/__init__.py +0 -0
  603. {monkeybot-3.0.2/tests/web_search → monkeybot-3.0.4/tests/gateway/realtime}/__init__.py +0 -0
  604. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_app.py +0 -0
  605. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_deps.py +0 -0
  606. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_guardrails.py +0 -0
  607. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_manager.py +0 -0
  608. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_metrics.py +0 -0
  609. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_routes_client_text.py +0 -0
  610. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_session.py +0 -0
  611. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/realtime/test_wire.py +0 -0
  612. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_attachments.py +0 -0
  613. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/sse/test_scheduler_routes.py +0 -0
  614. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_otel_fastapi.py +0 -0
  615. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_otel_lifespan.py +0 -0
  616. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_realtime_main.py +0 -0
  617. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_sse_events.py +0 -0
  618. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/gateway/test_subagent_event_publisher.py +0 -0
  619. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/integration/__init__.py +0 -0
  620. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/integration/test_mb_e2e_simple_reply.py +0 -0
  621. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/integration/test_observability_integration.py +0 -0
  622. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/integration/test_prompt_caching_integration.py +0 -0
  623. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/conftest.py +0 -0
  624. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_init.py +0 -0
  625. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_instrumentation.py +0 -0
  626. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_loop_hook_spans.py +0 -0
  627. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_propagation.py +0 -0
  628. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_span_contract.py +0 -0
  629. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_spans.py +0 -0
  630. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_sqlite_exporter.py +0 -0
  631. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_truncate.py +0 -0
  632. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/observability/test_turn_complete_trace.py +0 -0
  633. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/conftest.py +0 -0
  634. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_anthropic_history.py +0 -0
  635. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_bedrock_estimate.py +0 -0
  636. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_gemini_live.py +0 -0
  637. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_gemini_usage.py +0 -0
  638. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_huggingface.py +0 -0
  639. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_nvidia.py +0 -0
  640. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_openai_history.py +0 -0
  641. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_safe_parse_tool_args.py +0 -0
  642. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_source_grep_gates.py +0 -0
  643. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/providers/test_vertex_claude_history.py +0 -0
  644. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/scheduler/test_engine.py +0 -0
  645. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/scheduler/test_interval.py +0 -0
  646. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/skills/__init__.py +0 -0
  647. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/skills/test_generate_image_script.py +0 -0
  648. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/test_cold_start.py +0 -0
  649. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/test_packaging_config.py +0 -0
  650. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/test_release_script.py +0 -0
  651. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/todo_list/test_todo_list.py +0 -0
  652. {monkeybot-3.0.2 → monkeybot-3.0.4}/tests/web_search/test_web_search.py +0 -0
@@ -19,7 +19,7 @@ jobs:
19
19
  version: "latest"
20
20
 
21
21
  - name: Sync dependencies
22
- run: uv sync --extra claude --extra vertex-claude --extra bedrock
22
+ run: uv sync --extra claude --extra vertex-claude --extra bedrock --extra firestore
23
23
 
24
24
  - name: Mypy
25
25
  run: uv run mypy src/monkeybot
@@ -6,6 +6,30 @@ the project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### CLI
10
+
11
+ ### Changed
12
+
13
+ - CLI extras catalog / `monkeybot new` provider menu lists `ollama-cloud` and `ollama-local` instead of a single `ollama` row. `--with ollama` and `--provider ollama` still work.
14
+
15
+ ## [core v3.0.4] - 2026-08-28
16
+
17
+ ### Added
18
+
19
+ - Explicit `ollama-cloud` and `ollama-local` provider ids so Cloud always hits `https://ollama.com` even when a leftover local `OLLAMA_BASE_URL` is set. Legacy `ollama` still auto-routes from env.
20
+
21
+ ## [core v3.0.3] - 2026-08-23
22
+
23
+ ### Added
24
+
25
+ - Local computer control: nine opt-in, macOS-only `computer_*` tools (`computer/`) let the agent open/reveal files and folders, launch apps, open URLs, read/write the clipboard, and list/find/move/trash files under the user's home directory. Off by default (`computer.enabled: false` / `MONKEYBOT_COMPUTER_TOOLS`); intended for the Monkeybot desktop app, never a server deployment. Every call asks for approval by default via a built-in ruleset baseline (not `permissions.yaml`, which is fail-open); "Always allow" is scoped to the exact `(tool, resource)` approved and persists durably to `monkeybot_config/approvals.json` (a new machine-written file — never hand-edit). Hard security limits (home-directory confinement, credential-path denylist, exec-surface refusal on `open`, trash-not-delete) live in the tool bodies and cannot be bypassed by permission rules. See `docs/features.md` §22.
26
+ - `permissions.yaml`'s `tool-confirmations` approval now supports a durable `persist` hook (`remember_always_approval(..., persist=...)`) in addition to the existing in-session `SessionApprovals` cache; `resource_for_call` gained `url`/`app` argument lookups for readable permission resource strings on tools with no `path` arg.
27
+
28
+ ### Fixed
29
+
30
+ - Anthropic SDK 1.0 removed `temperature` / `top_p` / `top_k` from `messages.stream()`. Filter stream kwargs to the callable signature and retry `TypeError: unexpected keyword argument` so Claude/Bedrock streams no longer die before the request.
31
+ - Stop during a tool confirmation sets the turn cancel Event in `POST /cancel` (and on realtime interrupt) before pending futures are cancelled, so completed tool results settle into history instead of racing a 50ms poller. Session DELETE and websocket teardown leave the Event unset and propagate cancellation. Spill writes refuse an uncontained `_` symlink fallback; transcript and attachment dirs reuse a safe pre-sanitization folder when it still exists on disk. Attachment reads also reject symlinked attachment ids that resolve outside the workspace.
32
+
9
33
  ## [core v3.0.2] - 2026-08-18
10
34
 
11
35
  ### Fixed
@@ -37,6 +61,9 @@ the project adheres to [Semantic Versioning](https://semver.org/).
37
61
 
38
62
  ### Fixed
39
63
 
64
+ - Stop during a tool confirmation now settles completed tool results into history (and synthesizes cancel envelopes for the rest) instead of escaping before abort settlement; the realtime confirm path does the same. Cancel after a finished provider stream also persists already-shown assistant text so follow-ups match what the user saw, and settles any finalized tool calls with cancel envelopes.
65
+ - SQLite `history.reset` (compaction / load-max truncate) runs delete+reinsert in one transaction, matching Postgres, so a crash mid-reset cannot wipe or partially rewrite a thread.
66
+ - Tool spill paths sanitize client `session_id` / `thread_id` components and refuse to write or delete outside `.monkeybot/spill`; `POST /sessions` rejects path-traversal session ids; session DELETE quiesces the active turn before removing spill dirs. The same path-component sanitizer also applies to transcript and attachment directories, so legacy ids containing glob metacharacters map to a sanitized on-disk folder (reads still find a pre-sanitization folder when it exists).
40
67
  - Streamable HTTP MCP connects accept both 2-tuple and 3-tuple transport yields from the MCP Python SDK.
41
68
  - Stop mid-reply now cancels the in-flight provider token stream (instead of waiting for the full LLM call) and persists any already-streamed assistant text to history so follow-up turns keep matching what the user saw.
42
69
  - Chunking improvements now reach existing workspaces: a chunker version bump re-chunks indexed files even when their modification time never changed, so upgrades no longer require deleting `.monkeybot/knowledge/`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: monkeybot
3
- Version: 3.0.2
3
+ Version: 3.0.4
4
4
  Summary: monkeybot agent harness — FastAPI SSE gateway, owned loop, SQLite, and MCP.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -191,6 +191,13 @@ Clone only if you are changing the harness. Setup, checks, and the release workf
191
191
 
192
192
  Search or open an issue in the [GitHub issue tracker](https://github.com/human-plus-machine/monkeybot/issues).
193
193
 
194
+ ## Credits
195
+
196
+ MonkeyBot builds on two open-source projects:
197
+
198
+ - [Browser Use](https://github.com/browser-use/browser-use) — browser automation for the [browser MCP](docs/browser-mcp.md) (via [browser-harness](https://github.com/browser-use/browser-harness) and the interactive-element DOM walker). MIT licensed.
199
+ - [OpenSandbox](https://github.com/opensandbox-group/OpenSandbox) — sandbox runtime used for isolated `run_command` / code execution. Apache-2.0 licensed.
200
+
194
201
  ## License
195
202
 
196
203
  MIT — see [`LICENSE`](LICENSE).
@@ -93,6 +93,13 @@ Clone only if you are changing the harness. Setup, checks, and the release workf
93
93
 
94
94
  Search or open an issue in the [GitHub issue tracker](https://github.com/human-plus-machine/monkeybot/issues).
95
95
 
96
+ ## Credits
97
+
98
+ MonkeyBot builds on two open-source projects:
99
+
100
+ - [Browser Use](https://github.com/browser-use/browser-use) — browser automation for the [browser MCP](docs/browser-mcp.md) (via [browser-harness](https://github.com/browser-use/browser-harness) and the interactive-element DOM walker). MIT licensed.
101
+ - [OpenSandbox](https://github.com/opensandbox-group/OpenSandbox) — sandbox runtime used for isolated `run_command` / code execution. Apache-2.0 licensed.
102
+
96
103
  ## License
97
104
 
98
105
  MIT — see [`LICENSE`](LICENSE).
@@ -111,7 +111,9 @@ uv sync
111
111
  | `vertex-claude` | `GCP_PROJECT_ID` / `GOOGLE_CLOUD_PROJECT` / `ANTHROPIC_VERTEX_PROJECT_ID` (ADC) | `monkeybot[vertex-claude]` |
112
112
  | `aws_bedrock` | `AWS_ACCESS_KEY_ID` / `AWS_PROFILE` + `AWS_REGION` | `monkeybot[bedrock]` |
113
113
  | `huggingface` | `HF_TOKEN` (or `HUGGINGFACE_API_KEY`) | `monkeybot[huggingface]` |
114
- | `ollama` | None required — `OLLAMA_BASE_URL` (default `http://localhost:11434`) for a non-default server | `monkeybot[ollama]` |
114
+ | `ollama-cloud` | `OLLAMA_API_KEY` | `monkeybot[ollama]` |
115
+ | `ollama-local` | None required — `OLLAMA_BASE_URL` (default `http://localhost:11434`) | `monkeybot[ollama]` |
116
+ | `ollama` | Legacy auto-route (key + blank URL = cloud; explicit URL wins) | `monkeybot[ollama]` |
115
117
 
116
118
  **Agent-first dependencies.** The CLI is thin — it does **not** install provider/storage extras globally. `monkeybot new` scaffolds a `pyproject.toml` with the selected provider (and any `--with` extras). Run plain `uv sync` in the agent directory. `monkeybot run` / `chat` spawn the gateway from that project's interpreter (`.venv/bin/python`, else `uv run python`), and `doctor` checks extras in that same interpreter. For a config-only tree (just `monkeybot_config/`, no `pyproject.toml`) the gateway uses the CLI's interpreter when it already has MonkeyBot 3.x (and MemPalace if memory is on). If memory is enabled and that interpreter cannot import MemPalace, `run` / `chat` provision a cached CLI-managed venv under `~/.cache/monkeybot/runtimes/` holding `monkeybot[memory]` pinned to the running core (never rewrites a `pyproject.toml`). `doctor` reuses that cache when it is already present. Otherwise extras must be installed in the CLI env (`uv tool install --with 'monkeybot[<extra>]' monkeybot-cli`).
117
119
 
@@ -45,7 +45,7 @@ Validate check ids: `paths.agent_md.exists`, `paths.skills_path.exists`, `paths.
45
45
  | `max_turns` | `1000` | Hard cap on turns per run |
46
46
  | `summarization_model` | (main model) | Cheaper model for history summarization (env `CONTEXT_SUMMARIZATION_MODEL`) |
47
47
 
48
- Validate check ids: `model.provider.supported`, `model.name.present`. Supported YAML providers: `gemini`/`vertex`, `openai`, `anthropic`, `vertex-claude`, `huggingface`, `ollama`, `aws_bedrock`, `fake`.
48
+ Validate check ids: `model.provider.supported`, `model.name.present`. Supported YAML providers: `gemini`/`vertex`, `openai`, `anthropic`, `vertex-claude`, `huggingface`, `ollama-cloud`, `ollama-local`, `ollama`, `aws_bedrock`, `fake`.
49
49
 
50
50
  ## `gcp` / `anthropic_vertex` (non-secret identifiers)
51
51
 
@@ -5,54 +5,18 @@ Output is local-only — never sent to the agent.
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
- import os
9
- import signal
10
8
  import subprocess
11
9
  import sys
12
10
  import threading
13
11
  from pathlib import Path
14
12
 
15
- _IS_WINDOWS = sys.platform == "win32"
13
+ from monkeybot_cli.process_tree import IS_WINDOWS, kill_process_tree, popen_kwargs_for_platform
16
14
 
17
15
  # Cap capture before TUI truncation so `!yes`-style floods cannot OOM the process.
18
16
  _MAX_CAPTURE_CHARS = 100_000
19
17
  _READ_CHUNK = 4_096
20
18
 
21
19
 
22
- def _popen_kwargs_for_platform() -> dict[str, object]:
23
- if _IS_WINDOWS:
24
- # getattr fallback: this constant only exists on Windows builds of
25
- # `subprocess`, so a plain attribute access breaks importing/testing
26
- # this module on POSIX even though the branch never runs there.
27
- return {"creationflags": getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)}
28
- return {"start_new_session": True}
29
-
30
-
31
- def _kill_process_tree(pid: int) -> None:
32
- """Best-effort kill of the shell process group/tree.
33
-
34
- Swallow lookup/permission races — leader exit can make killpg raise
35
- ``PermissionError`` even though descendants still need a signal.
36
- """
37
- if _IS_WINDOWS:
38
- try:
39
- subprocess.run(
40
- ["taskkill", "/F", "/T", "/PID", str(pid)],
41
- capture_output=True,
42
- check=False,
43
- )
44
- except OSError:
45
- pass
46
- return
47
- try:
48
- os.killpg(pid, signal.SIGKILL)
49
- except (ProcessLookupError, PermissionError, OSError):
50
- try:
51
- os.kill(pid, signal.SIGKILL)
52
- except (ProcessLookupError, PermissionError, OSError):
53
- pass
54
-
55
-
56
20
  def _append_capped(chunks: list[str], total: int, data: str) -> tuple[int, bool]:
57
21
  """Append ``data`` up to the capture cap. Returns (new_total, hit_cap)."""
58
22
  remain = _MAX_CAPTURE_CHARS - total
@@ -84,7 +48,7 @@ def run_local_shell(command: str, cwd: Path, *, timeout: float = 120.0) -> tuple
84
48
  stdout=subprocess.PIPE,
85
49
  stderr=subprocess.STDOUT,
86
50
  text=True,
87
- **_popen_kwargs_for_platform(),
51
+ **popen_kwargs_for_platform(),
88
52
  )
89
53
  assert proc.stdout is not None
90
54
 
@@ -104,7 +68,7 @@ def run_local_shell(command: str, cwd: Path, *, timeout: float = 120.0) -> tuple
104
68
  state["total"], hit = _append_capped(chunks, state["total"], chunk)
105
69
  if hit:
106
70
  state["capped"] = True
107
- _kill_process_tree(proc.pid)
71
+ kill_process_tree(proc.pid)
108
72
  break
109
73
  except (ValueError, OSError):
110
74
  # stdout closed from the main thread to unblock a stuck read.
@@ -119,12 +83,12 @@ def run_local_shell(command: str, cwd: Path, *, timeout: float = 120.0) -> tuple
119
83
  proc.wait(timeout=timeout)
120
84
  except subprocess.TimeoutExpired:
121
85
  timed_out = True
122
- _kill_process_tree(proc.pid)
86
+ kill_process_tree(proc.pid)
123
87
 
124
88
  # Shell may have exited while a descendant still holds the pipe —
125
89
  # kill the tree and close stdout so the reader cannot block forever.
126
90
  if reader.is_alive():
127
- _kill_process_tree(proc.pid)
91
+ kill_process_tree(proc.pid)
128
92
  stop_reader.set()
129
93
  try:
130
94
  proc.stdout.close()
@@ -139,7 +103,7 @@ def run_local_shell(command: str, cwd: Path, *, timeout: float = 120.0) -> tuple
139
103
  reader.join(timeout=0.1)
140
104
  except Exception:
141
105
  timed_out = True
142
- _kill_process_tree(proc.pid)
106
+ kill_process_tree(proc.pid)
143
107
  stop_reader.set()
144
108
  try:
145
109
  proc.stdout.close()
@@ -149,7 +113,7 @@ def run_local_shell(command: str, cwd: Path, *, timeout: float = 120.0) -> tuple
149
113
 
150
114
  try:
151
115
  if proc.poll() is None:
152
- _kill_process_tree(proc.pid)
116
+ kill_process_tree(proc.pid)
153
117
  try:
154
118
  proc.wait(timeout=1)
155
119
  except Exception:
@@ -0,0 +1,197 @@
1
+ """monkeybot run — launch the SSE gateway as a subprocess."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import os
7
+ import signal
8
+ import subprocess
9
+ import sys
10
+ import time
11
+ from collections.abc import Callable
12
+ from pathlib import Path
13
+ from types import FrameType
14
+ from typing import Any
15
+
16
+ from monkeybot_cli.config_resolve import (
17
+ load_agent_dotenv,
18
+ load_config_doc,
19
+ resolve_agent_root,
20
+ resolve_config,
21
+ )
22
+ from monkeybot_cli.opensandbox_lifecycle import (
23
+ ensure_opensandbox_for_agent,
24
+ is_sandbox_enabled,
25
+ server_url_from_config,
26
+ )
27
+ from monkeybot_cli.process_tree import IS_WINDOWS, kill_process_tree, popen_kwargs_for_platform
28
+ from monkeybot_cli.runtime_python import gateway_argv, prepare_runtime_python
29
+
30
+ _SHUTDOWN_TIMEOUT_SECS = 5.0
31
+ _KILL_TIMEOUT_SECS = 1.0
32
+ _Handler = Callable[[int, FrameType | None], Any] | int | None
33
+
34
+
35
+ def _cli_exit_status(rc: int | None, received: int | None) -> int:
36
+ """Map a child ``wait()`` status to a CLI exit code.
37
+
38
+ ``wait()`` returns a negative signal number when the child dies from a
39
+ signal; ``SystemExit(-15)`` becomes shell status 241. Unix convention is
40
+ ``128 + signal`` (143 for SIGTERM, 130 for SIGINT).
41
+
42
+ When the shim received SIGINT, return 130 even if the child exited 0 —
43
+ that matches the conventional Ctrl-C exit status.
44
+ """
45
+ if received == signal.SIGINT:
46
+ return 130
47
+ if rc is None:
48
+ return 1
49
+ if rc < 0:
50
+ return 128 + (-rc)
51
+ return rc
52
+
53
+
54
+ def _signal_process_group(proc: subprocess.Popen[bytes], signum: int) -> None:
55
+ if proc.poll() is not None:
56
+ return
57
+ if IS_WINDOWS:
58
+ try:
59
+ proc.send_signal(signum)
60
+ except OSError as exc:
61
+ print(f"failed to signal gateway: {exc}", file=sys.stderr)
62
+ return
63
+ try:
64
+ os.killpg(proc.pid, signum)
65
+ return
66
+ except ProcessLookupError:
67
+ return
68
+ except OSError as exc:
69
+ try:
70
+ proc.send_signal(signum)
71
+ except OSError:
72
+ print(f"failed to signal gateway: {exc}", file=sys.stderr)
73
+
74
+
75
+ def run_gateway_process(
76
+ cmd: list[str],
77
+ *,
78
+ env: dict[str, str],
79
+ cwd: Path,
80
+ shutdown_timeout: float = _SHUTDOWN_TIMEOUT_SECS,
81
+ kill_timeout: float = _KILL_TIMEOUT_SECS,
82
+ ) -> int:
83
+ """Start the gateway and forward stop signals to its process group.
84
+
85
+ Electron sends SIGTERM only to this CLI shim. ``subprocess.run`` dies on
86
+ that signal and leaves uvicorn holding the port. On POSIX the child is
87
+ started in a new session so SIGTERM/SIGINT reach the whole tree (``uv run``
88
+ plus the gateway grandchild), then escalate to SIGKILL if it ignores the
89
+ signal for ``shutdown_timeout`` seconds.
90
+
91
+ ``start_new_session`` also detaches the gateway from the terminal's
92
+ foreground process group (stdin reads would raise SIGTTIN). That is fine
93
+ for uvicorn today and required for ``killpg``.
94
+
95
+ On Windows, ``send_signal(SIGTERM)`` only terminates the immediate child;
96
+ grandchildren may still be orphaned.
97
+
98
+ Interactive Ctrl-C already hits the foreground process group; forwarding
99
+ SIGINT matters here because the child is in a new session and would
100
+ otherwise keep running.
101
+ """
102
+ received: int | None = None
103
+ proc: subprocess.Popen[bytes] | None = None
104
+ signal_forwarded = False
105
+ deadline: float | None = None
106
+
107
+ def _forward(signum: int, _frame: object | None) -> None:
108
+ nonlocal received, signal_forwarded, deadline
109
+ if received is None:
110
+ received = signum
111
+ if proc is not None:
112
+ _signal_process_group(proc, signum)
113
+ signal_forwarded = True
114
+ if deadline is None:
115
+ deadline = time.monotonic() + shutdown_timeout
116
+
117
+ restored: dict[int, _Handler] = {}
118
+ forwarded = [signal.SIGINT, signal.SIGTERM]
119
+ if not IS_WINDOWS:
120
+ forwarded.append(signal.SIGHUP)
121
+ for sig in forwarded:
122
+ try:
123
+ restored[sig] = signal.signal(sig, _forward)
124
+ except (ValueError, OSError) as exc:
125
+ print(f"failed to install {sig.name} handler: {exc}", file=sys.stderr)
126
+ try:
127
+ proc = subprocess.Popen(
128
+ cmd,
129
+ env=env,
130
+ cwd=cwd,
131
+ **popen_kwargs_for_platform(),
132
+ )
133
+ if received is not None and not signal_forwarded:
134
+ _signal_process_group(proc, received)
135
+ if deadline is None:
136
+ deadline = time.monotonic() + shutdown_timeout
137
+ while True:
138
+ try:
139
+ rc = proc.wait(timeout=0.25)
140
+ except subprocess.TimeoutExpired:
141
+ if deadline is None or time.monotonic() < deadline:
142
+ continue
143
+ print(
144
+ "gateway did not exit after signal; killing process tree",
145
+ file=sys.stderr,
146
+ )
147
+ kill_process_tree(proc.pid)
148
+ try:
149
+ proc.wait(timeout=kill_timeout)
150
+ except subprocess.TimeoutExpired:
151
+ print("gateway still running after kill", file=sys.stderr)
152
+ rc = proc.returncode
153
+ return _cli_exit_status(rc, received)
154
+ finally:
155
+ for sig, handler in restored.items():
156
+ try:
157
+ signal.signal(sig, handler)
158
+ except (ValueError, OSError) as exc:
159
+ print(f"failed to restore {sig.name} handler: {exc}", file=sys.stderr)
160
+
161
+
162
+ def run_run(args: argparse.Namespace) -> int:
163
+ cwd = Path(args.cwd).expanduser().resolve() if args.cwd else None
164
+ config_path = resolve_config(args.config, cwd=cwd)
165
+ load_agent_dotenv(cwd=cwd, config_path=config_path)
166
+ env = os.environ.copy()
167
+ if config_path is not None:
168
+ env["MONKEYBOT_CONFIG"] = str(config_path)
169
+ if args.port:
170
+ env["PORT"] = str(args.port)
171
+ # --cwd intentionally pins the subprocess and runtime directory. Without
172
+ # it, an explicit config determines the agent root.
173
+ agent_root = resolve_agent_root(cwd=cwd, config_path=config_path)
174
+ if config_path is not None:
175
+ _, cfg_doc = load_config_doc(config_path)
176
+ if is_sandbox_enabled(cfg_doc):
177
+ if not ensure_opensandbox_for_agent(
178
+ agent_root,
179
+ server_url=server_url_from_config(cfg_doc),
180
+ # Fail fast: Mac app health-checks the gateway immediately.
181
+ docker_wait_secs=2.0,
182
+ ):
183
+ print(
184
+ "Continuing without a healthy OpenSandbox — run_command may fail.",
185
+ flush=True,
186
+ )
187
+ runtime = prepare_runtime_python(agent_root, config_path)
188
+ cmd = gateway_argv(runtime)
189
+ return run_gateway_process(cmd, env=env, cwd=agent_root)
190
+
191
+
192
+ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
193
+ p = subparsers.add_parser("run", help="Start the monkeybot SSE gateway")
194
+ p.add_argument("--config", help="Path to monkeybot.yaml (sets MONKEYBOT_CONFIG)")
195
+ p.add_argument("--port", type=int, help="Listen port (sets PORT)")
196
+ p.add_argument("--cwd", help="Working directory for the gateway process")
197
+ p.set_defaults(func=run_run)
@@ -24,7 +24,8 @@ PROVIDER_CHOICES: tuple[ExtraChoice, ...] = (
24
24
  ExtraChoice("vertex-claude", "Claude on Vertex AI"),
25
25
  ExtraChoice("aws_bedrock", "AWS Bedrock"),
26
26
  ExtraChoice("huggingface", "Hugging Face"),
27
- ExtraChoice("ollama", "Ollama (local)"),
27
+ ExtraChoice("ollama-cloud", "Ollama Cloud"),
28
+ ExtraChoice("ollama-local", "Ollama (local)"),
28
29
  ExtraChoice("nvidia", "NVIDIA NIM"),
29
30
  ExtraChoice("openrouter", "OpenRouter"),
30
31
  )
@@ -0,0 +1,44 @@
1
+ """Shared helpers for spawning and tearing down process groups/trees."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import signal
7
+ import subprocess
8
+ import sys
9
+
10
+ IS_WINDOWS = sys.platform == "win32"
11
+
12
+
13
+ def popen_kwargs_for_platform() -> dict[str, object]:
14
+ if IS_WINDOWS:
15
+ # getattr fallback: this constant only exists on Windows builds of
16
+ # `subprocess`, so a plain attribute access breaks importing/testing
17
+ # this module on POSIX even though the branch never runs there.
18
+ return {"creationflags": getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)}
19
+ return {"start_new_session": True}
20
+
21
+
22
+ def kill_process_tree(pid: int) -> None:
23
+ """Best-effort kill of the shell process group/tree.
24
+
25
+ Swallow lookup/permission races — leader exit can make killpg raise
26
+ ``PermissionError`` even though descendants still need a signal.
27
+ """
28
+ if IS_WINDOWS:
29
+ try:
30
+ subprocess.run(
31
+ ["taskkill", "/F", "/T", "/PID", str(pid)],
32
+ capture_output=True,
33
+ check=False,
34
+ )
35
+ except OSError:
36
+ pass
37
+ return
38
+ try:
39
+ os.killpg(pid, signal.SIGKILL)
40
+ except (ProcessLookupError, PermissionError, OSError):
41
+ try:
42
+ os.kill(pid, signal.SIGKILL)
43
+ except (ProcessLookupError, PermissionError, OSError):
44
+ pass
@@ -59,6 +59,17 @@ PROVIDER_SPECS: dict[str, ProviderSpec] = {
59
59
  (),
60
60
  credentials_optional=True,
61
61
  ),
62
+ "ollama-cloud": ProviderSpec(
63
+ ("ollama-cloud", "ollama_cloud"),
64
+ "ollama",
65
+ ("OLLAMA_API_KEY",),
66
+ ),
67
+ "ollama-local": ProviderSpec(
68
+ ("ollama-local", "ollama_local"),
69
+ "ollama",
70
+ (),
71
+ credentials_optional=True,
72
+ ),
62
73
  "fake": ProviderSpec(("fake",), None, (), credentials_optional=True),
63
74
  }
64
75
 
@@ -138,6 +138,7 @@ def ensure_workspace(dest: Path, *, force: bool) -> list[str]:
138
138
  "browser/playbooks",
139
139
  "browser/Screenshots",
140
140
  "generated-media/images",
141
+ "generated-media/video",
141
142
  ):
142
143
  path = workspace / rel
143
144
  path.mkdir(parents=True, exist_ok=True)
@@ -28,7 +28,10 @@ DB_URL=sqlite:///data/monkeybot.db
28
28
  # Hugging Face
29
29
  # HF_TOKEN=
30
30
 
31
- # Ollama (local modelsno API key needed)
31
+ # Ollama Cloud (model.provider: ollama-cloud)key from ollama.com/settings/keys
32
+ # OLLAMA_API_KEY=
33
+
34
+ # Ollama local (model.provider: ollama-local) — no API key needed
32
35
  # OLLAMA_BASE_URL=http://localhost:11434
33
36
 
34
37
  # Optional web search
@@ -87,7 +87,7 @@ paths:
87
87
  workspace_root: ./workspace
88
88
 
89
89
  model:
90
- # gemini | openai | anthropic | vertex-claude | huggingface | ollama | nvidia | openrouter | aws_bedrock | fake
90
+ # gemini | openai | anthropic | vertex-claude | huggingface | ollama-cloud | ollama-local | ollama | nvidia | openrouter | aws_bedrock | fake
91
91
  provider: gemini
92
92
  name: gemini-3.1-flash-live-preview
93
93
  temperature: 0.7
@@ -214,6 +214,18 @@ todo_list:
214
214
  enabled: true
215
215
  mirror_to_disk: true
216
216
 
217
+ # Desktop-only, macOS-only local computer control (open/reveal files & folders,
218
+ # launch apps, read/write the clipboard, browse/move/trash files) via
219
+ # computer_* tools. Off by default — server/Cloud Run deployments should never
220
+ # set this. The Monkeybot desktop app sets MONKEYBOT_COMPUTER_TOOLS when it
221
+ # spawns a gateway with this feature turned on in its settings; every computer_*
222
+ # call still asks for approval by default (a built-in permissions.yaml baseline,
223
+ # not configurable here) and "Always allow" is scoped to the exact action, not
224
+ # the whole tool. See monkeybot_config/permissions.yaml and
225
+ # monkeybot_config/approvals.json (machine-written, do not hand-edit).
226
+ computer:
227
+ enabled: false
228
+
217
229
  sandbox:
218
230
  # Opt-in: requires Docker Desktop (OpenSandbox). Leave false for normal Mac
219
231
  # installs so the gateway starts without Docker. When enabled, ``monkeybot run``
@@ -8,6 +8,7 @@ import time
8
8
  from pathlib import Path
9
9
 
10
10
  import monkeybot_cli.chat_local_shell as chat_local_shell
11
+ import monkeybot_cli.process_tree as process_tree
11
12
  from monkeybot_cli.chat_local_shell import run_local_shell, truncate_output
12
13
 
13
14
 
@@ -30,7 +31,7 @@ def test_run_local_shell_uses_cwd(tmp_path: Path) -> None:
30
31
 
31
32
 
32
33
  def test_kill_process_tree_swallows_permission_error(monkeypatch) -> None:
33
- monkeypatch.setattr(chat_local_shell, "_IS_WINDOWS", False)
34
+ monkeypatch.setattr(process_tree, "IS_WINDOWS", False)
34
35
 
35
36
  def _boom_killpg(pid: int, sig: int) -> None:
36
37
  raise PermissionError("race")
@@ -38,9 +39,9 @@ def test_kill_process_tree_swallows_permission_error(monkeypatch) -> None:
38
39
  def _boom_kill(pid: int, sig: int) -> None:
39
40
  raise ProcessLookupError()
40
41
 
41
- monkeypatch.setattr(chat_local_shell.os, "killpg", _boom_killpg)
42
- monkeypatch.setattr(chat_local_shell.os, "kill", _boom_kill)
43
- chat_local_shell._kill_process_tree(4321) # must not raise
42
+ monkeypatch.setattr(process_tree.os, "killpg", _boom_killpg)
43
+ monkeypatch.setattr(process_tree.os, "kill", _boom_kill)
44
+ process_tree.kill_process_tree(4321) # must not raise
44
45
 
45
46
 
46
47
  def test_run_local_shell_timeout(tmp_path: Path) -> None:
@@ -104,22 +105,22 @@ def test_run_local_shell_timeout_kills_grandchildren(tmp_path: Path) -> None:
104
105
 
105
106
 
106
107
  def test_popen_kwargs_use_process_group_on_posix(monkeypatch) -> None:
107
- monkeypatch.setattr(chat_local_shell, "_IS_WINDOWS", False)
108
- assert chat_local_shell._popen_kwargs_for_platform() == {"start_new_session": True}
108
+ monkeypatch.setattr(process_tree, "IS_WINDOWS", False)
109
+ assert process_tree.popen_kwargs_for_platform() == {"start_new_session": True}
109
110
 
110
111
 
111
112
  def test_popen_kwargs_use_new_process_group_on_windows(monkeypatch) -> None:
112
- monkeypatch.setattr(chat_local_shell, "_IS_WINDOWS", True)
113
- kwargs = chat_local_shell._popen_kwargs_for_platform()
113
+ monkeypatch.setattr(process_tree, "IS_WINDOWS", True)
114
+ kwargs = process_tree.popen_kwargs_for_platform()
114
115
  assert set(kwargs) == {"creationflags"}
115
116
 
116
117
 
117
118
  def test_kill_process_tree_uses_killpg_on_posix(monkeypatch) -> None:
118
- monkeypatch.setattr(chat_local_shell, "_IS_WINDOWS", False)
119
+ monkeypatch.setattr(process_tree, "IS_WINDOWS", False)
119
120
  calls: list[tuple[int, int]] = []
120
- monkeypatch.setattr(chat_local_shell.os, "killpg", lambda pid, sig: calls.append((pid, sig)))
121
- chat_local_shell._kill_process_tree(4321)
122
- assert calls == [(4321, chat_local_shell.signal.SIGKILL)]
121
+ monkeypatch.setattr(process_tree.os, "killpg", lambda pid, sig: calls.append((pid, sig)))
122
+ process_tree.kill_process_tree(4321)
123
+ assert calls == [(4321, process_tree.signal.SIGKILL)]
123
124
 
124
125
 
125
126
  def test_kill_process_tree_uses_taskkill_on_windows(monkeypatch) -> None:
@@ -128,14 +129,14 @@ def test_kill_process_tree_uses_taskkill_on_windows(monkeypatch) -> None:
128
129
  os.killpg doesn't exist on Windows, so the POSIX-only kill path would
129
130
  crash a timed-out `!` command instead of finishing the tool block there.
130
131
  """
131
- monkeypatch.setattr(chat_local_shell, "_IS_WINDOWS", True)
132
+ monkeypatch.setattr(process_tree, "IS_WINDOWS", True)
132
133
  calls: list[list[str]] = []
133
134
  monkeypatch.setattr(
134
- chat_local_shell.subprocess,
135
+ process_tree.subprocess,
135
136
  "run",
136
137
  lambda argv, **kwargs: calls.append(list(argv)),
137
138
  )
138
- chat_local_shell._kill_process_tree(4321)
139
+ process_tree.kill_process_tree(4321)
139
140
  assert calls == [["taskkill", "/F", "/T", "/PID", "4321"]]
140
141
 
141
142
 
@@ -21,6 +21,8 @@ def test_normalize_extra_token_features_and_providers() -> None:
21
21
  assert normalize_extra_token("anthropic") == "claude"
22
22
  assert normalize_extra_token("aws_bedrock") == "bedrock"
23
23
  assert normalize_extra_token("claude") == "claude"
24
+ assert normalize_extra_token("ollama-cloud") == "ollama"
25
+ assert normalize_extra_token("ollama-local") == "ollama"
24
26
  assert normalize_extra_token("fake") is None
25
27
  assert normalize_extra_token("not-a-real-extra") is None
26
28
 
@@ -42,6 +44,9 @@ def test_extra_module_covers_catalog_extras() -> None:
42
44
  def test_provider_extra_name() -> None:
43
45
  assert provider_extra_name("openai") == "openai"
44
46
  assert provider_extra_name("anthropic") == "claude"
47
+ assert provider_extra_name("ollama-cloud") == "ollama"
48
+ assert provider_extra_name("ollama-local") == "ollama"
49
+ assert provider_extra_name("ollama") == "ollama"
45
50
  assert provider_extra_name("fake") is None
46
51
 
47
52