
    bѠiG              	          d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	Z	ddl
mZmZmZmZ ddlmZ ddlmZ dZdZd	Zej,                  j/                  d
d      ZdZej,                  j/                  dd      ZdZdZdZdZ edd      ZejA                  edgddgdg        G d de      Z! G d de      Z"dee#   de$fd Z%g d!Z&g d"Z'g d#Z(d$e#de#fd%Z)ejT                  jW                  ed&      ejT                  jW                  ed'      d(Z,d$e#de#fd)Z-efd*e#d+e.de/e#e$f   fd,Z0d$e#de#fd-Z1d$e#de#fd.Z2dHd$e#d/ee#   de#fd0Z3dHd$e#d/ee#   de#fd1Z4ejk                  d2e"3       ed      fd4e!dee#   fd5       Z6ej/                  d6      d7        Z7e8d8k(  rddl9Z9 e:d9        e:d:e d;ejT                  jw                  e      rd<nd= d>        e:d?e d;ejT                  jw                  e      rd<nd= d>        e:d@e         e:dAeddB  dC        e:         e:dD        e9jx                  edEdFG       yy)Iu  
Terminal Relay Server — Voice-to-Terminal Bridge

Receives voice-transcribed commands from the MCP Voice Bridge (CF Worker)
and executes them against the Genesis codebase via terminal agents.

Architecture:
  Phone → Telnyx STT → MCP (CF Worker) → cloudflared → THIS SERVER → claude/gemini/bash → response

Smart routing:
  - "terminal" mode: claude -p (full terminal agent, uses API credits)
  - "gemini" mode: gemini CLI (free via Ultra subscription)
  - "bash" mode: direct subprocess (free, simple commands)
  - "read" mode: read file contents (free)
  - "auto" mode: smart routing based on task complexity

Run: uvicorn scripts.terminal_relay:app --host 0.0.0.0 --port 8765
Expose: cloudflared tunnel --url http://localhost:8765
    N)Optional)FastAPIHTTPExceptionHeaderRequest)CORSMiddleware)	BaseModelz/mnt/e/genesis-systemz8/home/authentic88/.nvm/versions/node/v22.22.0/bin/claudez8/home/authentic88/.nvm/versions/node/v22.22.0/bin/geminiGEMINI_API_KEY'AIzaSyALfbAdHfJ6aRnqNyiTRmKmGVoena1JsdUzXhttps://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContentRELAY_TOKENzsubaiva-prod-token-2026-genesis   x   <   i  zGenesis Terminal Relayz1.0.0)titleversion*POSTGET)allow_originsallow_methodsallow_headersc                   N    e Zd ZU eed<   dZeed<   dZee   ed<   dZee	   ed<   y)ExecuteRequestcommandautomodeNcontext  
max_tokens)
__name__
__module____qualname__str__annotations__r   r   r   r   int     //mnt/e/genesis-system/scripts/terminal_relay.pyr   r   ;   s-    LD#!GXc]! #J#r'   r   c                   :    e Zd ZU eed<   eed<   eed<   dZeed<   y)ExecuteResponseresponse	mode_usedduration_msF	truncatedN)r    r!   r"   r#   r$   r%   r.   boolr&   r'   r(   r*   r*   B   s    MNItr'   r*   authorizationreturnc                 \    | sy| j                  d      r| dd  }|t        k(  S | }|t        k(  S )NFzBearer    )
startswithr   )r0   tokens     r(   verify_authr6   K   sA    	*ab! K Kr'   )ze\b(edit|modify|change|update|fix|write|create|delete|remove)\b.*\b(file|code|function|class|config)\bz*\b(commit|push|pull|merge|branch|deploy)\bz\b(install|pip|npm|apt|brew)\bz+\b(run test|pytest|jest|check|lint|build)\bz$\b(refactor|implement|debug|trace)\b)zC^(ls|pwd|cat|head|tail|wc|du|df|free|uptime|whoami|date|hostname)\bzO^(echo|mkdir|touch|cp|mv|rm|chmod|chown|find|grep|sort|uniq|tr|sed|awk|xargs)\bz$^(bash|sh|python3?|node|curl|wget)\bz^(git |git$)z0^(ps |top|htop|docker |systemctl |journalctl )\bz.^(cd |source |export |\.|which |type |file )\bz%\b(list files|show files|directory)\bz'\b(disk space|memory usage|cpu usage)\bz\|z
[>]{1,2}\s&&z/mnt/[a-z]/)z2\bread\b.*\b(file|content|memory\.md|claude\.md)\bz!\bshow me\b.*\b(file|contents?)\bz&\bwhat('s| is) in\b.*\b(file|folder)\br   c                 |     j                         j                         t        D ]  }t        j                  |      s y t
        D ]  }t        j                  |      s y t        D ]  }t        j                  |      s y g d}t         fd|D              }|sg d}t        fd|D              ryy)	z7Smart-route a voice command to the best execution mode.bashread
gemini_ctx)|><r7   z||;z$(`z/mnt/z/home/z/tmp/c              3   &   K   | ]  }|v  
 y wNr&   ).0indr   s     r(   	<genexpr>z#classify_command.<locals>.<genexpr>   s     Fc3'>F   )genesisaivasubaivamissionprioritystatusmemorymrrrevenuecustomergeorgetelnyxvoiceagent	knowledgedeploy
productionzwhat are wezwhat is thezcurrent stateprogressc              3   &   K   | ]  }|v  
 y wrB   r&   rC   kw	cmd_lowers     r(   rE   z#classify_command.<locals>.<genexpr>   s     92rY9rF   gemini)lowerstripBASH_PATTERNSresearchREAD_PATTERNSTERMINAL_PATTERNSany)r   patternshell_indicatorslooks_like_shellsystem_keywordsr\   s   `    @r(   classify_commandrj   x   s    %%'I ! 99Wi(
 ! 99Wi(
 %  99Wi(  _F5EFF
 999 r'   	MEMORY.mdhive/session_recovery/LATEST.md)rM   handoffc                    g }| j                         	 t        t        d   d      5 }|j                         dd }ddd       |j	                  d        t        fddD              rD	 t        t        d   d      5 }|j                         dd	 }ddd       |j	                  d
        t        fddD              rX	 t        j                  dddddt              }|j                  r,|j	                  d|j                  j                                 |rdj                  |      S dS # 1 sw Y   xY w# t
        $ r Y w xY w# 1 sw Y   xY w# t
        $ r Y w xY w# t
        $ r Y Vw xY w)zCRead relevant codebase files to inject as context for AI responses.rM   rNi  z'=== GENESIS MEMORY (current state) ===
c              3   &   K   | ]  }|v  
 y wrB   r&   rZ   s     r(   rE   z*gather_codebase_context.<locals>.<genexpr>   s     
Pr2?
PrF   )sessionrX   rm   lastrm   i  z=== LATEST SESSION HANDOFF ===
c              3   &   K   | ]  }|v  
 y wrB   r&   rZ   s     r(   rE   z*gather_codebase_context.<locals>.<genexpr>   s     
Kr2?
KrF   )commitbranchrV   gitzgit log --oneline -5T   )shellcapture_outputtexttimeoutcwdz=== RECENT COMMITS ===


 )r^   openCONTEXT_FILESr:   append	Exceptionre   
subprocessrunGENESIS_DIRstdoutr_   join)r   context_partsfcontentresultr\   s        @r(   gather_codebase_contextr      sx   MI-)3/ 	&1ffhuoG	&GyQR
 
P%O
PP	mI.4 *&&(5D/*  #CG9!MN
 
K%J
KK	^^&d41+F }}$$'?@S@S@U?V%WX *76;;}%>B>7	& 	&  * *  		  		sd   D= D1D= -E  EE AE' 1D:6D= =	E	E	EE 	E$#E$'	E32E3rz   	max_charsc                     t        |       |k  r| dfS | d| j                  d      }||dz  kD  r
| d|dz    dfS | d| dz   dfS )z%Truncate response for voice delivery.FNz.       T...)lenrfind)rz   r   cuts      r(   truncate_for_voicer      sg    
4yIU{
z	

 
 
&C
Y!^IcAg$$
e#T))r'   c           	        K   g d}| j                         }|D ]  }||v sd| dc S  ddddddd	d
d}|j                         D ]  \  }}||v s|}  n t        j                  | t        j                  j
                  t        j                  j
                  t               d{   }	 t        j                  |j                         t               d{   \  }}	|j                  dd      }
|	r|
d|	j                  dd      z   z  }
|
j                         xs dS 7 {7 K# t        j                  $ r |j                          Y yw xY ww)z6Execute a bash command directly on the Genesis system.)zrm -rfmkfszdd if=z> /dev/z:(){ :|:& };:z-Blocked: dangerous command pattern detected ()zls -lazdf -hzfree -hpwd
git statuszgit branch -azgit log --oneline -10)z
list filesz
show filesz
disk spacezmemory usagezcurrent directoryr   zshow brancheszrecent commits)r   stderrr|   Nr{   utf-8replaceerrors
z(no output)z#Command timed out after 30 seconds.)r^   itemsasynciocreate_subprocess_shellr   PIPEr   wait_forcommunicateMAX_BASH_TIMEOUTdecoder_   TimeoutErrorkill)r   	dangerousr\   dvoice_to_bashrS   r9   procr   r   outputs              r(   execute_bashr      sh     III H	>B1#QGGH !""(1	M %**, tIG
 00!!&&!!&&	 D
5&//(8 
 
 wy9dV]]79]EEEF||~..
  5		45sT   E.EAE%D!&E+,D% D#AD%  E#D% %#EE
EEc                 f  K   t        j                  d|       }|r|j                  d      }n;dddddd}d}|j                         D ]  \  }}|| j	                         v s|} n |sy|j                  d	      s$t        j                  j                  t        |      }t        j                  j                  |      sd
| S 	 t        |ddd      5 }|j                         }ddd       t              t        kD  r|dt         dz   }|S # 1 sw Y   )xY w# t        $ r}d| cY d}~S d}~ww xY ww)z&Read a file from the Genesis codebase.z=(/[\w/.-]+|\b[\w/.-]+\.(py|ts|js|md|json|txt|yaml|toml|sh))\br   rk   rl   z%.claude/rules/GLOBAL_GENESIS_RULES.md)rM   rL   rJ   rm   rulesNzNI couldn't identify which file you want me to read. Please specify a filename./zFile not found: ro   r   r   )encodingr   z
... (truncated)zError reading file: )ra   rb   groupr   r^   r4   ospathr   r   existsr   r:   r   MAX_RESPONSE_CHARSr   )	r   
path_matchfilepathkeyword_filesr[   fpr   r   es	            r(   execute_readr     s?     []deJ##A& "!"8<
 #))+ 	FBW]]_$	 c s#77<<X677>>(#!(,,*(C')D 	ffhG	w<,,1125HHG		 	
  *%aS))*sU   AD1 A!D1D D
"'D 	D1
DD 	D.D)#D.$D1)D..D1r   c           	        K   | }|rd| d|  }|dz  }t         j                  j                         D ci c]  \  }}|dk7  s|| }}}d|d<   t        j                  t
        d|t        j                  j                  t        j                  j                  t        |       d	{   }	 t        j                  |j                         t        
       d	{   \  }}|j                  dd      j                         }	|	s#|r!|j                  dd      j                         }	|	xs dS c c}}w 7 7 [# t        j                  $ r |j                          Y yw xY ww)zIExecute via claude -p (full terminal agent with Genesis codebase access).zContext from voice call: z

Task: z

IMPORTANT: Keep your response concise and spoken-word friendly. No markdown formatting, no code blocks, no URLs. Respond as if speaking on a phone call. 2-4 sentences max unless the task requires more.
CLAUDECODE1(CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICz-p)r   r   r|   envNr   r   r   r   z1Claude completed the task but returned no output.zrThe terminal agent timed out. The task may be too complex for a voice command. Try breaking it into smaller steps.)r   environr   r   create_subprocess_exec
CLAUDE_CLIr   r   r   r   r   MAX_CLAUDE_TIMEOUTr   r_   r   r   )
r   r   promptkv	clean_envr   r   r   r   s
             r(   execute_clauder   .  s^    F,WIZyI   ^  ^F #%**"2"2"4J$!Q\8IAJIJ<?I89//D&!!&&!!&& D
D&//(: 
 
 wy9??A&]]79]=CCEFLLL# K
  D		 DDsZ   3E D-D-AE 'D3(E -,D7 D5AD7 ,E 5D7 7#EE EE c                 T  K   | }|rd| d|  }d}dd|igidd|igigdddd	}	 t        j                  t        
      4 d{   }|j                  t         dt
         |       d{   }|j                  dk(  r|j                         }|j                  dg       }|r`|d   j                  di       j                  dg       }	dj                  d |	D              j                         }
|
r|
cddd      d{    S 	 ddd      d{    y|j                  dk(  rt        j                  d       d{    |j                  t         dt
         |       d{   }|j                  dk(  r|j                         }|j                  dg       }|r`|d   j                  di       j                  dg       }	dj                  d |	D              j                         }
|
r|
cddd      d{    S 	 ddd      d{    y|j                  dd }d|j                   d| cddd      d{    S 7 7 7 I7 :7 7 7 Z7 J7 # 1 d{  7  sw Y   yxY w# t         j                  $ r Y yt        $ r}dt!        |      dd  cY d}~S d}~ww xY ww)zUExecute via Gemini API (free, fast, good for general questions and codebase queries).z	Context: z

Question: a  You are AIVA, the Genesis AI voice assistant. You are responding to a voice call. Keep responses concise and spoken-word friendly. No markdown, no code blocks, no URLs. 2-4 sentences unless more detail is needed. Speak naturally as if in a phone conversation.partsrz   r   gffffff?)maxOutputTokenstemperature)system_instructioncontentsgenerationConfigr   Nz?key=)json   
candidatesr   r    c              3   @   K   | ]  }|j                  d d        ywrz   r~   NgetrC   ps     r(   rE   z!execute_gemini.<locals>.<genexpr>p  s     #E!AEE&"$5#E   z"Gemini returned an empty response.i  r   c              3   @   K   | ]  }|j                  d d        ywr   r   r   s     r(   rE   z!execute_gemini.<locals>.<genexpr>  s     'Iafb(9'Ir   zAGemini is temporarily rate limited. Please try again in a moment.zGemini API error (z): z)Gemini timed out. Try a simpler question.zGemini error: )httpxAsyncClientMAX_GEMINI_TIMEOUTpostGEMINI_API_URLr
   status_coder   r   r   r_   r   sleeprz   TimeoutExceptionr   r#   )r   r   r   r   payloadclientrespdatar   r   rz   resp2
error_textr   s                 r(   execute_geminir   O  s    FWI^G9=	9   '&2D)E(FG 0123"
G%/$$-?@  	N  	NF!"%'78 %  D 3&yy{!XXlB7
&qM--i<@@"ME88#Eu#EEKKMD# 	N  	N  	N < 	N  	N  	N !!S(mmA&&&$kk%&eN+;<  *   $$+ ::<D!%,!;J! *1 1 1)R @ D DWb Q"xx'I5'IIOOQ#'9 	N  	N  	N: [; 	N  	N  	N> "YYt_
+D,<,<+=SMA 	N  	N  	N 	N  	N  '# 	N  	N  	N  	N  	N  	NB !! ;: /At~../s\  #J(I- II- $I,I-BI2I- >I?I- J(II- I
I- J('I=I>'I%I&BI+I- 7I8I- <J(=I>I- 	I
I- J( I/I- ;I<I-  J(I- II- 
I- III- I- I- I*I!I*&I- )J(*I- -J% J(J%
J J%J( J%%J(z/execute)response_modelbodyc                 V  K   t        |      st        dd      t        j                         }| j                  }|dk(  rt	        | j
                        }|dk(  rt        | j
                         d{   }n|dk(  rt        | j
                         d{   }n|dk(  r)t        | j
                  | j                         d{   }n|d	k(  r)t        | j
                  | j                         d{   }nf|d
k(  rQt        | j
                        }| j                  xs d}|r|r| d| n|}t        | j
                  |       d{   }nt        dd|       t        |      \  }}t        t        j                         |z
  dz        }	t        |||	|      S 7 +7 7 7 7 _w)z5Execute a voice command against the Genesis terminal.i  Unauthorized)r   detailr   r9   Nr:   terminalr]   r;   r~   r}   i  zUnknown mode: i  )r+   r,   r-   r.   )r6   r   timer   rj   r   r   r   r   r   r   r   r   r%   r*   )
r   r0   startr   raw_responsecodebase_ctxfull_contextr+   r.   r-   s
             r(   execute_commandr     sw     }%NCCIIKE 99Dv~- v~)$,,77	)$,,77		+DLL$,,GG		+DLL$,,GG		.t||<||)rBNl^4~>T`L+DLL,GGnTF4KLL -\:Hityy{U*d23K	 - 87GG Hs\   A0F)2F3"F)F -F)F#-F)1F%2AF)F'AF) F)#F)%F)'F)z/healthc                     K   t         j                  j                  t              } t	        t
              }t         j                  j                  t              }ddd| |ddd|t        j                         dS w)zHealth check endpoint.okzgenesis-terminal-relayz1.1.0T)claude
gemini_apir9   r:   )rL   servicer   backendsgenesis_dir	timestamp)	r   r   r   r   r/   r
   isdirr   r   )	claude_ok	gemini_ok
genesis_oks      r(   healthr	    sj      z*I^$I{+J +#	
 "YY[ s   A6A8__main__z/Starting Genesis Terminal Relay on port 8765...z  Claude CLI: z (OKMISSINGr   z  Gemini CLI: z  Genesis dir: z  Auth token:    r   z:Expose via: cloudflared tunnel --url http://localhost:8765z0.0.0.0i="  )hostportrB   )=__doc__r   r   r   r   ra   r   typingr   r   fastapir   r   r   r   fastapi.middleware.corsr   pydanticr	   r   r   
GEMINI_CLIr   r   r
   r   r   r   r   r   r   appadd_middlewarer   r*   r#   r/   r6   rd   r`   rc   rj   r   r   r   r   r%   tupler   r   r   r   r   r   r   r	  r    uvicornprintr   r   r&   r'   r(   <module>r     s  (   	  	    ; ; 2  &G
G
 02[\kjjnn],MN    ,g>   %5/%	  $Y $i  x}      $c $c $V ggll;4ww||K)JK
"?S "?S "?N 4F *S *S *%PSUYPYJZ *)5 )5 )5X&* &* &*RD# D D DB;/# ;/ ;/ ;/@ *_5 $*$<,
,C=, 6,^  0 z	
;<	N:,b
1KQZ([[\
]^	N:,b
1KQZ([[\
]^	OK=
)*	N;r?+3
/0	G	
FGGKK)$/ r'   