
    ɰSjn                    4   U d Z ddlm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
mZ ddlmZmZmZmZmZmZ  ej        e          ZdZdRd
ZdddSdZdTdZdZdUdZ e	d          dVd            Z e	d          dWd!            Zeeed"dXd%ZdYd'ZdZd)Z d* Z!dZ"dZ#d+ Z$d[d.Z%ddd/d\d3Z&d4Z'd5Z(d6e)d7<   d]d9Z*d^d;Z+d_d?Z,d`d@Z-ddd/d\dAZ.dRdBZ/dCZ0e1e1e2e2e2e2f         e1e2e2e2e2f         f         Z3dadFZ4dbdGZ5 G dH dI          Z6dedJddKdcdQZ7dS )du)  Decode a pet spritesheet and encode frames for a terminal.

Shared by the base CLI (writes the escape bytes to its own stdout) and the
TUI (``tui_gateway`` ships the encoded bytes to Ink, which writes them) so the
decode + capability-detection + protocol-encoding logic exists exactly once.

Supported output modes, in fidelity order:

- ``kitty``   — the kitty graphics protocol (kitty, Ghostty, WezTerm).
- ``iterm``   — iTerm2 inline images (iTerm2, WezTerm).
- ``sixel``   — DEC sixel (xterm -ti vt340, foot, mlterm, WezTerm, …).
- ``unicode`` — 24-bit half-block downscale; works in any truecolor terminal.

Frame decoding requires Pillow (a core Hermes dependency).  If Pillow or the
spritesheet is unavailable the renderer degrades to ``unicode`` text or an
empty string rather than raising.
    )annotationsN)	lru_cache)Path)DEFAULT_SCALEFRAME_HFRAME_WFRAMES_PER_STATEPetStatestate_row_index)autokittyitermsixelunicodeoffreturnstrc                     t           j                            dd                                          } t           j                            dd                                          }|dk    rdS t           j                            d          sd| v sd| v rdS |d	v rdS |d
k    st           j                            d          rdS |dk    st           j                            d          rdS |dv sd| v sd| v rdS d| v rdS dS )uH  Best-effort detection of the richest graphics protocol available.

    Env-based (non-blocking — we never issue a DA1/terminal query that could
    hang a pipe).  Returns one of ``kitty`` / ``iterm`` / ``sixel`` /
    ``unicode``.  Conservative: unknown terminals get ``unicode``, which works
    anywhere with truecolor.
    TERM TERM_PROGRAMvscoder   KITTY_WINDOW_IDr   ghostty>   r   weztermWEZTERM_PANEz	iterm.appITERM_SESSION_IDr   >   minttyfootmltermr   )osenvirongetlower)termterm_programs     6/home/thesage/.hermes/hermes-agent/agent/pet/render.pydetect_terminal_graphicsr(   0   s    :>>&"%%++--D:>>."55;;==L xy 
z~~'(( GtOOyD?P?Pw{""w y  BJNN>$B$B w {""bjnn5G&H&H"w z!!Vt^^x47G7Gw$w9    stream
configured
str | Nonec               @   | pd                                                                 }|t          vrd}|dk    rdS |pt          j        }	 t          |d          r|                                sdS n# t          t          f$ r Y dS w xY w|dk    rt                      S |S )u   Resolve the effective render mode from config + the environment.

    ``configured`` is ``display.pet.render_mode`` (``auto`` → detect).  Returns
    ``off`` when not attached to a TTY (no point emitting graphics into a pipe
    or logfile).
    r   r   isatty)
stripr$   RENDER_MODESsysstdouthasattrr/   
ValueErrorOSErrorr(   )r,   r+   modes      r'   resolve_moder8   ]   s      &''))//11D<u}}u!szF)) 	fmmoo 	5	    uu v~~')))Ks   $A2 2BBpathr   c                b    ddl m} |                    |           }|                    d          S )Nr   ImageRGBA)PILr<   openconvert)r9   r<   imgs      r'   _open_sheetrB   z   s7    
**T

C;;vr)      boolc                n    |                      d                                          d         t          k    S )zGTrue if *frame* has no meaningfully opaque pixel (transparent padding).A   )
getchannel
getextrema_BLANK_ALPHA)frames    r'   _frame_is_blankrL      s,    C  ++--a0L@@r)      )maxsize
sheet_pathstate_valueframe_wintframe_hframes_per_statetuplec                r   	 t          t          |                     }t          d|j        |z            }t          d|j        |z            }t          ||          }||z  }	|	|z   |j        k    rt          d|j        |z
            }	g }
t          t          ||                    D ]L}||z  }|                    ||	||z   |	|z   f          }t          |          r n|

                    |           Mt          |
          S # t          $ r(}t                              d| ||           Y d}~dS d}~ww xY w)a  Cropped, padding-trimmed RGBA frames for one state row (unscaled).

    Steps across the row until the first blank column so pets with ragged
    per-state frame counts never animate into empty padding.  Cached; returns
    ``()`` on any decode failure.
    rG   r   z$pet frame decode failed (%s, %s): %sN )rB   r   maxwidthheightr   rangemincroprL   appendrU   	Exceptionloggerdebug)rO   rP   rQ   rS   rT   sheetcolsrowsrowtopframesileftrK   excs                  r'   _raw_framesrk      sW   D,,--1ekW,--1elg-..k400Gm =5<''a/00Cs+T2233 	! 	!Aw;DJJc4'>3=IJJEu%% MM%    V}}   ;ZVYZZZrrrrrs   DD 
D6D11D6scale_wscale_hc                    t          | ||||          }|r
f||fk    rt          |          S ddlm fd|D             S )zReturn padding-trimmed RGBA frames for one state row, scaled.

    Thin scaling layer over :func:`_raw_frames`; both are cached so repeated
    frame requests during animation are free.
    r   r;   c                J    g | ]}|                     fj                   S rW   resizeLANCZOS).0fr<   rm   rl   s     r'   
<listcomp>z_frames_for.<locals>.<listcomp>   s.    EEEAAHHgw'77EEEr)   )rk   listr>   r<   )	rO   rP   rQ   rS   rT   rl   rm   rawr<   s	        `` @r'   _frames_forrx      sw     j+wAQ
R
RC 7G$'(:::CyyEEEEEEEEEEr)   )rQ   rS   rT   
str | Pathdict[str, int]c               6      fdt           D             S )u3  Map each driven :class:`PetState` → its real (padding-trimmed) frame count.

    The single source of truth for "how many frames does this state actually
    have?".  The CLI/TUI consume the trimmed frame lists directly; the gateway
    ships this map to the desktop canvas, which steps its own loop.
    c                    i | ]:}|j         t          t          t                    |j                             ;S rW   )valuelenrk   r   )rs   staterS   rQ   rT   rO   s     r'   
<dictcomp>z&state_frame_counts.<locals>.<dictcomp>   sU         	SJgwHXYY
 
  r)   )r
   )rO   rQ   rS   rT   s   ````r'   state_frame_countsr      sB           	   r)   bytesc                ~    t          j                    }|                     |d           |                                S )NPNG)format)ioBytesIOsavegetvalue)rK   bufs     r'   
_png_bytesr      s1    
*,,C	JJs5J!!!<<>>r)    tuple[int, int, int, int] | Nonec                f   dx}x}x}}| D ]}	 |                     d                                          }n# t          $ r d}Y nw xY w|s@|\  }}}	}
||nt          ||          }||nt          ||          }||	nt	          ||	          }||
nt	          ||
          }||||dS ||||fS )zFUnion opaque-pixel bbox across *frames* (a stable trim for animation).NrF   )rH   getbboxr_   r\   rX   )rg   ri   rf   rightbottomrK   bboxltrbs              r'   _union_alpha_bboxr      s   "&&D&3& 9 9	##C((0022DD 	 	 	DDD	 	
1aLqqc$ll;aaCQKK]E1n#fa..|s{emv~t#uf%%s   '6AAc                F    t          |           s| S fd| D             S )a1  Crop every frame to the union opaque bbox so the sprite hugs its box.

    kitty paints the whole transmitted rectangle, transparent margins included,
    which makes the visible pet look small and adrift inside a larger cell box.
    Trimming to the visible bounds keeps the pet tight in its corner.
    c                :    g | ]}|                               S rW   )r]   )rs   rt   r   s     r'   ru   z/_crop_frames_to_alpha_union.<locals>.<listcomp>  s#    )))QAFF4LL)))r)   )r   )rg   r   s    @r'   _crop_frames_to_alpha_unionr      s9     V$$D ))))&))))r)   c                (   | s| S ddl m | d         j        \  }}t          dt	          |t
          z                      }t          dt	          |t          z                      }|t
          z  |t          z  f||fk    r| S fd| D             S )zResize frames so width/height are exact multiples of the cell box.

    Removes the sub-cell remainder kitty would otherwise round up + clip. All
    frames share the union-cropped size, so they snap to the same cell grid.
    r   r;   rG   c                F    g | ]}|                     j                  S rW   rp   )rs   rt   r<   targets     r'   ru   z-_snap_frames_to_cell_grid.<locals>.<listcomp>$  s)    <<<AHHVU]++<<<r)   )r>   r<   sizerX   round_CELL_W_CELL_H)rg   whrc   rd   r<   r   s        @@r'   _snap_frames_to_cell_gridr     s      !9>DAqq%G$$%%Dq%G$$%%DWndWn-F	1v<<<<<V<<<<r)   ctrldatac                   d}t          |          |k    r	d|  d| dS d|  d|d|          dg}||d         }|r6|d|         ||d         }}|                    d|rdnd	 d
| d           |6d                    |          S )uK   Emit a kitty APC escape for *data*, chunked into ≤4096-byte ``m`` pieces.i   z_Gz,m=0;\z,m=1;Nz_Gm=rG   r   ;r   )r~   r^   join)r   r   chunkoutrestpieces         r'   
_kitty_apcr   '  s    E
4yyE///4////3D33tFUF|333
4C<D
 @6E6lDLt

>4.aaQ>>>>>???  @ 773<<r)   	cell_cols	cell_rowsr   
int | Noner   c                   d}|r|d| z  }|r|d| z  }t          |t          j        t          |                                         d                    S )zEncode one frame via the kitty graphics protocol (transmit + display).

    ``a=T`` transmits & displays at the cursor; ``c``/``r`` request a display
    box in terminal cells so successive frames overwrite the same area.
    zf=100,a=T,q=2,c=,r=asciir   base64standard_b64encoder   decode)rK   r   r   r   s       r'   _encode_kittyr   4  sq     D "!i!!! "!i!!!dF5j6G6GHHOOPWXXYYYr)   u   􎻮()  i  i  i  i  i  i=  i>  i?  iF  iJ  iK  iL  iP  iQ  iR  iW  i[  ic  id  ie  if  ig  ih  ii  ij  ik  il  im  in  io  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  iW  iX  iY  iZ  i[  i]  i^  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i0  i2  i3  i5  i6  i:  i=  i?  i@  iA  iC  iE  iG  iI  iJ  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i   i!  i"  i#  i%  i&  i'  i)  i*  i+  i,  i-  iQ	  iS	  iT	  i  i  i  i  i]  i^  i_  i  i:  i  iu  iv  iw  ix  iy  iz  i{  i|  ik  im  in  io  ip  iq  ir  is  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i   i   i   i   i   i   i   i   i   i   i   i   i,  i,  i,  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  i-  io  i|  i}  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i  i   i!  i"  i#  i$  i%  i&  i
 i8
 i i i i i i i i i iB iC iD ztuple[int, ...]_ROWCOL_DIACRITICSslugc                f    ddl }|                    |                     d                    dz  dz   S )a\  Stable per-pet image id in ``[1, 0x7FFF]``.

    The id is encoded in the placeholder's 24-bit foreground color, so it must
    be non-zero and fit comfortably under ``0xFFFFFF``. A small CRC keeps it
    deterministic per slug (so re-renders reuse the same terminal-side image)
    while making collisions between two different pets unlikely.
    r   Nzutf-8i  rG   )zlibcrc32encode)r   r   s     r'   kitty_image_idr   v  s5     KKKJJt{{7++,,v5::r)   image_idc                    d| dz  z  S )zEHex foreground color (``#rrggbb``) that encodes *image_id* for kitty.z#%06xi rW   )r   s    r'   kitty_color_hexr     s    h)**r)   rc   rd   	list[str]c                >   t          d|           } g }t          t          d|                    D ]l}t          |t          t                    dz
            }t
          t          t          |                   z   }|                    |t
          | dz
  z  z              m|S )ug  Build the placeholder text grid for an *rows*×*cols* image.

    Each line is one row of the grid: the first cell carries the row diacritic
    (column defaults to 0), and the remaining ``cols-1`` bare placeholders let
    the terminal auto-increment the column. The foreground color (the image id)
    is applied by the caller / Ink, not embedded here.
    rG   )rX   r[   r\   r~   r   _KITTY_PLACEHOLDERchrr^   )rc   rd   r   r   idxfirsts         r'   kitty_placeholder_rowsr     s     q$<<DC3q$<<   < <!S+,,q011"S);C)@%A%AA

5-::;;;;Jr)   c                   d| d| d| d}t          |t          j        t          |                                         d                    S )a  Transmit a frame as a kitty *virtual* placement for Unicode placeholders.

    ``a=T`` transmits and creates the placement in one shot; ``U=1`` marks it
    virtual (no on-screen output, cursor untouched); ``q=2`` suppresses the
    terminal's OK/error replies that would otherwise corrupt the host app's
    output. Re-sending with the same ``i`` replaces the image, so the static
    placeholder cells animate underneath.
    z
a=T,U=1,i=r   r   z
,f=100,q=2r   r   )rK   r   rc   rd   r   s        r'   _encode_kitty_virtualr     sV     ?>>T>>d>>>DdF5j6G6GHHOOPWXXYYYr)   c               8   t          j        t          |                                         d          }t	          |          }dd| dg}|r|                    d|            |r|                    d|            dd                    |           d	| d
S )z;Encode one frame as an iTerm2 inline image (OSC 1337 File).r   zinline=1zsize=zpreserveAspectRatio=1zwidth=zheight=z]1337;File=r   :)r   r   r   r   r~   r^   r   )rK   r   r   payloadr   argss         r'   _encode_itermr     s    '
5(9(9::AA'JJGw<<D(?@D *(Y(())) +)i))***;SXXd^^;;g;;;;r)   c           	     $   ddl m} | }|                    d                              d|j                  }|                                pg }|                                |                    d                                          }|j        \  }dd|fz  g}t          fd	t          |          D                       }|D ]}	|	d
z  t          |          k     r||	d
z           nd}
|	d
z  dz   t          |          k     r||	d
z  dz            nd}|	d
z  dz   t          |          k     r||	d
z  dz            nd}|                    d|	|
dz  dz  |dz  dz  |dz  dz  fz             t          d|d          D ]}|D ]}d|z  gddfd}t                    D ]r}d}t          d          D ]1}||z   }||k     r$|||f         dk    r||f         |k    r|d|z  z  }2t          d|z             }|k    rdz  c |             |dcs |             |                    d                              dz              |                    d           |                    d           d                    |          S )u  Encode one frame as DEC sixel.

    Quantizes to an adaptive palette (≤255 colors) and emits the sixel band
    stream.  Pillow has no sixel writer, so this is a compact hand-rolled
    encoder.  Transparent pixels render as background (color register skipped).
    r   r;   RGB   )colorsmethodrF   zP0;1;0qz
"1;1;%d;%dc                H    h | ]}t                    D ]}||f         S rW   )r[   )rs   yxpxr   s      r'   	<setcomp>z _encode_sixel.<locals>.<setcomp>  s4    @@@uQxx@@!2ad8@@@@r)      rG      z#%d;2;%d;%d;%dd      z#%dNc                     d S dk    r                      dfz             n                      z             d\  d S )Nr   z!%d%s)Nr   )r^   )linerun_charrun_lens   r'   flushz_encode_sixel.<locals>.flush  s[    #FQ;;KK7H*= =>>>>KK7 2333$+!'''r)       ?   r   $-r   )r>   r<   r@   quantize	MEDIANCUT
getpaletteloadrH   r   sortedr[   r~   r^   r   r   )rK   r<   rgbapalpalettealphar   r   usedr   r   gr   band	color_idxr   r   bitsbitr   chr   r   r   r   r   s                        @@@@@r'   _encode_sixelr     s    D
,,u


&
&c%/
&
J
JCnn$"G	BOOC  %%''E8DAq,!Q/
0C@@@@@U1XX@@@AAD ] ] #a#g,, 6 6GC!GA$'!GaK#g,,$>$>GC!GaK  A$'!GaK#g,,$>$>GC!GaK  A

#sAGsNAGsNAPSGWZN&[[\\\\ aA   	, 	,II%&DHG, , , , , , , 1XX . . 88 ) )Cs
A1uuq!tr!1!1bAh)6K6KS(d^^>>qLGGEGGG(*A%HggEGGGJJrwwt}}s*++++

3JJx773<<r)   u   ▀target_colslist[list[Cell]]c          	     J   ddl m} t          d|          }| j        t          d| j                  z  }t          dt          t          ||z  dz                      dz            }|                     ||f|j                  	                    d          }|
                                }g }t          d|d          D ]d}g }	t          |          D ];}
||
|f         }|dz   |k     r||
|dz   f         nd}|	                    ||f           <|                    |	           e|S )	u>  Downscale a frame to a grid of half-block cells.

    Each cell pairs a top and bottom pixel so one terminal row encodes two
    pixel rows.  Returns rows of ``((tr,tg,tb,ta),(br,bg,bb,ba))`` — the
    framework-neutral representation shared by the ANSI encoder (CLI) and the
    structured ``cells`` API (Ink).
    r   r;      rG   r   g      ?r=   )r   r   r   r   )r>   r<   rX   rZ   rY   rR   r   rq   rr   r@   r   r[   r^   )rK   r   r<   aspecttarget_rowssmallr   gridr   re   r   rf   r   s                r'   _downscale_cellsr    s?    a%%K\C5;///FaU;#7##=>>??!CDDKLL+{3U]CCKKFSSE	BD1k1%%  {## 	& 	&AQT(C%&U[%8%8R1q5\\lFJJV}%%%%CKr)   c               x   g }t          | |          D ]}g }|D ]`\  \  }}}}\  }	}
}}|dk     r|dk     r|                    d           1|                    d| d| d| d|	 d|
 d| dt                      a|                    d                    |          d	z              d
                    |          S )zGDownscale to truecolor ANSI half-blocks (one char = 2 vertical pixels).r   r   z[0m z[38;2;r   zm[48;2;mr   z[0m
)r  r^   _HALF_BLOCKr   )rK   r   linesre   cellstrtgtbtabrbgbbbas                r'   _encode_unicoder    s    E;??? 1 125 	] 	].RR.r2r2Bww277Z(((LL[b[[2[[[[r[[B[[[[k[[\\\\RWWU^^i/000099Ur)   c                  x    e Zd ZdZdedeeedd&dZe	d'd            Z
d(dZd)dZddd*dZd+d!Zd,d$Zd-d%ZdS ).PetRendereru   Holds a pet's spritesheet and yields encoded frames per (state, index).

    Construct once per pet, then call :meth:`frame` on an animation timer.
    Cheap to call repeatedly — decoded frames are cached.
    r      )r7   scaleunicode_colsrQ   rS   rT   spritesheetry   r7   r   r  floatr  rR   rQ   rS   rT   r   Nonec                   t          |          | _        |t          v r|nd| _        || _        || _        || _        || _        || _        d S )Nr   )	r   r  r1   r7   r  r  rQ   rS   rT   )selfr  r7   r  r  rQ   rS   rT   s           r'   __init__zPetRenderer.__init__*  sT     {++ L00DDi	
( 0r)   rD   c                d    | j         dk    o%t          | j                                                  S )Nr   )r7   r   r  is_file)r  s    r'   	availablezPetRenderer.available=  s+    yE!Fd4+;&<&<&D&D&F&FFr)   r   PetState | strc                F    t          |                     |                    S )N)r~   _frames)r  r   s     r'   frame_countzPetRenderer.frame_countA  s    4<<&&'''r)   c           	     R   t          |t                    r|j        nt          |          }t	          dt          | j        | j        z                      }t	          dt          | j        | j        z                      }t          | j
        || j        | j        | j        ||          S )NrG   )
isinstancer
   r}   r   rX   rR   rQ   r  rS   rx   r  rT   )r  r   r}   rl   rm   s        r'   r&  zPetRenderer._framesD  s    )%::JE

aT\DJ67788aT\DJ67788LL!
 
 	
r)   N)rc   indexrc   r   r   c                   |                      |          }|sg S ||t          |          z           }t          ||p| j                  S )zReturn one frame as a half-block cell grid (framework-neutral).

        Used by the TUI, which renders the grid with native Ink color props
        instead of raw ANSI.  Returns ``[]`` when no frame is available.
        r  )r&  r~   r  r  )r  r   r*  rc   rg   rK   s         r'   r  zPetRenderer.cellsR  sR     e$$ 	Ius6{{*+43L4;LMMMMr)   tuple[int, int]c                b    t          d|j        dz            t          d|j        dz            fS )u/  Terminal cell box for a scaled frame (~8×16 px per cell).

        Must match :meth:`frame` graphics sizing — kitty stretches the image to
        fill ``c``×``r`` cells, so these must reflect the scaled pixel
        dimensions, not a native-aspect column count (that upscales small pets).
        rG   rC   rM   )rX   rY   rZ   )r  rK   s     r'   	_cell_boxzPetRenderer._cell_box^  s1     1ekQ&''Q0B)C)CCCr)   r   dict | Nonec                   |                      |          }|sdS t          |          }t          |          }|                     |d                   \  t	                    fd|D             dS )u  Build the kitty Unicode-placeholder payload for one state.

        Returns ``{cols, rows, placeholder, frames}`` where ``frames`` is a
        list of transmit escapes (one per animation frame, all reusing
        ``image_id``) and ``placeholder`` is the static text grid Ink paints.
        Placement geometry is derived from the scaled frame pixels (via
        :meth:`_cell_box`), not ``unicode_cols`` — kitty upscales to fill
        ``c``×``r`` cells. ``None`` when no frame is available.
        Nr   c                6    g | ]}t          |           S ))r   rc   rd   )r   )rs   rt   rc   r   rd   s     r'   ru   z-PetRenderer.kitty_payload.<locals>.<listcomp>{  s8       VW%a(DQQQ  r)   )rc   rd   placeholderrg   )r&  r   r   r.  r   )r  r   r   rg   rc   rd   s     ` @@r'   kitty_payloadzPetRenderer.kitty_payloadg  s     e$$ 	4,V44*622^^F1I..
d1$==     [a  	
 
 	
r)   c                   | j         dk    rdS |                     |          }|sdS ||t          |          z           }|                     |          \  }}	 | j         dk    rt	          |||          S | j         dk    rt          |||          S | j         dk    rt          |          S t          || j                  S # t          $ r,}t                              d| j         |           Y d	}~dS d	}~ww xY w)
zReturn the encoded escape string for one frame, or ``""``.

        ``index`` is taken modulo the available frame count so callers can pass
        a free-running counter.
        r   r   r   r   r   r   r  z%pet frame encode failed (mode=%s): %sN)r7   r&  r~   r.  r   r   r   r  r  r_   r`   ra   )r  r   r*  rg   rK   r   r   rj   s           r'   rK   zPetRenderer.frame  s    92e$$ 	2us6{{*+#~~e44	9
	yG##$Ui9UUUUyG##$Ui9UUUUyG##$U+++"5d6GHHHH 	 	 	LL@$)SQQQ22222	s*   C 5C C ,C 
C8!C33C8)r  ry   r7   r   r  r  r  rR   rQ   rR   rS   rR   rT   rR   r   r  r   rD   )r   r$  r   rR   )r   r$  )r   r$  r*  rR   rc   r   r   r   )r   r,  )r   r$  r   rR   r   r/  )r   r$  r*  rR   r   r   )__name__
__module____qualname____doc__r   r   r   r	   r   propertyr#  r'  r&  r  r.  r3  rK   rW   r)   r'   r  r  #  s         $ 01 1 1 1 1 1& G G G XG( ( ( (
 
 
 
 NR 
N 
N 
N 
N 
N 
ND D D D
 
 
 
2     r)   r  r  )configured_moder  r  r+   r  r;  r  r  r  c               J    t          ||          }t          | |||          S )zFConvenience factory: resolve the mode from config+env, then construct.r*   )r7   r  r  )r8   r  )r  r;  r  r  r+   r7   s         r'   build_rendererr=    s9     777D!	   r)   )r   r   )r,   r-   r   r   )r9   r   r5  )rO   r   rP   r   rQ   rR   rS   rR   rT   rR   r   rU   )rO   r   rP   r   rQ   rR   rS   rR   rT   rR   rl   rR   rm   rR   )
rO   ry   rQ   rR   rS   rR   rT   rR   r   rz   )r   r   )r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   rR   )r   rR   r   r   )rc   rR   rd   rR   r   r   )r   rR   rc   rR   rd   rR   r   r   )r   rR   r   r   )r   rR   r   r   )
r  ry   r;  r-   r  r  r  rR   r   r  )8r9  
__future__r   r   r   loggingr!   r2   	functoolsr   pathlibr   agent.pet.constantsr   r   r   r	   r
   r   	getLoggerr6  r`   r1   r(   r8   rB   rJ   rL   rk   rx   r   r   r   r   r   r   r   r   r   r   r   __annotations__r   r   r   r   r   r   r
  rU   rR   Cellr  r  r  r=  rW   r)   r'   <module>rF     s    $ # " " " " "  				  				 



                            
	8	$	$ E* * * *Z 48      :    A A A A
 2" " " "J 1F F F F2 ,     2   & & & &(
* 
* 
*& 
= = =&
 
 
 
 59RV Z Z Z Z Z Z6 " 
'     D
; 
; 
; 
;+ + + +
   "
Z 
Z 
Z 
Z 59RV 	< 	< 	< 	< 	< 	<; ; ; ;|  U3S#%&c3S.@(AAB   6   $u u u u u u u uv #'        r)   