
    iwj                        U d Z ddlZddlZddlZddlZddlmZmZ ddlmZm	Z	 ddl
mZ ddlmZmZmZmZmZ ddlmZ ddlmZmZ ddlZddlZdd	lmZ ej6                  j9                  d
d      Zej6                  j9                  dd      Z eej6                  j9                  dd            Z ej6                  j9                  dd      Z!ej6                  j9                  dd      Z"ej6                  j9                  dd      Z# ejH                  ejJ                  dd        ejL                  d      Z'da(ee   e)d<   defdZ*defdZ+d Z,d Z-d Z.ed efd!       Z/ ed"d#d$e/%      Z0e0jc                  ed&gd&gd&g'        ed(      fd)e2fd*Z3 G d+ d,e      Z4 G d- d.e      Z5 G d/ d0e      Z6 G d1 d2e      Z7 G d3 d4e      Z8 G d5 d6e      Z9e0ju                  d7      d8efd9       Z;e0ju                  d:e6 ee3      g;      d<e4fd=       Z<e0j9                  d>e8 ee3      g;      d?        Z=e0ju                  d@e6 ee3      g;      d<e5fdA       Z>e0j9                  d@e8 ee3      g;      dB        Z?e0j                  dC ee3      gD      dVdEed<e9fdF       ZAe0j9                  dG ee3      gD      dWdHedIee2   fdJ       ZBe0ju                  dK      d8efdL       ZCe0j9                  dM      dN        ZDeEdOk(  rQddlFZF eej6                  j9                  dPdQ            ZGe'j                  dReG         eFj                  e0dSeGdTU       yy)Xa  
Genesis Command Bridge API

Voice-to-Terminal directive relay between Kinan (via AIVA on Telnyx)
and Claude Code command centre.

Architecture:
    Kinan (phone) -> AIVA (Telnyx Voice Assistant) -> Bridge API -> PostgreSQL <- Claude Code (polls)

Run:
    BRIDGE_API_KEY=your-secret-key uvicorn bridge_api:app --host 0.0.0.0 --port 8765

Environment Variables:
    BRIDGE_API_KEY          - API key for authentication (required)
    GENESIS_POSTGRES_HOST   - PostgreSQL host (default: Elestio)
    GENESIS_POSTGRES_PORT   - PostgreSQL port (default: 25432)
    GENESIS_POSTGRES_USER   - PostgreSQL user (default: postgres)
    GENESIS_POSTGRES_PASSWORD - PostgreSQL password
    GENESIS_POSTGRES_DATABASE - PostgreSQL database (default: postgres)
    N)datetimetimezone)OptionalList)asynccontextmanager)FastAPIHTTPExceptionDependsHeaderRequest)CORSMiddleware)	BaseModelField)ThreadedConnectionPoolBRIDGE_API_KEYzgenesis-bridge-2026GENESIS_POSTGRES_HOSTz(postgresql-genesis-u50607.vm.elestio.appGENESIS_POSTGRES_PORT25432GENESIS_POSTGRES_USERpostgresGENESIS_POSTGRES_PASSWORDzetY0eog17tD-dDuj--IRHGENESIS_POSTGRES_DATABASEz.%(asctime)s [BRIDGE] %(levelname)s %(message)sz%Y-%m-%d %H:%M:%S)levelformatdatefmtcommand_bridgepoolreturnc                      t        ddt        t        t        t        t
        ddddd      } t        j                  dt         dt         dt
                | S )	zNCreate a fresh connection pool with TCP keepalives to prevent idle disconnect.   
         )minconnmaxconnhostportuserpassworddatabase
keepaliveskeepalives_idlekeepalives_intervalkeepalives_countconnect_timeoutzPostgreSQL pool created -> :/)r   PG_HOSTPG_PORTPG_USERPG_PASSPG_DBloginfo)ps    7/mnt/e/genesis-system/AIVA/command_bridge/bridge_api.py_create_poolr;   D   sW    	A HH*7)1WIQugFGH    c                  .    t         
t               a t         S N)r   r;    r<   r:   get_poolr@   Y   s    |~Kr<   c                  f   	 t               j                         } | j                         j                  d       | S # t        $ rl}t
        j                  d| d       	 t        rt        j                          n# t        $ r Y nw xY wt               at        j                         cY d}~S d}~ww xY w)zMGet a connection from the pool, recreating pool if all connections are stale.SELECT 1zStale pool detected (u   ) — recreating poolN)
r@   getconncursorexecute	Exceptionr7   warningr   closeallr;   )connes     r:   get_connrK   `   s    z!!#j) +A3.CDE	 		~||~s?   8; 	B0B+A98B+9	BB+B B+%B0+B0c                     	 t               j                  |        y# t        $ r$ 	 | j                          Y y# t        $ r Y Y yw xY ww xY w)z Return a connection to the pool.N)r@   putconnrF   close)rI   s    r:   put_connrO   s   sF    
4  	JJL 			s$    	A	8	AA	AA	c                  $   t               } 	 | j                         }t        t        j                  j                  t        j                  j                  t              d      d      j                         }|j                  |       | j                          |j                          t        j                  d       	 t#        |        y# t        $ r.}| j                          t        j!                  d|         d}~ww xY w# t#        |        w xY w)z,Create schema and table if they don't exist.z
schema.sqlrzSchema genesis_bridge ensuredzSchema creation failed: N)rK   rD   openospathjoindirname__file__readrE   commitrN   r7   r8   rF   rollbackerrorrO   )rI   cur
schema_sqlrJ   s       r:   ensure_schemar^      s    :DkkmGGLL2LA3

$& 	 	J		01 	  		,QC01
 	s$   B/C 	C?)C::C??D Dappc                   K   t         j                  d       t                t         j                  d       d t        r*t        j	                          t         j                  d       yyw)zStartup/shutdown lifecycle.zCommand Bridge starting up...z5Command Bridge ONLINE - Kinan <-> Claude relay activeNz%Command Bridge shut down, pool closed)r7   r8   r^   r   rH   )r_   s    r:   lifespanra      sH      HH,-OHHDE	89 s   A+A-zGenesis Command Bridgez?Voice-to-Terminal directive relay: Kinan -> AIVA -> Claude Codez1.0.0)titledescriptionversionra   *)allow_originsallow_methodsallow_headers)defaultx_bridge_keyc                 8   K   | t         k7  rt        dd      yw)zSimple API key authentication.i  zInvalid or missing X-Bridge-Keystatus_codedetailT)r   r	   )rj   s    r:   verify_api_keyro      s     ~%4UVVs   c                       e Zd ZU dZ edd      Zeed<    edd      Zeed	<    ed
d      Z	eed<    ee
d      Ze
ed<   y)DirectiveRequestz*Directive from Kinan (via AIVA) to Claude..zThe directive from Kinanrc   messagenormallow/normal/high/urgentri   rc   priority
aiva_voicezOrigin of the directivesourceExtra contextdefault_factoryrc   metadataN)__name__
__module____qualname____doc__r   rs   str__annotations__rw   ry   dictr}   r?   r<   r:   rq   rq      sL    4*DEGSE(8PQHcQ:STFCT4_MHdMr<   rq   c                   l    e Zd ZU dZ edd      Zeed<    edd      Zeed	<    ee	d
      Z
e	ed<   y)StatusRequestz#Status update from Claude to Kinan..zStatus update textrr   rs   rt   ru   rv   rw   rz   r{   r}   N)r~   r   r   r   r   rs   r   r   rw   r   r}   r?   r<   r:   r   r      s:    -*>?GS?(8PQHcQ4_MHdMr<   r   c                   0    e Zd ZU dZeed<   eed<   eed<   y)DirectiveResponsez#Response after queuing a directive.statusidrs   N)r~   r   r   r   r   r   intr?   r<   r:   r   r      s    -KGLr<   r   c                   \    e Zd ZU dZeed<   eed<   eed<   eed<   dZee   ed<   i Z	e
ed<   y)	QueuedMessagezA message from the queue.r   rs   rw   
created_atNry   r}   )r~   r   r   r   r   r   r   ry   r   r}   r   r?   r<   r:   r   r      s1    #GLMO FHSM Hdr<   r   c                   ,    e Zd ZU dZee   ed<   eed<   y)StatusResponsezResponse with pending messages.updatescountN)r~   r   r   r   r   r   r   r   r?   r<   r:   r   r      s    )-  Jr<   r   c                   6    e Zd ZU dZ edd      Zee   ed<   y)ExecuteRequestz4Mark a directive as executed with optional response.NzExecution result summaryrr   response)	r~   r   r   r   r   r   r   r   r   r?   r<   r:   r   r      s    >#D6PQHhsmQr<   r   z/bridge/telnyx-webhookrequestc           
      ^  K   | j                          d{   }t        j                  dt        j                  |d      dd         	 d}i }d|v r(|d   }|j	                  d|j	                  di             }nqd	|v rm|d	   }d|v r(|d   }|j	                  d|j	                  di             }n<d
|v r8|d
   }|j	                  d      }|j	                  d|j	                  di             }t        |t              r	 t        j                  |      }|dk(  r|j	                  dd      }|j	                  dd      }|sddiS t               }	 |j                         }	|	j                  d||t        j                  ddi      f       |	j                         d   }
|j                          |	j                          t        j                  d|
 d| d|dd         dd|
 d| dit        |       S |dk(  r't               }	 |j                  t&        j(                  j*                         }	|	j                  d!       |	j-                         }|j                          |	j                          |sdd"it        |       S g }|D ]4  }|d   dk7  r	d#|d    d$nd}|j/                  d%|d&    | d'|d(           6 d)t1        |       d*t1        |      d+kD  rd,nd d-d.j3                  |      z   }t        j                  d/t1        |       d0       d|it        |       S |d3k(  rR|j	                  d4d      }|j	                  d5d6      }|j	                  d7d8      }|j	                  d9      xs% |j	                  d:      xs |j	                  d:d      }|j	                  d;d      }t               }	 |j                         }	|	j                  d<t        |      dd= t        |      dd> t        |      j5                         rt7        |      ndt        |      dd= |d?k(  rd?n|d@k(  rdAnd8f       |j                          |	j                          t        j                  dB| dC|        ddDit        |       S t        j9                  dG|        ddH| dIiS 7 # t         j                  $ r d|i}Y w xY w# t         $ rP}|j#                          t        j%                  d|        ddt        |      dd  icY d}~t        |       S d}~ww xY w# t        |       w xY w# t         $ rP}|j#                          t        j%                  d1|        dd2t        |      dd  icY d}~t        |       S d}~ww xY w# t        |       w xY w# t         $ rA}|j#                          t        j%                  dE|        ddFicY d}~t        |       S d}~ww xY w# t        |       w xY w# t         $ r5}t        j%                  dJ|        ddKt        |      dd  icY d}~S d}~ww xY ww)Lz
    Handle Telnyx Voice Assistant tool webhook calls.

    Telnyx sends the tool call details here. We parse the function name
    and parameters, execute the appropriate action, and return the result
    for AIVA to speak back to Kinan.
    NzTelnyx webhook received:    )indent  function_name	argumentsfunction_argumentsdatapayload	directiverelay_directive_to_claude rw   rt   resultz>No directive provided. Please tell me what to relay to Claude.zINSERT INTO genesis_bridge.command_queue
                       (direction, message, priority, source, metadata)
                       VALUES ('kinan_to_claude', %s, %s, 'aiva_voice', %s)
                       RETURNING idviatelnyx_webhookr   DIRECTIVE #	 queued []: d   z2Got it. I've relayed that to Claude as directive #z with z* priority. Claude will pick it up shortly.Failed to queue directive: z8Sorry, I couldn't relay that to Claude. Database error: check_claude_statuscursor_factoryzUPDATE genesis_bridge.command_queue
                       SET status = 'read', read_at = NOW()
                       WHERE direction = 'claude_to_kinan' AND status = 'pending'
                       RETURNING id, message, priority, created_at, metadatazLNo new updates from Claude at the moment. Everything is running as expected. (z
 priority)zUpdate r   : rs   zI have z updater    sz from Claude. z ... 
Delivered z! status updates to Kinan via AIVAFailed to fetch status: z:Sorry, I couldn't check Claude's status right now. Error: log_conversation_summarysummaryoutcome	completedcaller_moodneutralfromcaller_numberduration_secondszINSERT INTO aiva_rlm.aiva_interactions
                       (call_id, caller_number, transcript, call_duration_seconds, outcome, outcome_label)
                       VALUES (gen_random_uuid()::text, %s, %s, %s, %s, %s)2   i  positive
frustratednegativez3Call logged to aiva_rlm.aiva_interactions: outcome=z, mood=z<Logged. Thank you, AIVA. Your growth data has been recorded.zFailed to log conversation: z.Note logged locally. Database sync will retry.zUnknown function: z I don't recognize the function 'z*'. I can relay directives or check status.zWebhook processing error: z.Something went wrong processing that request: )jsonr7   r8   dumpsget
isinstancer   loadsJSONDecodeErrorrK   rD   rE   fetchonerY   rN   rO   rF   rZ   r[   psycopg2extrasRealDictCursorfetchallappendlenrU   isdigitr   rG   )r   bodyr   r   r   r   r   rw   rI   r\   cmd_idrJ   rowsr   rowr9   result_textr   r   r   r   durations                         r:   r   r      sJ     DHH(D)CDS)I(JKLI[	 d" 1Mdhh7KR.PQIt^<D$& $_ 5 HH[$((;OQS2TU	d"y/ 'O <#KKW[[AUWY5Z[	 i%5 JJy1	 77!k26I }}Z:H "bcc :Dkkm' $**e=M5N*OP *		;vhizYtPS_DUVW RSYRZZ`ai`j  kU  V 33:Dkk1O1OkPP ||~		$&tu    OC<?
Ox<W"S_-Z8]_ANNWSYKs"S^<L#MNO !(D	{'TQ#TV9WWefipiuiuv}i~~:c$i[0QRS +. 88mmIr2GmmI{;G#--yAK   6DHH_$= 6=="5  !}}%7;H:DkkmO M*3B/GUd+),X)>)>)@HaGSb)&1Z&?
&1\&A
y	 		NwiW^_j^klm "`a  KK,]O<= @Oyz{{U  8 '' 5()4	58  m		7s;< $\]`ab]cdheh]i\j"kllm
 :  o		4QC89 $^_bcd_efjgj_k^l"mnno
 D  T		8<= "RSST
   [		.qc23J3q6RVSV<.YZZ[s  X-R4X-B1W, >R .W, X-
W, BR7 %W, 0X-1W, A0T# 2W, =X->BT# W, X-BW, /B;V *W, 5X-6W, X-R40W, 3R44W, 7	T :T:T;T ?W, 
X-TT T  W, #	U<,:U7&U<'U? +W, 6X-7U<<U? ?VW, 	W+WWW W, X-WW W))W, ,	X*5*X%X* X-%X**X-z/bridge/directive)response_modeldependenciesreqc           
        K   | j                   dvrt        dd      t               }	 |j                         }|j	                  d| j
                  | j                   | j                  t        j                  | j                        f       |j                         d   }|j                          |j                          t        j                  d| d| j                    d	| j
                  d
d         t        d|| j
                        t!        |       S # t"        $ rC}|j%                          t        j'                  d|        t        dt)        |            d
}~ww xY w# t!        |       w xY ww)zi
    Queue a directive from Kinan to Claude.
    Called by AIVA via Telnyx tool webhook or directly.
    )lowrt   highurgenti  zInvalid priorityrl   zINSERT INTO genesis_bridge.command_queue
               (direction, message, priority, source, metadata)
               VALUES ('kinan_to_claude', %s, %s, %s, %s)
               RETURNING idr   r   r   r   Nr   queuedr   r   rs   r   r   )rw   r	   rK   rD   rE   rs   ry   r   r   r}   r   rY   rN   r7   r8   r   rO   rF   rZ   r[   r   r   rI   r\   r   rJ   s        r:   post_directiver     s'     ||>>4FGG:Dkkm [[#,,

DJJs||4LM	
 "		;vhi~STcAR@STU VS[[Q 	  <		/s34CF;;<
 	s5   &E4C D 	E4	E!>EE!!E$ $E11E4z/bridge/directivesc                    K   t               } 	 | j                  t        j                  j                        }|j                  d       |j                         }| j                          |j                          g }|D ][  }|j                  t        |d   |d   |d   |d   j                         |j                  d      |j                  di       	             ] |r"t        j                  d
t        |       d       t!        |t        |            t#        |        S # t$        $ rC}| j'                          t        j)                  d|        t+        dt-        |            d}~ww xY w# t#        |        w xY ww)z
    Claude polls this to get new directives from Kinan.
    Returns pending kinan_to_claude messages and marks them as 'read'.
    r   zUPDATE genesis_bridge.command_queue
               SET status = 'read', read_at = NOW()
               WHERE direction = 'kinan_to_claude' AND status = 'pending'
               RETURNING id, message, priority, created_at, source, metadatar   rs   rw   r   ry   r}   r   rs   rw   r   ry   r}   r   z directives to Clauder   r   zFailed to fetch directives: r   rl   NrK   rD   r   r   r   rE   r   rY   rN   r   r   	isoformatr   r7   r8   r   r   rO   rF   rZ   r[   r	   r   rI   r\   r   r   r   rJ   s         r:   get_directivesr     sF     :D"kk)G)GkHP	
 ||~		 
	CNN4y	N _"<0::<778, WWZ4	
	 HHz#g,/DEFgS\B 	  <		045CF;;<
 	5   E?DD  E? 	E,)>E''E,,E/ /E<<E?z/bridge/statusc           
        K   t               }	 |j                         }|j                  d| j                  | j                  t        j                  | j                        f       |j                         d   }|j                          |j                          t        j                  d| d| j                   d| j                  dd         t        d|| j                  	      t        |       S # t        $ rC}|j!                          t        j#                  d
|        t%        dt'        |            d}~ww xY w# t        |       w xY ww)zf
    Claude posts status updates for Kinan.
    AIVA will read these when Kinan asks for updates.
    zINSERT INTO genesis_bridge.command_queue
               (direction, message, priority, source, metadata)
               VALUES ('claude_to_kinan', %s, %s, 'claude_terminal', %s)
               RETURNING idr   zSTATUS #z	 posted [r   Nr   r   r   zFailed to post status: r   rl   )rK   rD   rE   rs   rw   r   r   r}   r   rY   rN   r7   r8   r   rO   rF   rZ   r[   r	   r   r   s        r:   post_statusr     s     :Dkkm [[#,,

3<<(@A	
 "		8F89S\\N#ckk$3>O=PQR VS[[Q 	  <		+A3/0CF;;<
 	s5   ECC/ #E/	D;8>D66D;;D> >EEc                    K   t               } 	 | j                  t        j                  j                        }|j                  d       |j                         }| j                          |j                          g }|D ][  }|j                  t        |d   |d   |d   |d   j                         |j                  d      |j                  di       	             ] |r"t        j                  d
t        |       d       t!        |t        |            t#        |        S # t$        $ rC}| j'                          t        j)                  d|        t+        dt-        |            d}~ww xY w# t#        |        w xY ww)z
    AIVA polls this to get status updates from Claude for Kinan.
    Returns pending claude_to_kinan messages and marks them as 'read'.
    r   zUPDATE genesis_bridge.command_queue
               SET status = 'read', read_at = NOW()
               WHERE direction = 'claude_to_kinan' AND status = 'pending'
               RETURNING id, message, priority, created_at, source, metadatar   rs   rw   r   ry   r}   r   r   z status updates for Kinanr   r   r   rl   Nr   r   s         r:   
get_statusr     sF     :D"kk)G)GkHP	
 ||~		 
	CNN4y	N _"<0::<778, WWZ4	
	 HHz#g,/HIJgS\B 	  <		,QC01CF;;<
 	r   z(/bridge/directive/{directive_id}/execute)r   directive_idc                 (  K   t               }	 |j                         }|r|j                  nd}|j                  d|| f       |j	                         }|j                          |j                          |st        dd      t        j                  d|  d       d| d	t        |       S # t        $ r  t        $ rC}|j                          t        j                  d
|        t        dt        |            d}~ww xY w# t        |       w xY ww)z:Mark a directive as executed, with optional response text.NzUPDATE genesis_bridge.command_queue
               SET status = 'executed', executed_at = NOW(), response = %s
               WHERE id = %s AND direction = 'kinan_to_claude'
               RETURNING idi  zDirective not foundrl   zDirective #z marked as executedexecuted)r   r   zFailed to mark executed: r   )rK   rD   r   rE   r   rY   rN   r	   r7   r8   rO   rF   rZ   r[   r   )r   r   rI   r\   response_textr   rJ   s          r:   mark_executedr   &  s      :Dkkm(+ L)	
 lln		C8MNN;|n,?@A$L9 	   <		-aS12CF;;<
 	s5   DBB* D*C?<>C::C??D DDz/bridge/historylimit	directionc                 ,  K   t               }	 |j                  t        j                  j                        }|r|j                  d|| f       n|j                  d| f       |j                         }|j                          |D ]%  }dD ]  }||   s	||   j                         ||<     ' |t        |      dt        |       S # t        $ r3}t        j                  d|        t        dt        |            d	}~ww xY w# t        |       w xY ww)
zGet recent command history.r   a  SELECT id, direction, message, priority, status, source,
                          created_at, read_at, executed_at, response, metadata
                   FROM genesis_bridge.command_queue
                   WHERE direction = %s
                   ORDER BY created_at DESC LIMIT %szSELECT id, direction, message, priority, status, source,
                          created_at, read_at, executed_at, response, metadata
                   FROM genesis_bridge.command_queue
                   ORDER BY created_at DESC LIMIT %s)r   read_atexecuted_at)historyr   zFailed to fetch history: r   rl   N)rK   rD   r   r   r   rE   r   rN   r   r   rO   rF   r7   r[   r	   r   )r   r   rI   r\   r   r   keyrJ   s           r:   get_historyr   G  s     :D!kk)G)GkHKK8
 E" KK8  ||~		  	4C? 4s8"3x113CH4	4
  #d)4
 		  <		-aS12CF;;< 	s;   DBC 'C 9D	D.C<<DD DDz/bridge/telnyx-transcriptc           
      X  K   	 | j                          d{   }t        j                  dt	        |      dd         	 |j                  d|      }|j                  d|      }|j                  d      xs |j                  d      xsm |j                  d      xsZ |j                  d      xsG |j                  d      xs4 d	t        j                  t        j                        j                          }|j                  d
      xsN |j                  d      xs; |j                  d      xs( |j                  d
      xs |j                  d      xs d}|j                  d      xs; |j                  d      xs( |j                  d      xs |j                  d      xs d}t        |t              rdj                  d |D              }nt	        |      }|j                  d      xs( |j                  d      xs |j                  d      xs d}	 t        t        |            }|j                  d      xs |j                  d      xs d}	t%               }
	 |
j'                         }|j)                  dt	        |      dd t	        |      dd |dd |t	        |	      dd |	dv rdndf       |
j+                          |j-                          t        j                  d| d| d        t3        |
       	 d#d$iS 7 # t        $ r i }Y w xY w# t         t"        f$ r d}Y w xY w# t        $ r2}|
j/                          t        j1                  d!|        Y d}~rd}~ww xY w# t3        |
       w xY w# t        $ r%}t        j1                  d"|        Y d}~d#d$iS d}~ww xY ww)%u,  
    Receive Telnyx post-call transcript and log to aiva_rlm.aiva_interactions.
    Configure in Telnyx: AI Assistant → transcription.webhook_url → this endpoint.

    Accepts any Telnyx transcript webhook format and extracts what it can.
    Returns 200 immediately so Telnyx doesn't retry.
    Nz$Telnyx transcript webhook received: i,  r   r   call_control_idcall_idr   zunknown-r   r   	caller_idr   
transcripttranscription
c           
   3      K   | ]I  }|j                  d d      j                          d|j                  d|j                  dd              K yw)role?r   contenttextr   N)r   upper).0ts     r:   	<genexpr>z$telnyx_transcript.<locals>.<genexpr>  sO      # 55$**,-RivbAQ0R/ST#s   AAr   r   r   r   r   a  
                INSERT INTO aiva_rlm.aiva_interactions
                    (call_id, caller_number, transcript, call_duration_seconds, outcome, outcome_label)
                VALUES (%s, %s, %s, %s, %s, %s)
                ON CONFLICT DO NOTHING
               r   iP  )r   resolvedsuccessr   r   zLogged call r   z s) to aiva_rlm.aiva_interactionsz&Failed to log transcript to aiva_rlm: z%Transcript webhook processing error: r   received)r   rF   r7   r8   r   r   r   nowr   utc	timestampr   listrU   r   float
ValueError	TypeErrorrK   rD   rE   rY   rN   rZ   r[   rO   )r   r   r   r   r   r   raw_transcriptr   r   r   rI   r\   rJ   s                r:   telnyx_transcriptr  o  s    \\^# HH3CIdsO3DEFO?xx%((9d+ KK)* C{{9%C{{4 C xx)*C xx	"	C
 (,,x||4>>@AB 	 KK {{?+{{;' xx xx(	
  	 KK% {{?+xx% xx(  	 nd+ #'# J
 ^,J KK*+ {{:&xx*+ 	 		5?+H ++i(NDHHY,?N; z	++-CKK  GTc"M"3B'6E"GSb!%)MM
S\ KKMIIKHH|G9Bxj8XYZ
 TN j!!q $ h I& 	H	2  	DMMOII>qcBCC	D TN ?		9!=>> j!!	?s   N*L K?L $N*GM9 L +2M9 BL+ /M9 ;N*?L LN*LN*L(%M9 'L((M9 +	M&4(M!M) !M&&M) )M66M9 9	N'N"N*"N''N*z/bridge/healthc                    K   	 t               } | j                         }|j                  d       |j                          t	        |        dddt        j                  t        j                        j                         dS # t        $ rO}dddt        |      dd	  t        j                  t        j                        j                         dcY d}~S d}~ww xY ww)
z Health check - no auth required.rB   healthyzgenesis-command-bridge	connected)r   servicer*   r  	unhealthyzerror: Nr   )rK   rD   rE   rN   rO   r   r  r   r  r   rF   r   )rI   r\   rJ   s      r:   healthr    s     
zkkmJ		  /#!hll3==?	
 	
  
!/!#a&#,0!hll3==?	
 	

s6   CA;B  ?C 	C	ACCCCC__main__BRIDGE_PORT8765z Starting Command Bridge on port z0.0.0.0r8   )r&   r'   	log_levelr>   )   N)Jr   rS   sysr   loggingr   r   typingr   r   
contextlibr   fastapir   r	   r
   r   r   fastapi.middleware.corsr   pydanticr   r   r   psycopg2.extraspsycopg2.poolr   environr   r   r2   r   r3   r4   r5   r6   basicConfigINFO	getLoggerr7   r   r   r;   r@   rK   rO   r^   ra   r_   add_middlewarer   ro   rq   r   r   r   r   r   postr   r   r   r   r   putr   r   r  r  r~   uvicornr'   r8   runr?   r<   r:   <module>r2     s  * 
 
   ' ! * D D 2 %   0  02GH **..02\
]
bjjnn4g>
?
**..0*
=
**..46M
N


2J?   
,,;
 g() *.h%& -, *( &	0 : : : 
"Q	   %%%	   .4D-A s Ny NNI N	 I Y RY R 
"#V[' V[ $V[| 
.?wWeOfNgh.  i> 	nGTbLcKde( f(V 
+<GTbLcKde=  f8 	.P^H_G`a( b(V 	37>CZB[\c   ]@ 	'.*A)BC$S $(3- $ D$N 
%&a"W a" 'a"H 	
 
8 zrzz~~mV45DHH/v67GKK)$&A r<   