
    )j;                       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mZm	Z	 ddl
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZ erdd
lmZ  ej        e          ZdZdLdZdMdZdNdZdOdZdOdZddiZ h dZ!dPdZ"dQd Z#dRd"Z$dSd$Z%dTd)Z&	 dUdVd+Z'dWd,Z(d-Z)dXd0Z*d1Z+dYd5Z,d6d7hZ-d6d7d7d8Z.dPd9Z/d:d:d:d:d;d:d<d<d:d;d=Z0dZdAZ1e G dB dC                      Z2 e            Z3dDe4dE<   d[d\dIZ5d]dKZ6dS )^a  Honcho client initialization and configuration.

Resolution order for config file:
  1. $HERMES_HOME/honcho.json  (instance-local, enables isolated Hermes instances)
  2. ~/.honcho/config.json     (global, shared across all Honcho-enabled apps)
  3. Environment variables     (HONCHO_API_KEY, HONCHO_ENVIRONMENT)

Resolution order for host-specific settings:
  1. Explicit host block fields (always win)
  2. Flat/global fields from config root
  3. Defaults (host name as workspace/peer)
    )annotationsN)	dataclassfield)Path)get_hermes_home)_get_default_hermes_home)SingletonSlot)AnyTYPE_CHECKINGHonchohermesprofile
str | Nonereturnstrc                    | r| dv rt           S d                    d | D                                           d          }t            d|pd S )z5Return the safe Honcho host key for a Hermes profile.>   customdefault c              3  N   K   | ] }|                                 s|d v r|ndV  !dS )z_-_N)isalnum).0cs     A/home/ubuntu/.hermes/hermes-agent/plugins/memory/honcho/client.py	<genexpr>z#profile_host_key.<locals>.<genexpr>(   s;      PP1QYY[[>AII3PPPPPP    r   r   )HOSTjoinstrip)r   	sanitizeds     r   profile_host_keyr#   $   sb     g!666PPPPPPPVVWZ[[I--Y+)---r   rawdicthostc                   |                      d          pi }|                     |i           }|s|                    t           d          s|S t           d|t          t                    dz   d          }|                     |i           S )z@Return host config, accepting legacy dot-form profile host keys.hostsr   .   N)get
startswithr   len)r$   r&   r(   blocklegacys        r   _host_blockr0   ,   s    GGG"EIIdBE DOOtJJJ// --tCIIMNN+--F99VR   r   c                     t           j                            dd                                          } | r| S 	 ddlm}  |            }t          |          S # t          $ r Y nw xY wt          S )a	  Derive the Honcho host key from the active Hermes profile.

    Resolution order:
      1. HERMES_HONCHO_HOST env var (explicit override)
      2. Active profile name via profiles system -> ``hermes.<profile>``
      3. Fallback: ``"hermes"`` (default profile)
    HERMES_HONCHO_HOSTr   r   )get_active_profile_name)	osenvironr+   r!   hermes_cli.profilesr3   r#   	Exceptionr   )explicitr3   r   s      r   resolve_active_hostr9   6   s     z~~2B77==??H ??????))++(((   Ks   A 
A$#A$r   c                 4    t          j                    dz  dz  S )z:Return the shared Honcho config path for the current HOME.z.honchozconfig.json)r   home r   r   resolve_global_config_pathr=   K   s    9;;"]22r   c                     t                      dz  } |                                 r| S t                      dz  }|| k    r|                                r|S t                      S )uo  Return the active Honcho config path.

    Resolution order:
      1. $HERMES_HOME/honcho.json      (profile-local, if it exists)
      2. ~/.hermes/honcho.json          (default profile — shared host blocks live here)
      3. ~/.honcho/config.json          (global, cross-app interop)

    Returns the global path if none exist (for first-time setup writes).
    zhoncho.json)r   existsr   r=   )
local_pathdefault_paths     r   resolve_config_pathrB   P   sn     !""]2J  ,--=Lz!!l&9&9&;&;!%'''r   autohybrid>   toolsrD   contextvalc                R    t                               | |           } | t          v r| ndS )u?   Normalize legacy recall mode values (e.g. 'auto' → 'hybrid').rD   )_RECALL_MODE_ALIASESr+   _VALID_RECALL_MODESrG   s    r   _normalize_recall_moderL   j   s,    

"
"3
,
,C,,,33(:r   r   boolc                6    |D ]}|t          |          c S | S )aE  Resolve a bool config field: first non-None wins, else default.

    Variadic to support aliased keys (e.g. ``pinUserPeer`` shadowing
    ``pinPeerName`` for backwards compatibility).  Pass values in
    precedence order: caller's preferred alias first, then fallback
    aliases, in (host, root) interleaving as needed.
    )rM   )r   valsrG   s      r   _resolve_boolrP   p   s4       ?99 Nr   
int | Nonec                j    | |fD ]-}|)	 t          |          c S # t          t          f$ r Y )w xY w.dS )z@Parse contextTokens: host wins, then root, then None (uncapped).Nint
ValueError	TypeErrorhost_valroot_valrG   s      r   _parse_context_tokensrZ   ~   s`    (#  ?3xx	*    
 4   //rT   c                j    | |fD ]-}|)	 t          |          c S # t          t          f$ r Y )w xY w.|S )z<Parse an integer config: host wins, then root, then default.rS   )rX   rY   r   rG   s       r   _parse_int_configr]      s`    (#  ?3xx	*    
 Nr[   host_objroot_objkeydict[str, str]c                L   || v r| |         n|                     |          }t          |t                    si S i }|                                D ]T\  }}t	          |                                          }|!t	          |                                          nd}|r|r|||<   U|S )z@Parse a string-to-string map with host-level whole-map override.Nr   )r+   
isinstancer%   itemsr   r!   )	r^   r_   r`   sourceresultraw_key	raw_value	alias_keyalias_values	            r   _parse_string_maprk      s    !XooXc]]8<<3D3DFfd## 	F$llnn , ,LL&&((	090Ec)nn**,,,2 	, 	, +F9Mr   r   c                    || v r|                      |          }n|                     ||          }||S t          |                                          S )zEParse a string field where host-level empty string can override root.)r+   r   r!   )r^   r_   r`   r   values        r   _parse_optional_stringrn      sU     hS!!S'**}u::r   c           	         | |fD ]I}|E	 t          dt          t          |          d                    c S # t          t          f$ r Y Ew xY wJdS )zCParse dialecticDepth: host wins, then root, then 1. Clamped to 1-3.Nr*      )maxminrT   rU   rV   rW   s      r   _parse_dialectic_depthrs      sw    (#  ?1c#c((A../////	*    
 1s   *7A
A)minimallowmediumhighrq   depthlist[str] | Nonec                    | |fD ]l}|ht          |t                    rSd |d|         D             }t          |          |k     r(|                    d           t          |          |k     (|c S mdS )zParse dialecticDepthLevels: optional array of reasoning levels per pass.

    Returns None when not configured (use proportional defaults).
    When configured, validates each level and truncates/pads to match depth.
    Nc                (    g | ]}|t           v r|nd S )ru   )_VALID_REASONING_LEVELS)r   lvls     r   
<listcomp>z1_parse_dialectic_depth_levels.<locals>.<listcomp>   s7        5555  r   ru   )rc   listr-   append)rX   rY   rx   rG   levelss        r   _parse_dialectic_depth_levelsr      s     (# 	 	?z#t44? vv;  F
 f++%%e$$$ f++%%MMM4r   g      >@valuesr
   float | Nonec                     | D ]c}|t          |t                    r|                                }|s1	 t          |          }n# t          t
          f$ r Y Uw xY w|dk    r|c S ddS )z=Return the first non-empty value coerced to a positive float.Nr   )rc   r   r!   floatrV   rU   )r   rm   parseds      r   _resolve_optional_floatr      s      =eS!! 	KKMME 	5\\FF:& 	 	 	H	A::MMM 4s   AAAunifieddirectional)sharedseparatecrossc                R    t                               | |           } | t          v r| ndS )z"Normalize observation mode values.r   )_OBSERVATION_MODE_ALIASESr+   _VALID_OBSERVATION_MODESrK   s    r   _normalize_observation_moder      s,    
#
'
'S
1
1C11133}Dr   Tuser_observe_meuser_observe_othersai_observe_meai_observe_othersF)r   r   modeobservation_objdict | Nonec                   t                               | t           d                   }|rt          |t                    st          |          S |                    d          pi }|                    d          pi }|                    d|d                   |                    d|d                   |                    d|d                   |                    d|d	                   d
S )aj  Resolve per-peer observation booleans.

    Config forms:
      String shorthand:  ``"observationMode": "directional"``
      Granular object:   ``"observation": {"user": {"observeMe": true, "observeOthers": true},
                                           "ai": {"observeMe": true, "observeOthers": false}}``

    Granular fields override preset defaults.
    r   userai	observeMer   observeOthersr   r   r   r   )_OBSERVATION_PRESETSr+   rc   r%   )r   r   preset
user_blockai_blocks        r   _resolve_observationr     s     "%%d,@,OPPF *_d"C"C F|| $$V,,2J""4((.BH &>>+v>O7PQQ)~~ovF[?\]]!k6/3JKK%\\/6BU;VWW	  r   c                     e Zd ZU dZeZded<   dZded<   dZded<   d	Z	ded
<   dZ
ded<   dZded<   dZded<   dZded<   dZded<    ee          Zded<   dZded<   dZded<   dZded<   dZded<   dZded<   d Zded!<   dZded"<   d#Zd$ed%<   d&Zd$ed'<   dZd(ed)<   dZded*<   d+Zded,<   d-Zd$ed.<   d/Zd$ed0<   d1Z ded2<   dZ!ded3<   d4Z"ded5<   dZ#ded6<   dZ$ded7<   dZ%ded8<   dZ&ded9<   d:Z'ded;<   dZ(ded<<    ee          Z)ded=<    ee          Z*d>ed?<   dZ+ded@<   e,	 	 dQdRdB            Z-e,	 	 dSdTdE            Z.e/dUdG            Z0dHZ1dIZ2e,dVdL            Z3	 	 	 	 dWdXdPZ4dS )YHonchoClientConfigz>Configuration for Honcho client, resolved for a specific host.r   r&   r   workspace_idNr   api_key
productionenvironmentbase_urlr   timeout	peer_nameai_peerFrM   pin_peer_name)default_factoryra   user_peer_aliasesr   runtime_peer_prefixenabledTsave_messagesasyncz	str | intwrite_frequencyrQ   context_tokensru   dialectic_reasoning_leveldialectic_dynamicX  rT   dialectic_max_charsr*   dialectic_depthry   dialectic_depth_levelsreasoning_heuristicrw   reasoning_level_capa  message_max_chars'  dialectic_max_input_charsrD   recall_modeinit_on_session_startr   observation_moder   r   r   r   per-directorysession_strategysession_peer_prefixsessionszdict[str, Any]r$   explicitly_configuredr   c                   |pt                      }t          j                            d          }t          j                            dd                                          pd}t          t          j                            d                    } | |||t          j                            dd          |||t          |p|                    S )	z4Create config from environment variables (fallback).HONCHO_API_KEYHONCHO_BASE_URLr   NHONCHO_TIMEOUTHONCHO_ENVIRONMENTr   )r&   r   r   r   r   r   r   r   )r9   r4   r5   r+   r!   r   rM   )clsr   r&   resolved_hostr   r   r   s          r   from_envzHonchoClientConfig.from_env~  s     5 3 5 5*..!122:>>"3R88>>@@HD)"*..9I*J*JKKs%
';\JJ!,H--	
 	
 	
 		
r   config_pathPath | Nonec                `   |pt                      }|pt                      }|                                s1t                              d|           |                     |          S 	 t          j        |                    d                    }nU# t          j	        t          f$ r<}t                              d||           |                     |          cY d}~S d}~ww xY wt          ||          }t          |          p|                    d          du }|                    d	          p|                    d	          p|}	|                    d
          p|                    d
          p|}
|                    d          p3|                    d          pt          j                            d          }|                    d          p|                    dd          }|                    d          pH|                    d          p3t          j                            dd                                          pd}t%          |                    d          |                    d          t          j                            d                    }|                    d          }|                    d          }||}n||}nt          |p|          }|                    d          p|                    d          pd}	 t'          |          }n&# t(          t*          f$ r t-          |          }Y nw xY w|                    d          }||n|                    dd          }|                    d          p|                    dd          }|                    d          }||n|                    dd          } | dSi d|d|	d|d|d|d|d |                    d!          p|                    d!          d"|
d#t/          |                    d$          |                    d%          |                    d$          |                    d%          d&          d't1          ||d(          d)t3          ||d*          d|d+|d,|d-t5          |                    d.          |                    d.                    d/|                    d0          p|                    d0          pd1d2t/          |                    d3          |                    d3          d&          d4t7          |                    d5          |                    d5          d6&          d7t9          |                    d8          |                    d8                    d9t;          |                    d:          |                    d:          t9          |                    d8          |                    d8                    ;          d<t/          |                    d=          |                    d=          d&          d>|                    d?          p|                    d?          pd@dAt7          |                    dB          |                    dB          dC&          dDt7          |                    dE          |                    dE          dF&          dGt=          |                    dH          p|                    dH          pdI          dJt/          |                    dK          |                    dK          d&          dLt?          |                    dM          p|                    dM          p|rdNndO          tA          t?          |                    dM          p|                    dM          p|rdNndO          |                    dP          p|                    dP                    |||                    dQi           ||dRS )TzCreate config from the resolved Honcho config path.

        Resolution: $HERMES_HOME/honcho.json -> ~/.honcho/config.json -> env vars.
        When host is None, derives it from the active Hermes profile.
        z2No global Honcho config at %s, falling back to env)r&   utf-8)encodingz*Failed to read %s: %s, falling back to envNr   T	workspaceaiPeerapiKeyr   r   r   baseUrlr   r   r   r   requestTimeoutr   writeFrequencyr   saveMessagessessionStrategyr   sessionPeerPrefixFr&   r   r   r   peerNamer   r   pinUserPeerpinPeerName)r   r   userPeerAliasesr   runtimePeerPrefixr   r   r   contextTokensr   dialecticReasoningLevelru   r   dialecticDynamicr   dialecticMaxCharsr   r   dialecticDepthr   dialecticDepthLevels)rx   r   reasoningHeuristicr   reasoningLevelCaprw   r   messageMaxCharsr   r   dialecticMaxInputCharsr   r   
recallModerD   r   initOnSessionStartr   observationModer   r   observationr   )r   r   r   r$   r   r<   )!r9   rB   r?   loggerdebugr   jsonloads	read_textJSONDecodeErrorOSErrorwarningr0   rM   r+   r4   r5   r!   r   rT   rV   rU   r   rP   rk   rn   rZ   r]   rs   r   rL   r   r   )r   r&   r   r   pathr$   e
host_block_explicitly_configuredr   r   r   r   r   r   host_enabledroot_enabledr   raw_wfr   	host_saver   r   host_prefixr   s                            r   from_global_configz%HonchoClientConfig.from_global_config  s	    5 3 5 53133{{}} 	4LLMtTTT<<]<333	4*T^^W^==>>CC$g. 	4 	4 	4NNGqQQQ<<]<33333333	4 !m44
 "&j!1!1!OSWWY5G5G45O NN;'' ww{## 	 NN8$$ wwx   	 NN8$$ 0wwx  0z~~.// 	 NN=)) 4ww}l33 	 GGI wwz""z~~/44::<< 	 	 *GGIGG$%%JNN+,,
 
 "~~i00wwy))#"GG%"GG 7.h//G NN+,, ww'(( 	
	*),VOO:& 	* 	* 	*!&kkOOO	* NN>22	%.%:		X\@]@] NN,-- ;ww(/:: 	 !nn%899&2KK,e44 	
 s t
 t
 t
t
"t
 Gt
 $	t

 Xt
 Gt
 !nnZ00GCGGJ4G4Gt
 Gt
 ( }--}--&&&&   t
, 0!  -t
6 !7#! ! !7t
@ GAt
B (-Ct
D ,OEt
F 1//((  Gt
P 899 77455Ut
X ,122*++   Yt
b !2233+,,! ! ! !ct
l 3/00())  mt
t $A566.//,Z^^<L-M-MswwWgOhOhii$ $ $ $ut
~ !.344,--! ! ! !t
J 233 77.//Ot
R 0011)**   St
\ '8788011' ' ' ']t
f /|,, 77<((  gt
p #0344,--# # # #qt
D 9011 L77,--L!7JII]  
 #+NN#455 Pww011P%;N		 
 }--G1G1G Ot
^ . 3WWZ,,"8gt
 t
 t
 t
 t	
s0   '(B C"&1CC"C"L  L>=L>cwdc                    ddl }	 |                    g ddd| d|j                  }|j        dk    r+t	          |j                                                  j        S n# t          |j	        f$ r Y nw xY wdS )zBReturn the git repo root directory name, or None if not in a repo.r   N)gitz	rev-parsez--show-toplevelT   )capture_outputtextr  r   stdin)

subprocessrunDEVNULL
returncoder   stdoutr!   namer   TimeoutExpired)r  r  roots      r   _git_repo_namez!HonchoClientConfig._git_repo_namen  s     			>>777#$C ( "  D
 !##DK--//0055 $23 	 	 	D	ts   AA A32A3d      r"   originalc                "   | j         }t          |          |k    r|S | j        }t          j        |                    d                                                    d|         }||z
  dz
  }|d|                             d          }| d| S )a]  Truncate a sanitized session ID to Honcho's 100-char limit.

        The common case (short keys) short-circuits with no modification.
        For over-limit keys, keep a prefix of the sanitized ID and append a
        deterministic ``-<sha256 prefix>`` suffix so two distinct long keys
        that share a leading segment don't collide onto the same truncated ID.
        The hash is taken over the *original* pre-sanitization key, so two
        inputs that sanitize to the same string still collide intentionally
        (same logical session), but two inputs that only share a prefix do not.
        r   Nr*   -)_HONCHO_SESSION_ID_MAX_LENr-   _HONCHO_SESSION_ID_HASH_LENhashlibsha256encode	hexdigestrstrip)r   r"   r  max_lenhash_lendigest
prefix_lenprefixs           r   _enforce_session_id_limitz,HonchoClientConfig._enforce_session_id_limit  s     0y>>W$$2 8 899CCEEixiP x'!+
;J;'..s33##6###r   session_title
session_idgateway_session_keyc                   ddl }|st          j                    }| j                            |          }|r|S |rH|                    dd|                              d          }|r| j        r| j        r| j         d| S |S |rB|                    dd|                              d          }|r| 	                    ||          S | j
        dk    r|r| j        r| j        r| j         d| S |S | j
        dk    rE|                     |          pt          |          j        }| j        r| j        r| j         d| S |S | j
        dv r0t          |          j        }| j        r| j        r| j         d| S |S | j        S )u  Resolve Honcho session name.

        Resolution order:
          1. Manual directory override from sessions map
          2. Hermes session title (from /title command)
          3. Gateway session key (stable per-chat identifier from gateway platforms)
          4. per-session strategy — Hermes session_id ({timestamp}_{hex})
          5. per-repo strategy — git repo root directory name
          6. per-directory strategy — directory basename
          7. global strategy — workspace name
        r   Nz[^a-zA-Z0-9_-]+r  per-sessionzper-repo>   r,  r   )rer4   getcwdr   r+   subr!   r   r   r'  r   r  r   r  r   )	selfr  r(  r)  r*  r-  manualr"   bases	            r   resolve_session_namez'HonchoClientConfig.resolve_session_name  s   $ 				 	)++C ""3'' 	M  	!13FFLLSQQI !+ ; ;"n::y:::    	V138KLLRRSVWWI V55iATUUU  M11j1' 8DN 8.77:777  J..&&s++=tCyy~D' 2DN 2.114111K  $DDD99>D' 2DN 2.114111K   r   )r   N)r   r   r&   r   r   r   )NN)r&   r   r   r   r   r   )r  r   r   r   )r"   r   r  r   r   r   )NNNN)
r  r   r(  r   r)  r   r*  r   r   r   )5__name__
__module____qualname____doc__r   r&   __annotations__r   r   r   r   r   r   r   r   r   r%   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r$   r   classmethodr   r  staticmethodr  r  r  r'  r3  r<   r   r   r   r   #  s        HHD L    G#K####H G     I    G  M ).d(C(C(CCCCC!!!!!GM ")O((((!%N%%%% &+**** #""""""""" O 043333 !%$$$$%%%%% #""""%*****
  K #('''' *)))) !O     $$$$$M"""""+++++ %%%%%$uT:::H::::%555C5555 #('''' %
 
 
 
 [
*   #'W
 W
 W
 W
 [W
r    \* "%"#$ $ $ [$4 $(!%*.C! C! C! C! C! C! C!r   r   r	   _honcho_client_slotconfigHonchoClientConfig | Noner   c                     t                                           }||S  t                                            j        s j        st          d          d fd}t                               |          S )a  Get or create the Honcho client singleton.

    When no config is provided, attempts to load ~/.honcho/config.json
    first, falling back to environment variables.

    Thread-safe: the client is built exactly once even under concurrent
    first calls (double-checked locking via ``SingletonSlot``), so racing
    threads can't each construct a client and leak the loser's connection.
    NzHoncho API key not found. Get your API key at https://app.honcho.dev, then run 'hermes honcho setup' or set HONCHO_API_KEY. For local instances, set HONCHO_BASE_URL instead.r   'Honcho'c                    	 ddl m} m}  |dd           n# t          $ r Y nt          $ r Y nw xY w	 ddlm} n# t          $ r t          d          w xY wj        }j        }|r|	 ddl	m
}  |            }|                    d	i           }t          |t                    rd|s*|                    d
d                                          pd }|6t          |                    d          |                    d                    }n# t          $ r Y nw xY w|t           }|r"t"                              d|j                   n&t"                              dj        j                   |od|v pd|v pd|v }|rgj        pi }	|	                    d          pi                     j        i           }
t-          |
                    d                    }|rj        nd}nj        }|r.dd l}|                    dd|                              d          }j        |j        d}|r||d
<   |||d<    |di |S )Nr   )FeatureUnavailableensurezmemory.honchoF)promptr   zhoncho-ai is required for Honcho integration. Install it with: pip install honcho-ai  (or run `hermes honcho setup` to configure).)load_confighonchor   r   r   request_timeoutz8Initializing Honcho client (base_url: %s, workspace: %s)z4Initializing Honcho client (host: %s, workspace: %s)	localhostz	127.0.0.1z::1r(   r   localz/v\d+/*$/)r   r   r   r<   )tools.lazy_depsrA  rB  ImportErrorr7   rE  r   r   r   hermes_cli.configrD  r+   rc   r%   r!   r   _DEFAULT_HTTP_TIMEOUTr   infor   r&   r$   rM   r   r-  r/  r!  r   )rA  _lazy_ensurer   resolved_base_urlresolved_timeoutrD  
hermes_cfg
honcho_cfg	_is_local_rawr0   _host_has_keyeffective_api_key_rekwargsr<  s                  r   _buildz!get_honcho_client.<locals>._build  s=   
		RRRRRRRRL77777 	 	 	D 	 	 	 D	
	%%%%%%% 	 	 	?  	 #O!>  	$4$<999999([]]
'^^Hb99
j$// , [,6NN:r,J,J,P,P,R,R,ZVZ)'/+B&NN955&NN+<==, ,(    
 #4 	rKKRTegmgz{{{{KKNPVP[]c]pqqq & 
,, *//*)) 	
  
	/
 :#D88G,,277RHHK !:!:;;M2? LW &  	X #R9J K K R RSV W W #/(!-
 

  	3!2F:' 0F9vs,    
1	11< A,BD 
DD)r   r?  )r;  peekr   r  r   r   rU   r+   )r<  cachedrZ  s   `  r   get_honcho_clientr]    s     !%%''F~#6688> 
&/ 
@
 
 	
d  d  d  d  d  d L ""6***r   Nonec                 8    t                                            dS )z7Reset the Honcho client singleton (useful for testing).N)r;  resetr<   r   r   reset_honcho_clientra  p  s    r   )r   r   r   r   )r$   r%   r&   r   r   r%   )r   r   )r   r   )rG   r   r   r   )r   rM   r   rM   )r   rQ   )r   rT   r   rT   )r^   r%   r_   r%   r`   r   r   ra   )r   )
r^   r%   r_   r%   r`   r   r   r   r   r   )r   rT   )rx   rT   r   ry   )r   r
   r   r   )r   r   r   r   r   r%   )N)r<  r=  r   r   )r   r^  )7r7  
__future__r   r   r4   loggingr  dataclassesr   r   pathlibr   hermes_constantsr   r6   r   plugins.plugin_utilsr	   typingr
   r   rE  r   	getLoggerr4  r   r   r#   r0   r9   r=   rB   rI   rJ   rL   rP   rZ   r]   rk   rn   rs   r|   r   rM  r   r   r   r   r   r   r   r;  r8  r]  ra  r<   r   r   <module>rj     sY     # " " " " "  				   ( ( ( ( ( ( ( (       , , , , , , 8 8 8 8 8 8 . . . . . . % % % % % % % % 		8	$	$. . . .! ! ! !   *3 3 3 3
( ( ( (, ) 444 ; ; ; ;              >@
 
 
 
 
    F    2     $ &}5 '0mVcdd E E E E  D 
  T 	 	    > ! ! ! ! ! ! ! !D &3]__  4 4 4 4D+ D+ D+ D+ D+N           r   