gemcode 0.3.25__tar.gz → 0.3.26__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 (113) hide show
  1. {gemcode-0.3.25/src/gemcode.egg-info → gemcode-0.3.26}/PKG-INFO +1 -1
  2. {gemcode-0.3.25 → gemcode-0.3.26}/pyproject.toml +1 -1
  3. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tui/scrollback.py +57 -18
  4. {gemcode-0.3.25 → gemcode-0.3.26/src/gemcode.egg-info}/PKG-INFO +1 -1
  5. {gemcode-0.3.25 → gemcode-0.3.26}/LICENSE +0 -0
  6. {gemcode-0.3.25 → gemcode-0.3.26}/MANIFEST.in +0 -0
  7. {gemcode-0.3.25 → gemcode-0.3.26}/README.md +0 -0
  8. {gemcode-0.3.25 → gemcode-0.3.26}/setup.cfg +0 -0
  9. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/__init__.py +0 -0
  10. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/__main__.py +0 -0
  11. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/agent.py +0 -0
  12. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/audit.py +0 -0
  13. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/autocompact.py +0 -0
  14. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/callbacks.py +0 -0
  15. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/capability_routing.py +0 -0
  16. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/cli.py +0 -0
  17. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/compaction.py +0 -0
  18. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/computer_use/__init__.py +0 -0
  19. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/computer_use/browser_computer.py +0 -0
  20. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/config.py +0 -0
  21. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/context_budget.py +0 -0
  22. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/context_warning.py +0 -0
  23. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/credentials.py +0 -0
  24. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/hitl_session.py +0 -0
  25. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/interactions.py +0 -0
  26. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/invoke.py +0 -0
  27. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/kairos_daemon.py +0 -0
  28. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/limits.py +0 -0
  29. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/live_audio_engine.py +0 -0
  30. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/logging_config.py +0 -0
  31. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/mcp_loader.py +0 -0
  32. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/memory/__init__.py +0 -0
  33. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/memory/embedding_memory_service.py +0 -0
  34. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/memory/file_memory_service.py +0 -0
  35. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/modality_tools.py +0 -0
  36. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/model_errors.py +0 -0
  37. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/model_routing.py +0 -0
  38. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/paths.py +0 -0
  39. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/permissions.py +0 -0
  40. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/plugins/__init__.py +0 -0
  41. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  42. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  43. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/prompt_suggestions.py +0 -0
  44. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/__init__.py +0 -0
  45. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/config.py +0 -0
  46. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/deps.py +0 -0
  47. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/engine.py +0 -0
  48. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/stop_hooks.py +0 -0
  49. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/token_budget.py +0 -0
  50. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/query/transitions.py +0 -0
  51. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/repl_commands.py +0 -0
  52. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/repl_slash.py +0 -0
  53. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/session_runtime.py +0 -0
  54. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/slash_commands.py +0 -0
  55. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/thinking.py +0 -0
  56. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tool_prompt_manifest.py +0 -0
  57. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tool_registry.py +0 -0
  58. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/__init__.py +0 -0
  59. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/bash.py +0 -0
  60. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/browser.py +0 -0
  61. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/edit.py +0 -0
  62. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/filesystem.py +0 -0
  63. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/search.py +0 -0
  64. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/shell.py +0 -0
  65. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/shell_gate.py +0 -0
  66. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/subtask.py +0 -0
  67. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/think.py +0 -0
  68. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/todo.py +0 -0
  69. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools/web.py +0 -0
  70. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tools_inspector.py +0 -0
  71. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/trust.py +0 -0
  72. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tui/input_handler.py +0 -0
  73. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tui/spinner.py +0 -0
  74. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tui/welcome_banner.py +0 -0
  75. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/tui/welcome_rich.py +0 -0
  76. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/version.py +0 -0
  77. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/vertex.py +0 -0
  78. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/web/__init__.py +0 -0
  79. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/web/claude_sse_adapter.py +0 -0
  80. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/web/terminal_repl.py +0 -0
  81. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode/workspace_hints.py +0 -0
  82. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode.egg-info/SOURCES.txt +0 -0
  83. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode.egg-info/dependency_links.txt +0 -0
  84. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode.egg-info/entry_points.txt +0 -0
  85. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode.egg-info/requires.txt +0 -0
  86. {gemcode-0.3.25 → gemcode-0.3.26}/src/gemcode.egg-info/top_level.txt +0 -0
  87. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_agent_instruction.py +0 -0
  88. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_autocompact.py +0 -0
  89. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_capability_routing.py +0 -0
  90. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_claude_web_adapter_sse.py +0 -0
  91. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_cli_init.py +0 -0
  92. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_computer_use_permissions.py +0 -0
  93. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_context_budget.py +0 -0
  94. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_context_warning.py +0 -0
  95. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_credentials.py +0 -0
  96. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_interactive_permission_ask.py +0 -0
  97. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_kairos_scheduler.py +0 -0
  98. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_modality_tools.py +0 -0
  99. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_model_error_retry.py +0 -0
  100. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_model_errors.py +0 -0
  101. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_model_routing.py +0 -0
  102. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_paths.py +0 -0
  103. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_permissions.py +0 -0
  104. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_prompt_suggestions.py +0 -0
  105. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_repl_commands.py +0 -0
  106. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_repl_slash.py +0 -0
  107. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_slash_commands.py +0 -0
  108. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_thinking_config.py +0 -0
  109. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_token_budget.py +0 -0
  110. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_tool_context_circulation.py +0 -0
  111. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_tools.py +0 -0
  112. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_tools_inspector.py +0 -0
  113. {gemcode-0.3.25 → gemcode-0.3.26}/tests/test_workspace_hints.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.25
3
+ Version: 0.3.26
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.3.25"
7
+ version = "0.3.26"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -140,6 +140,43 @@ class _Ansi:
140
140
  return self.esc("38;5;69")
141
141
 
142
142
 
143
+ async def _read_permission_char(loop) -> bool:
144
+ """
145
+ Read a single character from stdin without requiring Enter.
146
+
147
+ Uses cbreak mode (Unix) so the user just presses 'y' — no Enter needed.
148
+ This sidesteps the prompt_toolkit raw-mode conflict entirely: after
149
+ prompt_async() returns, the terminal may still behave as if Enter sends
150
+ \\r instead of \\n, causing input()/readline() to block forever.
151
+ cbreak mode + read(1) works regardless of the terminal's current line-
152
+ discipline state.
153
+
154
+ Falls back to readline() on Windows or non-TTY (CI, piped input).
155
+ """
156
+ # ── Unix / macOS: cbreak + read(1) ───────────────────────────────────────
157
+ try:
158
+ import termios
159
+ import tty
160
+
161
+ fd = sys.stdin.fileno()
162
+ old_settings = termios.tcgetattr(fd)
163
+ try:
164
+ tty.setcbreak(fd) # single-char, no echo, signals still work
165
+ ch = await loop.run_in_executor(None, lambda: sys.stdin.read(1))
166
+ finally:
167
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
168
+ return ch.lower() == "y"
169
+ except Exception:
170
+ pass
171
+
172
+ # ── Fallback: readline in thread (Windows, non-TTY, termios error) ───────
173
+ try:
174
+ raw = await loop.run_in_executor(None, sys.stdin.readline)
175
+ return (raw or "").replace("\r", "").replace("\n", "").strip().lower() in ("y", "yes")
176
+ except EOFError:
177
+ return False
178
+
179
+
143
180
  def _term_width(default: int = 100) -> int:
144
181
  try:
145
182
  import shutil
@@ -581,27 +618,29 @@ async def run_gemcode_scrollback_tui(
581
618
  f"for {ansi.bold}{tool_name}{ansi.reset}."
582
619
  )
583
620
  sys.stdout.flush()
584
- # Use run_in_executor so input() runs in a thread this avoids
585
- # blocking the asyncio event loop and prevents the terminal-state
586
- # conflict that occurs when prompt_toolkit's raw-mode setup causes
587
- # synchronous input() to not recognise \r as end-of-line.
621
+ # The core issue: prompt_toolkit puts the terminal in raw mode
622
+ # while reading user input. After prompt_async() returns, the
623
+ # terminal may still be in (or close to) raw mode. In raw mode
624
+ # pressing Enter sends \r instead of \n. Both input() and
625
+ # readline() wait for \n — so they block forever.
626
+ #
627
+ # Fix: read a SINGLE CHARACTER using cbreak mode (no Enter needed).
628
+ # - tty.setcbreak() disables line-buffering + echo but keeps
629
+ # signal keys (Ctrl+C etc.) working.
630
+ # - read(1) returns immediately after any key is pressed.
631
+ # - The user only needs to press "y" — no Enter required.
632
+ # - On Windows (no termios) we fall back to readline().
588
633
  prompt_str = (
589
634
  f" ⎿ Allow? "
590
- f"[{ansi.blue_ok}y{ansi.reset} = yes"
591
- f" /{ansi.dim}Enter = no{ansi.reset}] "
635
+ f"[{ansi.blue_ok}y{ansi.reset} = yes "
636
+ f"{ansi.dim}any other key = no{ansi.reset}] "
592
637
  )
593
- try:
594
- # run_in_executor runs input() in a thread so the asyncio event
595
- # loop stays alive (spinner can update, timeouts can fire).
596
- # get_running_loop() is the correct call inside an async function.
597
- _loop = asyncio.get_running_loop()
598
- raw = await _loop.run_in_executor(None, input, prompt_str)
599
- # Strip \r and \n — handles raw-mode terminals where pressing
600
- # Enter sends \r (shown as ^M) instead of \n.
601
- ans = (raw or "").replace("\r", "").replace("\n", "").strip().lower()
602
- except EOFError:
603
- ans = ""
604
- ok = ans in ("y", "yes")
638
+ sys.stdout.write(prompt_str)
639
+ sys.stdout.flush()
640
+ ok = await _read_permission_char(asyncio.get_running_loop())
641
+ # Echo the answer and move to next line
642
+ sys.stdout.write(("y" if ok else "n") + "\n")
643
+ sys.stdout.flush()
605
644
 
606
645
  # Explicit visual feedback — user knows their answer was received.
607
646
  if ok:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.25
3
+ Version: 0.3.26
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes