gemcode 0.3.43__py3-none-any.whl → 0.3.45__py3-none-any.whl
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/agent.py +4 -1
- gemcode/session_runtime.py +73 -1
- gemcode/tui/scrollback.py +16 -6
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/METADATA +1 -1
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/RECORD +9 -9
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/WHEEL +0 -0
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.43.dist-info → gemcode-0.3.45.dist-info}/top_level.txt +0 -0
gemcode/agent.py
CHANGED
|
@@ -603,10 +603,13 @@ For tasks where quality matters:
|
|
|
603
603
|
4. Report done only when verified
|
|
604
604
|
|
|
605
605
|
## Error recovery
|
|
606
|
-
- **Test/build failures**: read the full error, identify the exact line, fix, re-run.
|
|
606
|
+
- **Test/build failures**: read the full error, identify the exact line, fix, re-run. Do NOT give up after one attempt.
|
|
607
|
+
- **Frontend / Next.js build errors**: read `src/app/page.tsx` (or the file in the error trace), fix the import/export precisely, then re-run the dev server.
|
|
608
|
+
- **lucide-react icon errors** (`Export X was not found`): The correct icon API for lucide-react ≥0.460 uses `Github` → `Github` is removed; use `GithubIcon` or find the right name by checking `node_modules/lucide-react/dist/esm/lucide-react.js` with `grep_content`. Always verify icon names before writing code.
|
|
607
609
|
- **Tool errors**: diagnose why it failed before retrying — don't repeat the exact same call.
|
|
608
610
|
- **After 2 failed attempts on the same problem**: stop and explain the blocker clearly.
|
|
609
611
|
- **Unexpected file content**: re-read the actual file rather than assuming your mental model is correct.
|
|
612
|
+
- **Compiler / linter errors pasted by the user**: extract the file path and line from the error, read that file, apply the minimal fix, and re-run the check. Never explain without fixing.
|
|
610
613
|
|
|
611
614
|
## Risk and permissions
|
|
612
615
|
- State destructive operations clearly before doing them (deletes, force-push, data truncation).
|
gemcode/session_runtime.py
CHANGED
|
@@ -30,6 +30,78 @@ def session_db_path(cfg: GemCodeConfig) -> Path:
|
|
|
30
30
|
return cfg.project_root / ".gemcode" / "sessions.sqlite"
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
class _SafeComputerUseToolset:
|
|
34
|
+
"""
|
|
35
|
+
Drop-in wrapper around ComputerUseToolset that catches Playwright startup
|
|
36
|
+
failures (e.g. missing browser binary) and disables computer-use gracefully
|
|
37
|
+
for the current session instead of crashing every turn with an unhandled error.
|
|
38
|
+
|
|
39
|
+
When the underlying toolset fails for the *first* time a one-time warning is
|
|
40
|
+
printed to stderr so the user knows they need to run ``playwright install``.
|
|
41
|
+
Subsequent calls are silently no-ops so the session keeps working without
|
|
42
|
+
browser tools — the agent can still use all other tools normally.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, computer) -> None:
|
|
46
|
+
try:
|
|
47
|
+
from google.adk.tools.computer_use.computer_use_toolset import ComputerUseToolset
|
|
48
|
+
self._inner = ComputerUseToolset(computer=computer)
|
|
49
|
+
except Exception:
|
|
50
|
+
self._inner = None
|
|
51
|
+
self._broken = False
|
|
52
|
+
self._warned = False
|
|
53
|
+
|
|
54
|
+
def _warn_once(self, error: Exception) -> None:
|
|
55
|
+
if self._warned:
|
|
56
|
+
return
|
|
57
|
+
self._warned = True
|
|
58
|
+
import sys
|
|
59
|
+
msg = str(error)
|
|
60
|
+
if "playwright install" in msg.lower() or "executable doesn't exist" in msg.lower():
|
|
61
|
+
print(
|
|
62
|
+
"\n[gemcode] Browser (computer-use) is unavailable — Playwright browsers are not installed.\n"
|
|
63
|
+
" Run: playwright install chromium\n"
|
|
64
|
+
" Then restart GemCode with /computer on (or --computer flag).\n"
|
|
65
|
+
" Continuing without browser tools for this session.\n",
|
|
66
|
+
file=sys.stderr,
|
|
67
|
+
)
|
|
68
|
+
else:
|
|
69
|
+
print(
|
|
70
|
+
f"\n[gemcode] Browser (computer-use) failed to start: {msg!s:.200}\n"
|
|
71
|
+
" Continuing without browser tools for this session.\n",
|
|
72
|
+
file=sys.stderr,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# ── ADK toolset protocol ────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
async def process_llm_request(self, *, tool_context, llm_request) -> None:
|
|
78
|
+
if self._broken or self._inner is None:
|
|
79
|
+
return
|
|
80
|
+
try:
|
|
81
|
+
await self._inner.process_llm_request(
|
|
82
|
+
tool_context=tool_context, llm_request=llm_request
|
|
83
|
+
)
|
|
84
|
+
except Exception as exc:
|
|
85
|
+
self._broken = True
|
|
86
|
+
self._warn_once(exc)
|
|
87
|
+
|
|
88
|
+
async def get_tools(self, readonly_context=None):
|
|
89
|
+
if self._broken or self._inner is None:
|
|
90
|
+
return []
|
|
91
|
+
try:
|
|
92
|
+
return await self._inner.get_tools(readonly_context)
|
|
93
|
+
except Exception as exc:
|
|
94
|
+
self._broken = True
|
|
95
|
+
self._warn_once(exc)
|
|
96
|
+
return []
|
|
97
|
+
|
|
98
|
+
def __getattr__(self, name: str):
|
|
99
|
+
"""Proxy all other attribute accesses to the inner toolset."""
|
|
100
|
+
if self._inner is not None:
|
|
101
|
+
return getattr(self._inner, name)
|
|
102
|
+
raise AttributeError(name)
|
|
103
|
+
|
|
104
|
+
|
|
33
105
|
def _build_artifact_service(cfg: GemCodeConfig):
|
|
34
106
|
"""
|
|
35
107
|
Return an ADK ArtifactService for this session, or None if disabled.
|
|
@@ -92,7 +164,7 @@ def create_runner(cfg: GemCodeConfig, extra_tools: list | None = None) -> Runner
|
|
|
92
164
|
headless=headless,
|
|
93
165
|
viewport_size=(viewport_w, viewport_h),
|
|
94
166
|
)
|
|
95
|
-
computer_toolset =
|
|
167
|
+
computer_toolset = _SafeComputerUseToolset(computer=computer)
|
|
96
168
|
merged_extra_tools = list(merged_extra_tools or [])
|
|
97
169
|
merged_extra_tools.append(computer_toolset)
|
|
98
170
|
|
gemcode/tui/scrollback.py
CHANGED
|
@@ -573,12 +573,14 @@ async def run_gemcode_scrollback_tui(
|
|
|
573
573
|
INTENT_GREETING,
|
|
574
574
|
INTENT_DESCRIPTIONS,
|
|
575
575
|
)
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
576
|
+
# Show as a transient spinner status (do not print a permanent line).
|
|
577
|
+
_start_anim("Intentifying\u2026")
|
|
578
|
+
try:
|
|
579
|
+
_intent, _intent_src = await classify_intent_with_source(prompt)
|
|
580
|
+
finally:
|
|
581
|
+
_stop_anim()
|
|
582
|
+
# If disabled, show nothing; otherwise the spinner already conveyed it.
|
|
583
|
+
_ = show_intentifying_line(_intent_src)
|
|
582
584
|
|
|
583
585
|
if _intent == INTENT_GREETING:
|
|
584
586
|
_start_anim("Replying\u2026")
|
|
@@ -726,6 +728,14 @@ async def run_gemcode_scrollback_tui(
|
|
|
726
728
|
final_text = thought_text
|
|
727
729
|
thought_text = ""
|
|
728
730
|
|
|
731
|
+
# If the model produced no visible text at all, show an explicit hint
|
|
732
|
+
# instead of returning to the prompt silently.
|
|
733
|
+
if not final_text and not thought_text and not assistant_wrote_text:
|
|
734
|
+
await typewrite(
|
|
735
|
+
f"{ansi.dim}(No text response received. Try 'continue' to retry the last request.){ansi.reset}"
|
|
736
|
+
)
|
|
737
|
+
print("")
|
|
738
|
+
|
|
729
739
|
# ── Thinking display (collapsed by default, verbose with /thinking verbose)
|
|
730
740
|
if thought_text and not (
|
|
731
741
|
buffered_final and _normalize_ws(thought_text) == _normalize_ws(final_text)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
gemcode/__init__.py,sha256=l0DCRYqK7KM7Fb7u49fqh-5_SlpeIL7r3LjMeJWMgSg,112
|
|
2
2
|
gemcode/__main__.py,sha256=EX2s1hxq2Yvli_-tnBN3w5Qv4bOjsBBbjyISF0pDIQw,37
|
|
3
|
-
gemcode/agent.py,sha256=
|
|
3
|
+
gemcode/agent.py,sha256=ODiOL6e2vDuXEHdiEmn71xKx7Lk4O-_uePmaavROVgA,42229
|
|
4
4
|
gemcode/audit.py,sha256=bh9uhXaeh8wqxqoZtz3ZAowd8Ndk1ss-mw9993Vlrgo,469
|
|
5
5
|
gemcode/autocompact.py,sha256=77h5tgFzJ2rjrhlCL2oIc28IHwLbP4Pqlo7cSNgDwiA,6727
|
|
6
6
|
gemcode/callbacks.py,sha256=qgbxyBMOlgzVkJr9lI55En4EpJOwjo83U3dvNrl5I4s,24229
|
|
@@ -33,7 +33,7 @@ gemcode/refine.py,sha256=BijEZ4Z32wGa9aK_WottyAhZF-j0xEqRg5UpjedNv2A,7653
|
|
|
33
33
|
gemcode/repl_commands.py,sha256=qPUVSjNLR0QnABmURoYP58quu2pAcz3F0wUvDd_1v3o,11340
|
|
34
34
|
gemcode/repl_slash.py,sha256=JomAwJpOQvRJKnjaLIW2X2VWVNXSCvZ9s6P0iYUhC98,46969
|
|
35
35
|
gemcode/review_agent.py,sha256=4t7_5-aE60b4-EheJ_eSB_H2eQYf9GppKoui6jw0TME,5264
|
|
36
|
-
gemcode/session_runtime.py,sha256=
|
|
36
|
+
gemcode/session_runtime.py,sha256=RIxncWWbf9T9An8E9cVnQQWa4IRTOOtVodKIext10oc,8613
|
|
37
37
|
gemcode/session_store.py,sha256=POUT_QQf715c74jbXj0s5vCd4dlAgJz_CLsIWuEUoO0,6051
|
|
38
38
|
gemcode/slash_commands.py,sha256=Qylzsj1notk0xN_hvd3CR4HD8g-l99UENDMcg1pKeBA,794
|
|
39
39
|
gemcode/thinking.py,sha256=RanBf_x9fKv1o4DNyNXPLfOdn2xT0KybJb65nYgmMEE,4885
|
|
@@ -73,16 +73,16 @@ gemcode/tools/think.py,sha256=WrNATR-bi97aLkbSsOFOYYAGxbzihe9AnPDZfw3z5-Q,1704
|
|
|
73
73
|
gemcode/tools/todo.py,sha256=d9aXiyT04r1RFZIk6qdVif17-_Oc3oi4ymDnsPBRg68,3143
|
|
74
74
|
gemcode/tools/web.py,sha256=ULg1e3inG4FjPSUCYI8dVBzTrcCHINNRo76SIU9qw-A,4489
|
|
75
75
|
gemcode/tui/input_handler.py,sha256=VWF92Fe3WkD3QP9kBDY5zrx333Vj2eShO3UO0x2n6eo,10079
|
|
76
|
-
gemcode/tui/scrollback.py,sha256=
|
|
76
|
+
gemcode/tui/scrollback.py,sha256=YUEmdjShp_RMMSdYpRGNNcS3VsIQznXl6RMgXweBbqs,33958
|
|
77
77
|
gemcode/tui/spinner.py,sha256=AJrApG5od-Sh40-5uWcNM9RHb5ax7gr-NbgAZmTbIYY,4848
|
|
78
78
|
gemcode/tui/welcome_banner.py,sha256=aocl1lnoyLIM6RN4f65g3i0wRA71RqUlgPrGsXeVLW4,4387
|
|
79
79
|
gemcode/tui/welcome_rich.py,sha256=8FEZzLXrzqly5JWiDgV9ooRV1LNXDk-CXV1a7K6ua-U,4048
|
|
80
80
|
gemcode/web/__init__.py,sha256=EysmUAWs6g-lmMk4VFljKfaHVrEgb_FiIzwQmBdORJc,40
|
|
81
81
|
gemcode/web/claude_sse_adapter.py,sha256=HcNp0Lh4DdBZBLOpstsqa-VzfqAUrRngZ6FSuJ-mIMg,8609
|
|
82
82
|
gemcode/web/terminal_repl.py,sha256=k2irvFGbCY8gDm_pbirR7b_cakaeafcctoTIvnJkVXk,3902
|
|
83
|
-
gemcode-0.3.
|
|
84
|
-
gemcode-0.3.
|
|
85
|
-
gemcode-0.3.
|
|
86
|
-
gemcode-0.3.
|
|
87
|
-
gemcode-0.3.
|
|
88
|
-
gemcode-0.3.
|
|
83
|
+
gemcode-0.3.45.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
|
|
84
|
+
gemcode-0.3.45.dist-info/METADATA,sha256=75BwlxWcZdJ9_ZE2up7TdU2Ma_E57mkthy0gQ3zGYLw,23695
|
|
85
|
+
gemcode-0.3.45.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
86
|
+
gemcode-0.3.45.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
|
|
87
|
+
gemcode-0.3.45.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
|
|
88
|
+
gemcode-0.3.45.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|