gemcode 0.3.56__tar.gz → 0.3.58__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.56/src/gemcode.egg-info → gemcode-0.3.58}/PKG-INFO +1 -1
- {gemcode-0.3.56 → gemcode-0.3.58}/pyproject.toml +1 -1
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/session_runtime.py +81 -3
- {gemcode-0.3.56 → gemcode-0.3.58/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.56 → gemcode-0.3.58}/LICENSE +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/MANIFEST.in +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/README.md +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/setup.cfg +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/cli.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/config.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/invoke.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/kairos_daemon.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/version.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/web/claude_sse_adapter.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_claude_web_adapter_sse.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_credentials.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_kairos_scheduler.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_paths.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_permissions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_tools.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.56 → gemcode-0.3.58}/tests/test_workspace_hints.py +0 -0
|
@@ -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?
|
|
@@ -47,14 +101,37 @@ def _playwright_available() -> bool:
|
|
|
47
101
|
This is called before building the runner so we can disable computer-use
|
|
48
102
|
early and prevent model routing from switching to gemini-2.5-computer-use-*.
|
|
49
103
|
"""
|
|
104
|
+
# 1) Preferred: ask Playwright for the resolved executable path.
|
|
105
|
+
# This can fail in some environment-mismatch cases (package installed but driver
|
|
106
|
+
# cannot start), so we also do a cache-based probe below.
|
|
50
107
|
try:
|
|
51
108
|
from playwright.sync_api import sync_playwright
|
|
52
109
|
with sync_playwright() as p:
|
|
53
|
-
exe = p.chromium
|
|
54
|
-
|
|
110
|
+
exe = getattr(p.chromium, "executable_path", None)
|
|
111
|
+
if exe and Path(str(exe)).exists():
|
|
112
|
+
return True
|
|
113
|
+
except Exception:
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
# 2) Fallback: check the default browser cache directly.
|
|
117
|
+
# This avoids false negatives when Playwright import/driver resolution is flaky,
|
|
118
|
+
# but browsers are present (common on macOS with mixed --user/system installs).
|
|
119
|
+
try:
|
|
120
|
+
cache_root = Path.home() / "Library" / "Caches" / "ms-playwright"
|
|
121
|
+
if not cache_root.exists():
|
|
122
|
+
return False
|
|
123
|
+
# macOS paths (Chromium.app or "Google Chrome for Testing.app")
|
|
124
|
+
mac_bins = list(cache_root.glob("chromium-*/*/Chromium.app/Contents/MacOS/Chromium"))
|
|
125
|
+
mac_bins += list(
|
|
126
|
+
cache_root.glob(
|
|
127
|
+
"chromium-*/*/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing"
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
if any(p.exists() for p in mac_bins):
|
|
131
|
+
return True
|
|
55
132
|
except Exception:
|
|
56
133
|
pass
|
|
57
|
-
|
|
134
|
+
|
|
58
135
|
return False
|
|
59
136
|
|
|
60
137
|
|
|
@@ -124,6 +201,7 @@ def _make_safe_computer_toolset(computer):
|
|
|
124
201
|
await self._inner.process_llm_request(
|
|
125
202
|
tool_context=tool_context, llm_request=llm_request
|
|
126
203
|
)
|
|
204
|
+
_wrap_computer_use_tools_with_safety_ack(llm_request)
|
|
127
205
|
except Exception as exc:
|
|
128
206
|
if not self._broken:
|
|
129
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
|
|
File without changes
|