gemcode 0.3.57__tar.gz → 0.3.59__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.3.57/src/gemcode.egg-info → gemcode-0.3.59}/PKG-INFO +1 -1
- {gemcode-0.3.57 → gemcode-0.3.59}/pyproject.toml +1 -1
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/capability_routing.py +8 -15
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/session_runtime.py +55 -0
- {gemcode-0.3.57 → gemcode-0.3.59/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.57 → gemcode-0.3.59}/LICENSE +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/MANIFEST.in +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/README.md +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/setup.cfg +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/config.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/invoke.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/kairos_daemon.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/version.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/web/claude_sse_adapter.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_claude_web_adapter_sse.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_credentials.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_kairos_scheduler.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_paths.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_permissions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_tools.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.57 → gemcode-0.3.59}/tests/test_workspace_hints.py +0 -0
|
@@ -8,6 +8,9 @@ outer/inner loops intact.
|
|
|
8
8
|
It is intentionally conservative:
|
|
9
9
|
- It only enables capabilities (turns them on), it does not disable
|
|
10
10
|
explicitly requested capabilities.
|
|
11
|
+
- Computer-use is NEVER auto-enabled from prompt heuristics. It requires
|
|
12
|
+
an explicit user action (/computer on or capability_mode=computer) because
|
|
13
|
+
it switches the model, launches a browser, and blocks file-system tools.
|
|
11
14
|
- Computer-use model selection is enforced at model-routing precedence, and
|
|
12
15
|
tool execution remains permission-gated via `callbacks.py`.
|
|
13
16
|
"""
|
|
@@ -44,19 +47,6 @@ _EMBEDDINGS_TRIGGERS = [
|
|
|
44
47
|
"relevant docs",
|
|
45
48
|
]
|
|
46
49
|
|
|
47
|
-
_COMPUTER_TRIGGERS = [
|
|
48
|
-
"click",
|
|
49
|
-
"button",
|
|
50
|
-
"double click",
|
|
51
|
-
"type into",
|
|
52
|
-
"navigate",
|
|
53
|
-
"browser",
|
|
54
|
-
"open website",
|
|
55
|
-
"scroll",
|
|
56
|
-
"ui automation",
|
|
57
|
-
"open tab",
|
|
58
|
-
]
|
|
59
|
-
|
|
60
50
|
_AUDIO_TRIGGERS = [
|
|
61
51
|
"audio",
|
|
62
52
|
"voice",
|
|
@@ -125,13 +115,16 @@ def apply_capability_routing(
|
|
|
125
115
|
return
|
|
126
116
|
|
|
127
117
|
# Auto mode: prompt heuristics.
|
|
118
|
+
# NOTE: computer-use is deliberately NOT auto-triggered here.
|
|
119
|
+
# It must be enabled explicitly via /computer on or capability_mode=computer.
|
|
120
|
+
# Auto-enabling it causes the model to switch to the computer-use preview
|
|
121
|
+
# for any prompt containing words like "navigate"/"scroll"/"browser",
|
|
122
|
+
# which blocks normal file and code tools for completely unrelated tasks.
|
|
128
123
|
if mode == "auto":
|
|
129
124
|
if _contains_any(p_norm, _RESEARCH_TRIGGERS):
|
|
130
125
|
enable_research()
|
|
131
126
|
if _contains_any(p_norm, _EMBEDDINGS_TRIGGERS):
|
|
132
127
|
enable_embeddings()
|
|
133
|
-
if _contains_any(p_norm, _COMPUTER_TRIGGERS):
|
|
134
|
-
enable_computer()
|
|
135
128
|
if _contains_any(p_norm, _AUDIO_TRIGGERS):
|
|
136
129
|
enable_audio()
|
|
137
130
|
return
|
|
@@ -35,6 +35,60 @@ def session_db_path(cfg: GemCodeConfig) -> Path:
|
|
|
35
35
|
return cfg.project_root / ".gemcode" / "sessions.sqlite"
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _wrap_computer_use_tools_with_safety_ack(llm_request) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Gemini Computer Use models may include `safety_decision` in tool call args.
|
|
41
|
+
The client must acknowledge it in the corresponding FunctionResponse or the
|
|
42
|
+
API returns HTTP 400.
|
|
43
|
+
|
|
44
|
+
ADK's ComputerUseTool returns only image/url by default, so we wrap the tool
|
|
45
|
+
functions to (a) ignore `safety_decision` for execution and (b) include
|
|
46
|
+
`safety_acknowledgement="true"` in the tool result when present.
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
from google.adk.tools.computer_use.computer_use_tool import ComputerUseTool
|
|
50
|
+
except Exception:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
tools_dict = getattr(llm_request, "tools_dict", None)
|
|
55
|
+
if not isinstance(tools_dict, dict) or not tools_dict:
|
|
56
|
+
return
|
|
57
|
+
except Exception:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
# Wrap each ComputerUseTool's underlying function in-place.
|
|
61
|
+
for tool_name, tool in list(tools_dict.items()):
|
|
62
|
+
try:
|
|
63
|
+
if not isinstance(tool, ComputerUseTool):
|
|
64
|
+
continue
|
|
65
|
+
original_func = getattr(tool, "func", None)
|
|
66
|
+
if original_func is None:
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
async def wrapped(*, _orig=original_func, _tool_name=tool_name, **args):
|
|
70
|
+
sd = None
|
|
71
|
+
if isinstance(args, dict) and "safety_decision" in args:
|
|
72
|
+
sd = args.pop("safety_decision", None)
|
|
73
|
+
result = await _orig(**args)
|
|
74
|
+
if sd is None:
|
|
75
|
+
return result
|
|
76
|
+
# Acknowledge the safety decision as required by Gemini computer-use.
|
|
77
|
+
if isinstance(result, dict):
|
|
78
|
+
out = dict(result)
|
|
79
|
+
out["safety_acknowledgement"] = "true"
|
|
80
|
+
return out
|
|
81
|
+
return {"result": result, "safety_acknowledgement": "true"}
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
wrapped.__name__ = tool_name
|
|
85
|
+
except Exception:
|
|
86
|
+
pass
|
|
87
|
+
tool.func = wrapped
|
|
88
|
+
except Exception:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
|
|
38
92
|
def _playwright_available() -> bool:
|
|
39
93
|
"""
|
|
40
94
|
Quick synchronous check: does a usable Playwright browser executable exist?
|
|
@@ -147,6 +201,7 @@ def _make_safe_computer_toolset(computer):
|
|
|
147
201
|
await self._inner.process_llm_request(
|
|
148
202
|
tool_context=tool_context, llm_request=llm_request
|
|
149
203
|
)
|
|
204
|
+
_wrap_computer_use_tools_with_safety_ack(llm_request)
|
|
150
205
|
except Exception as exc:
|
|
151
206
|
if not self._broken:
|
|
152
207
|
self._broken = True
|
|
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
|