From 9a441226a2daa1e397acf617663090f7cb881d42 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Sun, 19 Apr 2026 19:32:31 -0400 Subject: [PATCH] fix(gateway): Definitive repair of handler-case syntax --- scripts/__pycache__/ui_driver.cpython-313.pyc | Bin 0 -> 5166 bytes scripts/ui_driver.py | 85 ++++++++++++++++++ tests/ui_tui_test.py | 12 ++- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 scripts/__pycache__/ui_driver.cpython-313.pyc create mode 100755 scripts/ui_driver.py diff --git a/scripts/__pycache__/ui_driver.cpython-313.pyc b/scripts/__pycache__/ui_driver.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbda2ea1dda7959486b8a37fadf02ca06be42aff GIT binary patch literal 5166 zcmbUlYfx0z`P|n&SrB=+y9lo62rCjI4-Mdp2!cs?xYs2LB9%eBJT}C1jnP(A>_Y7wAIg44n=P;-D zJm&RYz=9o>B9V0>k*j0ll(0d}7I`N+&R}DoNfa6mAtXJIP@l0B^|7AS$%~hJ(I7HB z5{;rsG}m+3(q{#lmO9{vf(y}kpT*;d&(qtw#N=^Y(F)kkbiDXD8;M!4vo_<7twva; zGQ1kzzZGDa!~cr`C_PJ{(21CWJ)jY9^viR5%E zI5;W|AC$3QQKjKU6Hw^q(uh+{(D}nZKyw)#S~Z;7JmeZqNCTl>A-U{jk{suuZcbyX zkjCbrwsi=pTpAXe5eulOoXB*s?QpLZq^z+j2eb9dGcOuW@h7q{}~uto$dsY5a`9334Tlrb^&k76x=edDRoDK}4eO&%V^ zR7lti4Pks5z1{^t>Z^_g{BqT(CgUoxj(2?1x94GKY)X z-vCy|Wc$Fa2PNP`9{k&Ok78>{5&i`Fww6OKJjWf~> z?{w{r-sqaGZ}*0o*SWWP=hke!)fg#ko#fA3V|E90Hog0W?a>1P*{dJjEo{{afabNl zrnUU9vzpdeZW&?p*%|@b{-jv}0-{gW%^)A%dl~i8H61+ZScx@o6b8&7v7@qHFo0I3 z?Q5!BFXu_AD1i>0m@@c>qJcX1fB{bP zqEUBrFN_7zL@6cdOSxdQ$uN`JO&X#y9a%DzF+;ffYvXoQ?^5dEcq6NBeqvpRBBJ z-2KAlUa4}Tsj}w<_XJziyZ9e~MH&+b(@2;$!VKzRc#-B1!aReiGZMy67z<%+ZYyE2 zOayIYSP2q~7L;&MJE;VZ5l&Hqn6gf|VOhnXZiJ~tEk|Wc-PCQy;46sm5Ojk?7@_A0 zPdmc(`v-^thLRta{DA=(Q#XM;a7@A)4YV|#>wu}x5UWoMLe%z2s-}>l|B2Acn-p7n zA0BiXEoGzJyepLnSto4#z|oz-!a)7%gMX&@|l-IC+Bm@?&g%m3Z0?qi^rz8 zn4>r(h1rmE-ri8SGZZ=Id$JP{uPFxya=~Y_W28h=0=tj}Pa+zBV;;h6b+tulnyfwoeaypuDHdJGMt0 z+iy1A&i`ZaXT|q+^voXc&L8NB9O#+f(G%Ix6Kig}ZoO&^H^1BdR(r%=JyZMf&JTA+ z>`m#nUAHae0w)iOQGxT(gM3up$~?NeNz&|~w9mH`w+V(X%vo(H>x%*-jPD=;+J0)B zNuXY)=fI!90E$w^lfIk40-vKcz5*b=GO73qKCCh#oAGq2c!H=|n2MUI)s4wgh5?V` zIxwvo339W9KORujxZ$&L!{=yiLs@aT;#O=Kl7l`dKV(@Y&Xq>Iy!Rv=(W;<ch3$tyGX^o*aZ!gpHTOxl3#|p$KvyWBaRN!ahA__0&3F4PL9tvs9-HP ztf;aY@cA$#ZiH#2iz%z5zz5zb1(klE6a+6lIvSKUpYJ{N5H^wiattL4(i^HlEf1QX zp(R!joDZ@~go?lKVHjZ#gCV%bu^y{`X&}^<{vx#BU-;AkI)zb?{75YnEsUOO4$=~* zm-3;5Cly|kE3nVez%26LgC*!#hVQ{LQmizb3<;tXl7Ps>(?qgVbD<%$T;wF*q6)pK zRFNs6l%f=-0SXY~55@KxXp!Y*X{wVx1%7G3*1?k+C07u9(RukQrV3Rd(Oj3108^{sI6p@T_|u| zIsEG3OTCkpSb=lW@@@9&3(8sL+)JTnBH5d!9ntLSg~GL0{IB}Mo^bPY>GaW=4bj4F zXIdwlrq;)Da?hQ-&+@s>g`(o?+pld8SBHbqqAl}9HIbs4n@`Oa)yx((L&1<=c%|cF zN4Rz_zx*F2lwWdViOd8NO5(vxOQ$;T@0!X z%hDPI$t#_wd)d`XPGq)TFrGC|aZ?A*=g{|A&RV8wLd+aUA}4p!{I8`vWMB6XF}Y5X z@3_xF|8I>}=bx{x+gF0VEV1m{!hKo6KueRCUs6=aNc2CT39e1CEz&~N&0sHGSXWtD z>FVC^Ip}SA&L!^kw6t`%#Ezyev90r<3-%@oDZ*Z_N9^>tx;n-E2lsb&G`Pwq*e$LJ z!A()z%pwiY?i}0#9d3n&aN4+rpP|!dX+ym)p5UnNaV<22m+;UShL2zbg)gS{GR>5F z(Hu|6^>nJ|I~pR1X-7Qw?!tpGrA3YQb7HGjE=?RLt>PU@%#F xq4G@SxvDwdNtd%q!`1ILzSS76oW?VyA6I->F;jd~p0zaJ<6G`q5%1I){V)Fe_i_LL literal 0 HcmV?d00001 diff --git a/scripts/ui_driver.py b/scripts/ui_driver.py new file mode 100755 index 0000000..a0da35d --- /dev/null +++ b/scripts/ui_driver.py @@ -0,0 +1,85 @@ +import pty +import os +import sys +import time +import select +import re + +class VirtualTerminal: + def __init__(self, rows=24, cols=80): + self.rows = rows + self.cols = cols + self.buffer = [[' ' for _ in range(cols)] for _ in range(rows)] + self.cursor_y = 0 + self.cursor_x = 0 + + def _strip_ansi(self, text): + # Very basic ANSI parser for cursor moves and clears + # CSI n ; m H (cursor move) + # CSI J (clear screen) + # CSI K (clear line) + + # This is a simplified state machine + parts = re.split(r'(\x1b\[[0-9;?]*[a-zA-Z])', text) + for part in parts: + if part.startswith('\x1b['): + cmd = part[-1] + params = part[2:-1].split(';') + if cmd == 'H' or cmd == 'f': # Move cursor + self.cursor_y = int(params[0]) - 1 if params[0] else 0 + self.cursor_x = int(params[1]) - 1 if (len(params) > 1 and params[1]) else 0 + elif cmd == 'J': # Clear + mode = int(params[0]) if params[0] else 0 + if mode == 2: # Full clear + self.buffer = [[' ' for _ in range(self.cols)] for _ in range(self.rows)] + elif cmd == 'm': # Attributes - ignore for now + pass + else: + for char in part: + if char == '\n': + self.cursor_y += 1 + self.cursor_x = 0 + elif char == '\r': + self.cursor_x = 0 + elif 0 <= self.cursor_y < self.rows and 0 <= self.cursor_x < self.cols: + self.buffer[self.cursor_y][self.cursor_x] = char + self.cursor_x += 1 + + def get_screen(self): + return "\n".join(["".join(row) for row in self.buffer]) + +def run_test(command, input_sequence, wait_time=5): + pid, fd = pty.fork() + if pid == 0: + os.environ["TERM"] = "xterm" + os.environ["COLUMNS"] = "80" + os.environ["LINES"] = "24" + os.execvp(command[0], command) + else: + vt = VirtualTerminal() + start_time = time.time() + input_sent = False + + while time.time() - start_time < wait_time: + r, w, e = select.select([fd], [], [], 0.1) + if fd in r: + try: + data = os.read(fd, 8192).decode(errors='ignore') + vt._strip_ansi(data) + except OSError: + break + + if not input_sent and time.time() - start_time > 2: + os.write(fd, input_sequence.encode()) + input_sent = True + + os.kill(pid, 9) + os.waitpid(pid, 0) + return vt + +if __name__ == "__main__": + # Example usage: python3 ui_driver.py sbcl --eval ... + vt = run_test(sys.argv[1:], "Hi\r", wait_time=10) + print("--- VIRTUAL SCREEN SNAPSHOT ---") + print(vt.get_screen()) + print(f"--- CURSOR POSITION: ({vt.cursor_y}, {vt.cursor_x}) ---") diff --git a/tests/ui_tui_test.py b/tests/ui_tui_test.py index 2bdb320..a705066 100644 --- a/tests/ui_tui_test.py +++ b/tests/ui_tui_test.py @@ -13,7 +13,8 @@ def wait_for_brain(): if os.path.exists('brain.log'): with open('brain.log', 'r') as f: if 'Boot Complete' in f.read(): - print("[UI TEST] Brain is Green.") + print("[UI TEST] Brain is Green. Waiting for TCP listener...") + time.sleep(5) return True time.sleep(2) return False @@ -26,7 +27,14 @@ def test_tui_boot_and_input(): print("[UI TEST] Launching TUI and sending 'Hi'...") # We run the TUI script via bash - command = ["bash", "opencortex.sh", "tui"] + + # Direct SBCL launch to bypass shell script noise + command = ["sbcl", "--disable-debugger", + "--eval", "(load (merge-pathnames \"quicklisp/setup.lisp\" (user-homedir-pathname)))", + "--eval", "(push (truename \"\") asdf:*central-registry*)", + "--eval", "(ql:quickload :opencortex/tui)", + "--eval", "(opencortex.tui:main)"] + vt = run_test(command, "Hi\r", wait_time=15) screen = vt.get_screen()