gemcode 0.3.25__py3-none-any.whl → 0.3.26__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/tui/scrollback.py +57 -18
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/METADATA +1 -1
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/RECORD +7 -7
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/WHEEL +0 -0
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.25.dist-info → gemcode-0.3.26.dist-info}/top_level.txt +0 -0
gemcode/tui/scrollback.py
CHANGED
|
@@ -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
|
-
#
|
|
585
|
-
#
|
|
586
|
-
#
|
|
587
|
-
#
|
|
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"
|
|
635
|
+
f"[{ansi.blue_ok}y{ansi.reset} = yes "
|
|
636
|
+
f"{ansi.dim}any other key = no{ansi.reset}] "
|
|
592
637
|
)
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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:
|
|
@@ -65,16 +65,16 @@ gemcode/tools/think.py,sha256=WrNATR-bi97aLkbSsOFOYYAGxbzihe9AnPDZfw3z5-Q,1704
|
|
|
65
65
|
gemcode/tools/todo.py,sha256=d9aXiyT04r1RFZIk6qdVif17-_Oc3oi4ymDnsPBRg68,3143
|
|
66
66
|
gemcode/tools/web.py,sha256=ULg1e3inG4FjPSUCYI8dVBzTrcCHINNRo76SIU9qw-A,4489
|
|
67
67
|
gemcode/tui/input_handler.py,sha256=rCSzV5Ucc-nZTBbY8KKTDS9einNrgMzvI_NGcMls9e8,8147
|
|
68
|
-
gemcode/tui/scrollback.py,sha256=
|
|
68
|
+
gemcode/tui/scrollback.py,sha256=f14MSfDM4dryDWWG3vfTuzkV4mJfFbz2Yd7gF9S4pXs,23455
|
|
69
69
|
gemcode/tui/spinner.py,sha256=AJrApG5od-Sh40-5uWcNM9RHb5ax7gr-NbgAZmTbIYY,4848
|
|
70
70
|
gemcode/tui/welcome_banner.py,sha256=aocl1lnoyLIM6RN4f65g3i0wRA71RqUlgPrGsXeVLW4,4387
|
|
71
71
|
gemcode/tui/welcome_rich.py,sha256=8FEZzLXrzqly5JWiDgV9ooRV1LNXDk-CXV1a7K6ua-U,4048
|
|
72
72
|
gemcode/web/__init__.py,sha256=EysmUAWs6g-lmMk4VFljKfaHVrEgb_FiIzwQmBdORJc,40
|
|
73
73
|
gemcode/web/claude_sse_adapter.py,sha256=HcNp0Lh4DdBZBLOpstsqa-VzfqAUrRngZ6FSuJ-mIMg,8609
|
|
74
74
|
gemcode/web/terminal_repl.py,sha256=k2irvFGbCY8gDm_pbirR7b_cakaeafcctoTIvnJkVXk,3902
|
|
75
|
-
gemcode-0.3.
|
|
76
|
-
gemcode-0.3.
|
|
77
|
-
gemcode-0.3.
|
|
78
|
-
gemcode-0.3.
|
|
79
|
-
gemcode-0.3.
|
|
80
|
-
gemcode-0.3.
|
|
75
|
+
gemcode-0.3.26.dist-info/licenses/LICENSE,sha256=TD4524qn-W8Z07GTDnag-9jJPFutFZNB0a1WbMHPC54,8388
|
|
76
|
+
gemcode-0.3.26.dist-info/METADATA,sha256=gvuLPIdccTr2APbK1N6Zjp9MwO9Uw7k6sS6C71ckrXU,23695
|
|
77
|
+
gemcode-0.3.26.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
78
|
+
gemcode-0.3.26.dist-info/entry_points.txt,sha256=cZdLTLDiHbks7OSUCuxCh66dCWeQdpLR8BozoqfEjV4,45
|
|
79
|
+
gemcode-0.3.26.dist-info/top_level.txt,sha256=UYrjULLBY2bcgK6KI6flomJWmsbDXu7n0rvW2SWFrbo,8
|
|
80
|
+
gemcode-0.3.26.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|