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.
- {gemcode-0.4.24/src/gemcode.egg-info → gemcode-0.4.25}/PKG-INFO +1 -1
- {gemcode-0.4.24 → gemcode-0.4.25}/pyproject.toml +1 -1
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/sse_adapter.py +57 -14
- {gemcode-0.4.24 → gemcode-0.4.25/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/SOURCES.txt +1 -0
- gemcode-0.4.25/tests/test_web_permissions_hitl.py +71 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/LICENSE +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/MANIFEST.in +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/README.md +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/setup.cfg +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/__main__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/a2a_bridge.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_habits.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_intelligence.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_mesh.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/agent_triggers.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/audit.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/automations.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/autotune.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/checkpoints.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/cli.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/codebase_awareness.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/compaction.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/config.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/credentials.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/curated_memory.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/delegation_learning.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/dynamic_policy.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/evals/harness.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/event_bus.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/fleet_reports.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/habit_chains.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/habit_runs.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/hooks.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/ide_protocol.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/ide_stdio.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/interactions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/invoke.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_client.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_daemon.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_ipc.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/kaira_job_store.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/learning.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/limits.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/multimodal_input.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/org.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/output_styles.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/paths.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/permissions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/policy_profile.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/pricing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/config.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/query_sanitizer.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/refine.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/rules.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/self_healing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_store.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/session_summariser.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/skills.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/thinking.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tool_synthesis.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/automations_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/compress_memory.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/curated_memory.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/org_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/skills.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/user_choice.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/veomem_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/trust.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/veomem_bridge.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/version.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/vertex.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/wal.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/chat_skills.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/customize_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/files_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/fleet_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/hitl_bridge.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/preview_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/project_root.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/runtime_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/serve_bind.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/serve_state.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/server.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/sessions_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/terminal_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/ui_chat_store.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/web_config_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/web_sse_compat.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/web/workspace_panel_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_add_dir.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_habits.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_agent_mesh.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_autocompact.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_automations.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_capability_routing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_checkpoint_diff_command.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_cli_init.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_compress_memory_tool.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_context_budget.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_context_warning.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_credentials.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_eval_harness_layout.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_event_bus.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_files_api.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_fleet_reports.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_habit_chains.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_habit_runs.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_hosted_tenant.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_ide_stdio_attachments.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_kaira_ipc_paths.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_kaira_scheduler.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_modality_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_errors.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_model_routing.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_multimodal_input.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_output_styles_and_rules.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_paths.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_permissions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_preview_proxy.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_repl_commands.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_repl_slash.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_session_runtime_cache.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_skills.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_slash_commands.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_slash_completion_registry.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_sse_confirmation_batch.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_thinking_config.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_token_budget.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tools.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_web_server.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_web_sse_adapter.py +0 -0
- {gemcode-0.4.24 → gemcode-0.4.25}/tests/test_workspace_hints.py +0 -0
|
@@ -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
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
|
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
|
-
|
|
954
|
-
|
|
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
|
|
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
|
)
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|