gemcode 0.4.24__tar.gz → 0.4.25__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 (209) hide show
  1. {gemcode-0.4.24/src/gemcode.egg-info → gemcode-0.4.25}/PKG-INFO +1 -1
  2. {gemcode-0.4.24 → gemcode-0.4.25}/pyproject.toml +1 -1
  3. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/sse_adapter.py +57 -14
  4. {gemcode-0.4.24 → gemcode-0.4.25/src/gemcode.egg-info}/PKG-INFO +1 -1
  5. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/SOURCES.txt +1 -0
  6. gemcode-0.4.25/tests/test_web_permissions_hitl.py +71 -0
  7. {gemcode-0.4.24 → gemcode-0.4.25}/LICENSE +0 -0
  8. {gemcode-0.4.24 → gemcode-0.4.25}/MANIFEST.in +0 -0
  9. {gemcode-0.4.24 → gemcode-0.4.25}/README.md +0 -0
  10. {gemcode-0.4.24 → gemcode-0.4.25}/setup.cfg +0 -0
  11. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/__init__.py +0 -0
  12. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/__main__.py +0 -0
  13. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/a2a_bridge.py +0 -0
  14. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent.py +0 -0
  15. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_habits.py +0 -0
  16. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_intelligence.py +0 -0
  17. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_mesh.py +0 -0
  18. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_triggers.py +0 -0
  19. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/audit.py +0 -0
  20. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/autocompact.py +0 -0
  21. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/automations.py +0 -0
  22. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/autotune.py +0 -0
  23. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/callbacks.py +0 -0
  24. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/capability_routing.py +0 -0
  25. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/checkpoints.py +0 -0
  26. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/cli.py +0 -0
  27. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/codebase_awareness.py +0 -0
  28. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/compaction.py +0 -0
  29. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/computer_use/__init__.py +0 -0
  30. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/computer_use/browser_computer.py +0 -0
  31. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/config.py +0 -0
  32. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/context_budget.py +0 -0
  33. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/context_warning.py +0 -0
  34. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/credentials.py +0 -0
  35. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/curated_memory.py +0 -0
  36. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/delegation_learning.py +0 -0
  37. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/dynamic_policy.py +0 -0
  38. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/evals/harness.py +0 -0
  39. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/event_bus.py +0 -0
  40. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/fleet_reports.py +0 -0
  41. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/habit_chains.py +0 -0
  42. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/habit_runs.py +0 -0
  43. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/hitl_session.py +0 -0
  44. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/hooks.py +0 -0
  45. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/ide_protocol.py +0 -0
  46. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/ide_stdio.py +0 -0
  47. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/intent_classifier.py +0 -0
  48. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/interactions.py +0 -0
  49. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/invoke.py +0 -0
  50. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_client.py +0 -0
  51. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_daemon.py +0 -0
  52. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_ipc.py +0 -0
  53. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_job_store.py +0 -0
  54. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/learning.py +0 -0
  55. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/limits.py +0 -0
  56. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/live_audio_engine.py +0 -0
  57. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/logging_config.py +0 -0
  58. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/mcp_loader.py +0 -0
  59. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/__init__.py +0 -0
  60. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/embedding_memory_service.py +0 -0
  61. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/file_memory_service.py +0 -0
  62. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/modality_tools.py +0 -0
  63. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/model_errors.py +0 -0
  64. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/model_routing.py +0 -0
  65. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/multimodal_input.py +0 -0
  66. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/openapi_loader.py +0 -0
  67. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/org.py +0 -0
  68. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/output_styles.py +0 -0
  69. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/paths.py +0 -0
  70. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/permissions.py +0 -0
  71. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/__init__.py +0 -0
  72. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  73. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  74. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/policy_profile.py +0 -0
  75. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/pricing.py +0 -0
  76. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/prompt_suggestions.py +0 -0
  77. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/__init__.py +0 -0
  78. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/config.py +0 -0
  79. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/deps.py +0 -0
  80. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/engine.py +0 -0
  81. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/stop_hooks.py +0 -0
  82. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/token_budget.py +0 -0
  83. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/transitions.py +0 -0
  84. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query_sanitizer.py +0 -0
  85. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/refine.py +0 -0
  86. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/repl_commands.py +0 -0
  87. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/repl_slash.py +0 -0
  88. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/review_agent.py +0 -0
  89. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/rules.py +0 -0
  90. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/self_healing.py +0 -0
  91. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_runtime.py +0 -0
  92. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_store.py +0 -0
  93. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_summariser.py +0 -0
  94. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/skills.py +0 -0
  95. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/slash_commands.py +0 -0
  96. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/thinking.py +0 -0
  97. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_prompt_manifest.py +0 -0
  98. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_registry.py +0 -0
  99. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_result_store.py +0 -0
  100. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_synthesis.py +0 -0
  101. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/__init__.py +0 -0
  102. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/automations_tools.py +0 -0
  103. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/bash.py +0 -0
  104. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/browser.py +0 -0
  105. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/compress_memory.py +0 -0
  106. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/curated_memory.py +0 -0
  107. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/edit.py +0 -0
  108. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/filesystem.py +0 -0
  109. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/notebook.py +0 -0
  110. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/notes.py +0 -0
  111. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/org_tools.py +0 -0
  112. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/repo_map.py +0 -0
  113. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/search.py +0 -0
  114. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/shell.py +0 -0
  115. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/shell_gate.py +0 -0
  116. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/skills.py +0 -0
  117. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/subtask.py +0 -0
  118. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/tasks.py +0 -0
  119. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/think.py +0 -0
  120. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/todo.py +0 -0
  121. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/user_choice.py +0 -0
  122. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/veomem_tools.py +0 -0
  123. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/web.py +0 -0
  124. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/web_search.py +0 -0
  125. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools_inspector.py +0 -0
  126. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/trust.py +0 -0
  127. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/input_handler.py +0 -0
  128. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/scrollback.py +0 -0
  129. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/spinner.py +0 -0
  130. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/welcome_banner.py +0 -0
  131. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/welcome_rich.py +0 -0
  132. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/veomem_bridge.py +0 -0
  133. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/version.py +0 -0
  134. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/vertex.py +0 -0
  135. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/wal.py +0 -0
  136. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/__init__.py +0 -0
  137. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/chat_skills.py +0 -0
  138. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/customize_api.py +0 -0
  139. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/files_api.py +0 -0
  140. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/fleet_api.py +0 -0
  141. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/hitl_bridge.py +0 -0
  142. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/preview_api.py +0 -0
  143. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/project_root.py +0 -0
  144. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/runtime_api.py +0 -0
  145. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/serve_bind.py +0 -0
  146. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/serve_state.py +0 -0
  147. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/server.py +0 -0
  148. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/sessions_api.py +0 -0
  149. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/terminal_api.py +0 -0
  150. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/terminal_repl.py +0 -0
  151. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/ui_chat_store.py +0 -0
  152. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/web_config_api.py +0 -0
  153. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/web_sse_compat.py +0 -0
  154. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/workspace_panel_api.py +0 -0
  155. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/workspace_hints.py +0 -0
  156. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/dependency_links.txt +0 -0
  157. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/entry_points.txt +0 -0
  158. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/requires.txt +0 -0
  159. {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/top_level.txt +0 -0
  160. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_add_dir.py +0 -0
  161. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_habits.py +0 -0
  162. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_instruction.py +0 -0
  163. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_mesh.py +0 -0
  164. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_autocompact.py +0 -0
  165. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_automations.py +0 -0
  166. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_capability_routing.py +0 -0
  167. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_checkpoint_diff_command.py +0 -0
  168. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_cli_init.py +0 -0
  169. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_compress_memory_tool.py +0 -0
  170. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_computer_use_permissions.py +0 -0
  171. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_context_budget.py +0 -0
  172. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_context_warning.py +0 -0
  173. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_credentials.py +0 -0
  174. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_eval_harness_layout.py +0 -0
  175. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_event_bus.py +0 -0
  176. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_files_api.py +0 -0
  177. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_fleet_reports.py +0 -0
  178. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_habit_chains.py +0 -0
  179. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_habit_runs.py +0 -0
  180. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_hosted_tenant.py +0 -0
  181. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_ide_stdio_attachments.py +0 -0
  182. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_interactive_permission_ask.py +0 -0
  183. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_kaira_ipc_paths.py +0 -0
  184. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_kaira_scheduler.py +0 -0
  185. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_modality_tools.py +0 -0
  186. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_error_retry.py +0 -0
  187. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_errors.py +0 -0
  188. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_routing.py +0 -0
  189. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_multimodal_input.py +0 -0
  190. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_output_styles_and_rules.py +0 -0
  191. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_paths.py +0 -0
  192. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_permissions.py +0 -0
  193. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_preview_proxy.py +0 -0
  194. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_prompt_suggestions.py +0 -0
  195. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_repl_commands.py +0 -0
  196. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_repl_slash.py +0 -0
  197. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_session_runtime_cache.py +0 -0
  198. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_skills.py +0 -0
  199. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_slash_commands.py +0 -0
  200. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_slash_completion_registry.py +0 -0
  201. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_sse_confirmation_batch.py +0 -0
  202. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_thinking_config.py +0 -0
  203. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_token_budget.py +0 -0
  204. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tool_context_circulation.py +0 -0
  205. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tools.py +0 -0
  206. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tools_inspector.py +0 -0
  207. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_web_server.py +0 -0
  208. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_web_sse_adapter.py +0 -0
  209. {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_workspace_hints.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.4.24
3
+ Version: 0.4.25
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gemcode"
7
- version = "0.4.24"
7
+ version = "0.4.25"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -489,17 +489,33 @@ def _inject_web_code_context(cfg: GemCodeConfig, prompt: str, req: dict[str, Any
489
489
  "or type @path — unless they mean the whole project (see below)."
490
490
  )
491
491
 
492
- lines.extend(
493
- [
494
- 'When the user says "this file", "the current one", or similar, use the active / @-referenced file above.',
495
- 'When they ask to analyze the whole codebase, project, repo, or "all files", start with `repo_map` and '
496
- '`list_directory` on `.` — do not ask which file first.',
497
- "**Web UI permissions** — shell and mutating tools pause for an **inline Yes/No card in the chat** "
498
- "(above the composer). Do **not** tell the user to open a dialog, popup, terminal, or separate Approve button — "
499
- "just wait; the UI card is the approval UI. After they tap Yes or No, continue automatically.",
500
- "When Auto-approve / Super mode is on, tools run without asking — do not mention approvals.",
501
- ]
492
+ # Permission mode for THIS turn (must match actual HITL / auto-approve behavior).
493
+ lines.append(
494
+ 'When the user says "this file", "the current one", or similar, use the active / @-referenced file above.'
502
495
  )
496
+ lines.append(
497
+ 'When they ask to analyze the whole codebase, project, repo, or "all files", start with `repo_map` and '
498
+ '`list_directory` on `.` — do not ask which file first.'
499
+ )
500
+ auto_on = bool(
501
+ getattr(cfg, "yes_to_all", False)
502
+ or getattr(cfg, "super_mode", False)
503
+ or not getattr(cfg, "_web_interactive_hitl", True)
504
+ )
505
+ if auto_on:
506
+ lines.append(
507
+ "**Web UI permissions — AUTO-APPROVE is ON for this turn.** "
508
+ "Shell and mutating tools run immediately with **no** Yes/No card. "
509
+ "Never mention Approve, Deny, approval prompts, dialogs, or waiting for the user — "
510
+ "just run tools and report what you did."
511
+ )
512
+ else:
513
+ lines.append(
514
+ "**Web UI permissions — interactive.** Shell and mutating tools pause for an "
515
+ "**inline Yes/No card in the chat** (also pinned above the composer). "
516
+ "Do **not** invent Approve/Deny dialog text or tell the user to open a popup — "
517
+ "wait silently; after they tap Yes or No the turn continues."
518
+ )
503
519
 
504
520
  if mode == "agents":
505
521
  lines.extend(
@@ -922,6 +938,7 @@ def _apply_web_permissions(cfg: GemCodeConfig, req: dict[str, Any]) -> None:
922
938
  }
923
939
  object.__setattr__(cfg, "_web_auto_approve", normalized)
924
940
 
941
+ # UI is source of truth for web chat — do not leave env GEMCODE_SUPER_MODE stuck on.
925
942
  super_mode = bool(perms.get("super_mode"))
926
943
  if super_mode:
927
944
  cfg.super_mode = True
@@ -931,6 +948,7 @@ def _apply_web_permissions(cfg: GemCodeConfig, req: dict[str, Any]) -> None:
931
948
  object.__setattr__(cfg, "_web_interactive_hitl", False)
932
949
  return
933
950
 
951
+ cfg.super_mode = False
934
952
  if all(normalized.values()):
935
953
  cfg.yes_to_all = True
936
954
  cfg.interactive_permission_ask = False
@@ -948,13 +966,33 @@ def _apply_web_permissions(cfg: GemCodeConfig, req: dict[str, Any]) -> None:
948
966
 
949
967
 
950
968
  def _configure_web_permissions(cfg: GemCodeConfig, req: dict[str, Any]) -> None:
951
- """Web chat defaults to interactive Approve/Deny unless everything is auto-approved."""
969
+ """Web chat HITL follows the UI request, not process-level GEMCODE_SUPER_MODE.
970
+
971
+ Hosted tenant images historically set ``GEMCODE_SUPER_MODE=1`` so mesh/jobs are
972
+ unattended. That must not silently skip Yes/No cards when the user has
973
+ Auto-approve off in the web UI. Mesh workers still use
974
+ ``GEMCODE_MESH_WORKER_UNATTENDED`` independently.
975
+ """
952
976
  object.__setattr__(cfg, "_gemcode_web_sse", True)
953
- _apply_web_permissions(cfg, req)
954
- if not isinstance(req.get("permissions"), dict):
977
+
978
+ perms = req.get("permissions")
979
+ has_perms = isinstance(perms, dict)
980
+
981
+ # Clear env-applied super mode before applying the UI payload.
982
+ if not (has_perms and bool(perms.get("super_mode"))):
983
+ cfg.super_mode = False
955
984
  cfg.yes_to_all = False
956
985
  cfg.interactive_permission_ask = True
957
986
  object.__setattr__(cfg, "_web_interactive_hitl", True)
987
+
988
+ if has_perms:
989
+ _apply_web_permissions(cfg, req)
990
+ else:
991
+ cfg.super_mode = False
992
+ cfg.yes_to_all = False
993
+ cfg.interactive_permission_ask = True
994
+ object.__setattr__(cfg, "_web_interactive_hitl", True)
995
+
958
996
  _ensure_web_hitl(cfg)
959
997
  if os.environ.get("GEMCODE_WEB_YES_TO_ALL", "").lower() in ("1", "true", "yes", "on"):
960
998
  cfg.yes_to_all = True
@@ -963,8 +1001,9 @@ def _configure_web_permissions(cfg: GemCodeConfig, req: dict[str, Any]) -> None:
963
1001
 
964
1002
 
965
1003
  def _ensure_web_hitl(cfg: GemCodeConfig) -> None:
966
- """Web chat always uses the UI approval bridge when tools are not fully auto-approved."""
1004
+ """Web chat uses the UI approval bridge when tools are not fully auto-approved."""
967
1005
  if getattr(cfg, "yes_to_all", False) or getattr(cfg, "super_mode", False):
1006
+ object.__setattr__(cfg, "_web_interactive_hitl", False)
968
1007
  return
969
1008
  cfg.interactive_permission_ask = True
970
1009
  object.__setattr__(cfg, "_web_interactive_hitl", True)
@@ -1248,6 +1287,10 @@ async def run_adapter(req: dict[str, Any]) -> None:
1248
1287
  "model": model,
1249
1288
  "project_root": str(cfg.project_root),
1250
1289
  "workspace_mode": workspace_mode,
1290
+ "hitl_interactive": bool(getattr(cfg, "_web_interactive_hitl", False)),
1291
+ "auto_approve": bool(
1292
+ getattr(cfg, "yes_to_all", False) or getattr(cfg, "super_mode", False)
1293
+ ),
1251
1294
  **({"skill": resolved.skill_name} if resolved.skill_name else {}),
1252
1295
  }
1253
1296
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.4.24
3
+ Version: 0.4.25
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -201,6 +201,7 @@ tests/test_token_budget.py
201
201
  tests/test_tool_context_circulation.py
202
202
  tests/test_tools.py
203
203
  tests/test_tools_inspector.py
204
+ tests/test_web_permissions_hitl.py
204
205
  tests/test_web_server.py
205
206
  tests/test_web_sse_adapter.py
206
207
  tests/test_workspace_hints.py
@@ -0,0 +1,71 @@
1
+ """Web UI permissions must override process-level GEMCODE_SUPER_MODE."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from gemcode.config import GemCodeConfig, apply_super_mode
8
+ from gemcode.web import sse_adapter
9
+
10
+
11
+ def test_web_permissions_clear_env_super_mode(tmp_path: Path, monkeypatch) -> None:
12
+ monkeypatch.setenv("GEMCODE_SUPER_MODE", "1")
13
+ cfg = GemCodeConfig(project_root=tmp_path)
14
+ assert cfg.super_mode is True
15
+ apply_super_mode(cfg)
16
+ assert cfg.yes_to_all is True
17
+
18
+ sse_adapter._configure_web_permissions(
19
+ cfg,
20
+ {
21
+ "permissions": {
22
+ "super_mode": False,
23
+ "auto_approve": {
24
+ "bash": False,
25
+ "file_read": False,
26
+ "file_write": False,
27
+ "web_search": False,
28
+ },
29
+ }
30
+ },
31
+ )
32
+ assert cfg.super_mode is False
33
+ assert cfg.yes_to_all is False
34
+ assert getattr(cfg, "_web_interactive_hitl") is True
35
+
36
+
37
+ def test_web_permissions_ui_super_mode_on(tmp_path: Path, monkeypatch) -> None:
38
+ monkeypatch.delenv("GEMCODE_SUPER_MODE", raising=False)
39
+ cfg = GemCodeConfig(project_root=tmp_path)
40
+ cfg.super_mode = False
41
+ cfg.yes_to_all = False
42
+
43
+ sse_adapter._configure_web_permissions(
44
+ cfg,
45
+ {"permissions": {"super_mode": True, "auto_approve": {}}},
46
+ )
47
+ assert cfg.super_mode is True
48
+ assert cfg.yes_to_all is True
49
+ assert getattr(cfg, "_web_interactive_hitl") is False
50
+
51
+
52
+ def test_inject_web_context_auto_approve_copy(tmp_path: Path) -> None:
53
+ cfg = GemCodeConfig(project_root=tmp_path)
54
+ cfg.yes_to_all = True
55
+ object.__setattr__(cfg, "_web_workspace_mode", "code")
56
+ object.__setattr__(cfg, "_web_interactive_hitl", False)
57
+ out = sse_adapter._inject_web_code_context(cfg, "hello", {})
58
+ assert "AUTO-APPROVE is ON" in out
59
+ assert "Never mention Approve" in out
60
+ assert "inline Yes/No card" not in out
61
+
62
+
63
+ def test_inject_web_context_interactive_copy(tmp_path: Path) -> None:
64
+ cfg = GemCodeConfig(project_root=tmp_path)
65
+ cfg.super_mode = False
66
+ cfg.yes_to_all = False
67
+ object.__setattr__(cfg, "_web_workspace_mode", "code")
68
+ object.__setattr__(cfg, "_web_interactive_hitl", True)
69
+ out = sse_adapter._inject_web_code_context(cfg, "hello", {})
70
+ assert "inline Yes/No card" in out
71
+ assert "AUTO-APPROVE is ON" not in out
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes