+
    iD                       R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	]	P                  ! ]4      t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIt^ RIHtHtHtHt ^ RIHt ^ RIt^ RI H t  ^ RI!H"t" ^ RI#H$t$ ^ RI%H&t& ]$! 4       t']"! ](4      PR                  R	,          t*]&! ]']*R
7      t+]+'       d   ]+ F  t,]P[                  R],4       K  	  M]P[                  R4       ^ RI.H/t/H0t0H1t1H2t2 ^ RI3H4t4 ^ RI5H6t7 ^ RI8H9t9 ^ RI#H:t: ^ RI;H<t< ^ RI=H>t>H?t?H@t@HAtAHBtBHCtC ^ RIDHEtEHFtFHGtGHHtHHItIHJtJHKtKHLtL ^ RIMHNtN ^ RIOHPtP ^ RIQHRtR ^ RI=HStSHTtTHUtUHVtVHWtWHXtXHYtYHZtZ ^ RI[H\t\H]t] ^ RI^H_t_H`taHbtcHdtdHetf ^ RIgHhthHitiHjtk ^ RIlHmtmHntn  ! R R4      toR R  ltp ! R! R"4      tq]r! R#04      ts]r! 0 R?m4      tt]r! 0 R@m4      tu^tv]P                  ! R$]P                  4      ty]P                  ! R%4      tzR& R' lt{R( R) lt|R* R+ lt}R, R- lt~]P                  ! R.4      t]P                  ! R/]EP                   4      tR0 R1 ltR2 R3 ltR4 R5 ltR6tR7tR8 R9 lt ! R: R;4      tRAR< R= llt]R>8X  d   ]EP                  ! ]4       R# R# )Bao  
AI Agent Runner with Tool Calling

This module provides a clean, standalone agent that can execute AI models
with tool calling capabilities. It handles the conversation loop, tool execution,
and response management.

Features:
- Automatic tool calling loop until completion
- Configurable model parameters
- Error handling and recovery
- Message history management
- Support for multiple model providers

Usage:
    from run_agent import AIAgent
    
    agent = AIAgent(base_url="http://localhost:30000/v1", model="claude-opus-4-20250514")
    response = agent.run_conversation("Tell me about the latest Python updates")
N)SimpleNamespace)ListDictAnyOptional)OpenAI)datetime)Pathget_hermes_home)load_hermes_dotenvz.env)hermes_homeproject_envz$Loaded environment variables from %sz7No .env file found. Using system environment variables.)get_tool_definitionsget_toolset_for_toolhandle_function_callcheck_toolset_requirements)
cleanup_vm)set_interrupt)cleanup_browser)OPENROUTER_BASE_URL)build_memory_context_block)DEFAULT_AGENT_IDENTITYPLATFORM_HINTSMEMORY_GUIDANCESESSION_SEARCH_GUIDANCESKILLS_GUIDANCEbuild_nous_subscription_prompt)fetch_model_metadataestimate_tokens_roughestimate_messages_tokens_roughestimate_request_tokens_roughget_next_probe_tierparse_context_limit_from_errorsave_context_lengthis_local_endpoint)ContextCompressor)SubdirectoryHintTracker)apply_anthropic_cache_control)build_skills_system_promptbuild_context_files_promptload_soul_mdTOOL_USE_ENFORCEMENT_GUIDANCETOOL_USE_ENFORCEMENT_MODELSDEVELOPER_ROLE_MODELS!GOOGLE_MODEL_OPERATIONAL_GUIDANCEOPENAI_MODEL_EXECUTION_GUIDANCE)estimate_usage_costnormalize_usage)KawaiiSpinnerbuild_tool_previewget_cute_tool_message_detect_tool_failureget_tool_emoji)convert_scratchpad_to_thinkhas_incomplete_scratchpadsave_trajectory)atomic_json_writeenv_var_enabledc                   L   a  ] tR t^nt o RtR
tR tR tR tR t	R t
R tRtV tR	# )_SafeWriteru<  Transparent stdio wrapper that catches OSError/ValueError from broken pipes.

When hermes-agent runs as a systemd service, Docker container, or headless
daemon, the stdout/stderr pipe can become unavailable (idle timeout, buffer
exhaustion, socket reset). Any print() call then raises
``OSError: [Errno 5] Input/output error``, which can crash agent setup or
run_conversation() — especially via double-fault when an except handler
also tries to print.

Additionally, when subagents run in ThreadPoolExecutor threads, the shared
stdout handle can close between thread teardown and cleanup, raising
``ValueError: I/O operation on closed file`` instead of OSError.

This wrapper delegates all writes to the underlying stream and silently
catches both OSError and ValueError. It is transparent when the wrapped
stream is healthy.
c                4    \         P                  V R V4       R# )_innerN)object__setattr__)selfinners   &&&/home/ubuntu/hermes-agent/run_agent.py__init___SafeWriter.__init__   s    451    c                     V P                   P                  V4      #   \        \        3 d)    \	        T\
        4      '       d   \        T4      u # ^ u # i ; i    )r@   writeOSError
ValueError
isinstancestrlen)rC   datas   &&rE   rL   _SafeWriter.write   sK    	=;;$$T**$ 	= *4 5 53t9<1<	=s    2AAAc                l     V P                   P                  4        R #   \        \        3 d     R # i ; iN)r@   flushrM   rN   rC   s   &rE   rV   _SafeWriter.flush   s.    	KK$ 		s    33c                6    V P                   P                  4       # rU   )r@   filenorW   s   &rE   rZ   _SafeWriter.fileno   s    {{!!##rH   c                h     V P                   P                  4       #   \        \        3 d     R # i ; i)F)r@   isattyrM   rN   rW   s   &rE   r]   _SafeWriter.isatty   s1    	;;%%''$ 		s    11c                .    \        V P                  V4      # rU   )getattrr@   )rC   names   &&rE   __getattr___SafeWriter.__getattr__   s    t{{D))rH    N)r@   )__name__
__module____qualname____firstlineno____doc__	__slots__rF   rL   rV   rZ   r]   rb   __static_attributes____classdictcell____classdict__s   @rE   r>   r>   n   s4     $ I2=$* *rH   r>   c                    V ^8  d   QhRR/#    returnNrd   )formats   "rE   __annotate__rt      s     ; ;T ;rH   c                     R FL  p \        \        V R4      pVf   K  \        V\        4      '       d   K2  \	        \        V \        V4      4       KN  	  R# )zHWrap stdout/stderr so best-effort console output cannot crash the agent.N)stdoutstderr)r`   sysrO   r>   setattr)stream_namestreams     rE   _install_safe_stdior|      s=    +k40j&E&ECk&&9: ,rH   c                      a  ] tR t^t o RtV 3R lR ltV 3R lR ltV 3R lR lt]V 3R lR	 l4       t	]V 3R
 lR l4       t
RtV tR# )IterationBudgetu9  Thread-safe iteration counter for an agent.

Each agent (parent or subagent) gets its own ``IterationBudget``.
The parent's budget is capped at ``max_iterations`` (default 90).
Each subagent gets an independent budget capped at
``delegation.max_iterations`` (default 50) — this means total
iterations across parent + subagents can exceed the parent's cap.
Users control the per-subagent limit via ``delegation.max_iterations``
in config.yaml.

``execute_code`` (programmatic tool calling) iterations are refunded via
:meth:`refund` so they don't eat into the budget.
c                    < V ^8  d   QhRS[ /# )rq   	max_totalint)rs   rn   s   "rE   rt   IterationBudget.__annotate__   s     & &# &rH   c                T    Wn         ^ V n        \        P                  ! 4       V n        R# rK   N)r   _used	threadingLock_lock)rC   r   s   &&rE   rF   IterationBudget.__init__   s    "
^^%
rH   c                    < V ^8  d   QhRS[ /# rq   rr   bool)rs   rn   s   "rE   rt   r      s       rH   c                    V P                   ;_uu_ 4        V P                  V P                  8  d    RRR4       R# V ;P                  ^,          un         RRR4       R#   + '       g   i     R# ; i)z7Try to consume one iteration.  Returns True if allowed.NFTr   r   r   rW   s   &rE   consumeIterationBudget.consume   sC    ZZZzzT^^+ Z JJ!OJ	 ZZZs   A A  A1	c                   < V ^8  d   QhRR/# rp   rd   )rs   rn   s   "rE   rt   r      s          rH   c                    V P                   ;_uu_ 4        V P                  ^ 8  d   V ;P                  ^,          un        RRR4       R#   + '       g   i     R# ; i)z6Give back one iteration (e.g. for execute_code turns).N)r   r   rW   s   &rE   refundIterationBudget.refund   s/    ZZZzzA~

a
 ZZZs   +A

A	c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r      s      c rH   c                    V P                   # rU   )r   rW   s   &rE   usedIterationBudget.used   s    zzrH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r      s     7 73 7rH   c                    V P                   ;_uu_ 4        \        ^ V P                  V P                  ,
          4      uuRRR4       #   + '       g   i     R# ; ir   )r   maxr   r   rW   s   &rE   	remainingIterationBudget.remaining   s.    ZZZq$..4::56 ZZZs   'AA	r   N)re   rf   rg   rh   ri   rF   r   r   propertyr   r   rk   rl   rm   s   @rE   r~   r~      sP     & &
       7 7rH   r~   clarifyz(?:^|\s|&&|\|\||;|`)(?:
        rm\s|rmdir\s|
        mv\s|
        sed\s+-i|
        truncate\s|
        dd\s|
        shred\s|
        git\s+(?:reset|clean|checkout)\s
    )z[^>]>[^>]|^>[^>]c                0    V ^8  d   QhR\         R\        /# )rq   cmdrr   rP   r   )rs   s   "rE   rt   rt      s        rH   c                    V '       g   R# \         P                  V 4      '       d   R# \        P                  V 4      '       d   R# R# )zJHeuristic: does this terminal command look like it modifies/deletes files?FT)_DESTRUCTIVE_PATTERNSsearch_REDIRECT_OVERWRITE)r   s   &rE   _is_destructive_commandr      s3    ##C((!!#&&rH   c                $    V ^8  d   QhR\         /# r   r   )rs   s   "rE   rt   rt     s     ) )$ )rH   c                  a \        V 4      ^8:  d   R# V  Uu. uF  qP                  P                  NK  	  pp\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   R# . pV  EF
  pVP                  P                  p \        P
                  ! VP                  P                  4      p\        T\        4      '       g/   \        P                  ! RT\        T4      P                  4        R# T\        9   di   \        YV4      oSf    R# \        ;QJ d    T3R lT 4       F  '       g   K   RM	  RM! T3R lT 4       4      '       d    R# TP!                  S4       K  T\"        9  g   EK
   R# 	  R# u upi   \         d9    \        P                  ! RTTP                  P                  R,          4         R# i ; i)z?Return True when a tool-call batch is safe to run concurrently.Fc              3   2   "   T F  q\         9   x  K  	  R # 5irU   )_NEVER_PARALLEL_TOOLS).0ra   s   & rE   	<genexpr>1_should_parallelize_tool_batch.<locals>.<genexpr>  s     
@ZT((Zs   Tu@   Could not parse args for %s — defaulting to sequential; raw=%sN   Nu6   Non-dict args for %s (%s) — defaulting to sequentialc              3   <   <"   T F  p\        SV4      x  K  	  R # 5irU   )_paths_overlap)r   existingscoped_paths   & rE   r   r   )  s     XX>+x88s   )rQ   functionra   anyjsonloads	arguments	ExceptionloggingdebugrO   dicttypere   _PATH_SCOPED_TOOLS_extract_parallel_scope_pathappend_PARALLEL_SAFE_TOOLS)
tool_callstc
tool_namesreserved_paths	tool_call	tool_namefunction_argsr   s   &      @rE   _should_parallelize_tool_batchr     si   
:!-78Zr++""ZJ8
s
@Z
@sss
@Z
@@@!#N	&&++		 JJy'9'9'C'CDM -..MMH]#,,
 **6yPK"sXXsssXXXX!!+.00;  > I 9  	MMR"",,T2
 	s   F	*F>GGc                J    V ^8  d   QhR\         R\        R\        R,          /# )rq   r   r   rr   N)rP   r   r	   )rs   s   "rE   rt   rt   4  s&     = =C = =PT =rH   c                   V \         9  d   R# VP                  R4      p\        V\        4      '       d   VP	                  4       '       g   R# \        V4      P                  4       pVP                  4       '       d2   \        \        P                  P                  \        V4      4      4      # \        \        P                  P                  \        \
        P                  ! 4       V,          4      4      4      # )z8Return the normalized file target for path-scoped tools.Npath)r   getrO   rP   stripr	   
expanduseris_absoluteosr   abspathcwd)r   r   raw_pathexpandeds   &&  rE   r   r   4  s    **  (Hh$$HNN,<,<H~((*HBGGOOCM233 DHHJ$9 :;<<rH   c                <    V ^8  d   QhR\         R\         R\        /# )rq   leftrightrr   )r	   r   )rs   s   "rE   rt   rt   E  s!     ? ? ?d ?t ?rH   c                    V P                   pVP                   pV'       d	   V'       g+   \        V4      \        V4      8H  ;'       d    \        V4      # \        \        V4      \        V4      4      pVRV VRV 8H  # )z9Return True when two paths may refer to the same subtree.N)partsr   minrQ   )r   r   
left_partsright_parts
common_lens   &&   rE   r   r   E  si    J++K[J4#44IIj9IIS_c+&67Jkz"k+:&>>>rH   z[\ud800-\udfff]z5\[BUDGET(?:\s+WARNING)?:\s+Iteration\s+\d+/\d+\..*?\]c                0    V ^8  d   QhR\         R\         /# )rq   textrr   rP   )rs   s   "rE   rt   rt   Y  s      s s rH   c                h    \         P                  V 4      '       d   \         P                  RV 4      # V # )zReplace lone surrogate code points with U+FFFD (replacement character).

Surrogates are invalid in UTF-8 and will crash ``json.dumps()`` inside the
OpenAI SDK.  This is a fast no-op when the text contains no surrogates.
   �)_SURROGATE_REr   sub)r   s   &rE   _sanitize_surrogatesr   Y  s-     D!!  400KrH   c                0    V ^8  d   QhR\         R\        /# rq   messagesrr   )listr   )rs   s   "rE   rt   rt   d  s      D T rH   c                B   RpV  EF  p\        V\        4      '       g   K  VP                  R4      p\        V\        4      '       d9   \        P                  V4      '       d   \        P                  RV4      VR&   RpK{  \        V\        4      '       g   K  V F|  p\        V\        4      '       g   K  VP                  R4      p\        V\        4      '       g   KD  \        P                  V4      '       g   Ka  \        P                  RV4      VR&   RpK~  	  EK  	  V# )zSanitize surrogate characters from all string content in a messages list.

Walks message dicts in-place.  Returns True if any surrogates were found
and replaced, False otherwise.
Fcontentr   Tr   )rO   r   r   rP   r   r   r   r   )r   foundmsgr   partr   s   &     rE   _sanitize_messages_surrogatesr   d  s     E#t$$'')$gs##(<(<W(E(E*..xAC	NE&&dD))88F+D!$,,1E1Ed1K1K'4'8'84'HV $    LrH   c                (    V ^8  d   QhR\         RR/# rq   r   rr   Nr   )rs   s   "rE   rt   rt   |  s     % %$ %4 %rH   c                ,   V  F  p\        V\        4      '       d   VP                  R4      R8w  d   K1  VP                  R4      p\        V\        4      '       d   RV9  d
   RV9  d   Kh   \        P
                  ! V4      p\        V\        4      '       d(   RV9   d!   VR \        P                  ! VRR7      VR&   K  \        P                  RT4      P                  4       pYB8w  g   K  YAR&   K  	  R	#   \        P                  \        3 d     LSi ; i)
a   Remove budget pressure warnings from tool-result messages in-place.

Budget warnings are turn-scoped signals that must not leak into replayed
history.  They live in tool-result ``content`` either as a JSON key
(``_budget_warning``) or appended plain text.
roletoolr   _budget_warningz[BUDGETFensure_ascii N)rO   r   r   rP   r   r   dumpsJSONDecodeError	TypeError_BUDGET_WARNING_REr   r   )r   r   r   parsedcleaneds   &    rE   #_strip_budget_warnings_from_historyr  |  s     #t$$6(A'')$'3''+<G+KPYahPh	ZZ(F&$'',=,G,-!%F!GI
 %((W5;;=$	N)  $$i0 		s   ,AC55DD順 i  c                <    V ^8  d   QhR\         R\         R\         /# )rq   function_namefunction_resultrr   r   )rs   s   "rE   rt   rt     s!     -
 -
s -
S -
S -
rH   c           	        \        V4      pV\        8:  d   V#  \        P                  P	                  \        4       RR4      p\        P                  ! VRR7       \        P                  ! 4       P                  R4      p\        P                  ! RRV 4      R,          pV RV R	2p\        P                  P	                  W64      p\        VR
RR7      ;_uu_ 4       pVP                  V4       RRR4       VR\         p	V	 RVR R\        R RV R2#   + '       g   i     L-; i  \         dA   p
\         P#                  RT
4       TR\         RTR R\        R RT
 R2,           u Rp
?
# Rp
?
ii ; i)u  Replace oversized tool results with a file reference + preview.

When a tool returns more than ``_LARGE_RESULT_CHARS`` characters, the full
content is written to a temporary file under ``HERMES_HOME/cache/tool_responses/``
and the result sent to the model is replaced with:
  • a brief head preview  (first ``_LARGE_RESULT_PREVIEW_CHARS`` chars)
  • the file path so the model can use ``read_file`` / ``search_files``

Falls back to destructive truncation if the file write fails.
cachetool_responsesT)exist_ok%Y%m%d_%H%M%S_%fz[^\w\-]_N(   Nz.txtwutf-8encodingNz

[Large tool response: ,u%    characters total — only the first z$ shown above. Full output saved to: z@
Use read_file or search_files on that path to access the rest.]z,Failed to save large tool result to file: %sz 

[Truncated: tool response was z chars, exceeding the z char limit. File save failed: ])rQ   _LARGE_RESULT_CHARSr   r   joinr   makedirsr   nowstrftimerer   openrL   _LARGE_RESULT_PREVIEW_CHARSr   loggerwarning)r  r  original_lenresponse_dir	timestamp	safe_namefilenamefilepathfpreviewexcs   &&         rE   _save_oversized_tool_resultr*    sp    'L**
ww||O$5w@PQ
L40LLN++,>?	FF:sM:3?	[)D177<<7(C'22aGGO$ 3 "">#>?i %%1!$4 59!< =%%-J /NO	
	 32  
EsK0012<2B C03 4!!$Q((	

s6   CD% D-$D% D"	D% %E005E+%E0+E0c            3       	  a  ] tR tRt o Rt]V 3R lR l4       t]P                  V 3R lR l4       tRRRRRRRRR^ZR	RRR
R
R
R^dR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
^2R
R33V 3R lR lltR t	RR lt
R tRR
/V 3R lR lltV 3R lR ltV 3R lR ltRV 3R lR lltV 3R lR ltV 3R lR ltV 3R lR ltV 3R  lR! ltV 3R" lR# ltV 3R$ lR% ltV 3R& lR' ltV 3R( lR) ltV 3R* lR+ ltR,tR-tR.tRV 3R/ lR0 lltV 3R1 lR2 ltRV 3R3 lR4 lltRV 3R5 lR6 lltV 3R7 lR8 lt V 3R9 lR: lt!V 3R; lR< lt"V 3R= lR> lt#]$V 3R? lR@ l4       t%V 3RA lRB lt&V 3RC lRD lt']$V 3RE lRF l4       t(V 3RG lRH lt)RIR/V 3RJ lRK llt*]$V 3RL lRM l4       t+RV 3RN lRO llt,RV 3RP lRQ llt-V 3RR lRS lt.V 3RT lRU lt/V 3RV lRW lt0RV 3RX lRY llt1V 3RZ lR[ lt2]V 3R\ lR] l4       t3RV 3R^ lR_ llt4]$V 3R` lRa l4       t5]6! 0 Rm4      t7]$V 3Rb lRc l4       t8]$V 3Rd lRe l4       t9]$V 3Rf lRg l4       t:V 3Rh lRi lt;Rj t<RV 3Rk lRl llt=]$RV 3Rm lRn ll4       t>]$V 3Ro lRp l4       t?RV 3Rq lRr llt@V 3Rs lRt ltAV 3Ru lRv ltBRwR
/V 3Rx lRy lltCV 3Rz lR{ ltDV 3R| lR} ltEV 3R~ lR ltFV 3R lR ltGV 3R lR ltHV 3R lR ltI]$V 3R lR l4       tJV 3R lR ltK]$V 3R lR l4       tLV 3R lR ltMV 3R lR ltNV 3R lR ltOV 3R lR ltPV 3R lR ltQV 3R lR ltRRV 3R lR lltSRV 3R lR lltTRR/V 3R lR lltURR/V 3R lR lltVV 3R lR ltWV 3R lR ltXV 3R lR ltYRR/V 3R lR lltZV 3R lR lt[V 3R lR lt\V 3R lR lt]V 3R lR lt^V 3R lR lt_V 3R lR lt`RR/V 3R lR lltaV 3R lR ltbV 3R lR ltc]6! 0 Rm4      tdV 3R lR lte]$V 3R lR l4       tf]$V 3R lR l4       tgV 3R lR lthV 3R lR ltiV 3R lR ltjV 3R lR ltkV 3R lR ltlV 3R lR ltmV 3R lR ltnV 3R lR lto]$V 3R lR l4       tpV 3R lR ltqRV 3R lR lltrRRRR/V 3R lR lltsRV 3R lR llttRV 3R lR lltuRV 3R lR lltvRV 3R lR lltwV 3R lR ltxV 3R lR ltyV 3R lR ltzRV 3R lR llt{RV 3R lR llt|Rt}V t~R# )AIAgenti  z
AI Agent with tool calling capabilities.

This class manages the conversation flow, tool execution, and response handling
for AI models that support function calling.
c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   AIAgent.__annotate__  s      # rH   c                    V P                   # rU   )	_base_urlrW   s   &rE   base_urlAIAgent.base_url  s    ~~rH   c                $   < V ^8  d   QhRS[ RR/# )rq   valuerr   Nr   )rs   rn   s   "rE   rt   r.    s     > >c >d >rH   c                ^    Wn         V'       d   VP                  4       V n        R# R V n        R# r   N)r0  lower_base_url_lowerrC   r4  s   &&rE   r1  r2    s    05u{{}2rH   Nr   g      ?FTc          b        < V ^8  d   QhRS[ RS[ RS[ RS[ RS[ RS[S[ ,          R,          RS[ R	S[S[ ,          R,          R
S[ RS[RS[RS[S[ ,          RS[S[ ,          RS[RS[RS[RS[ RS[RS[ RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[ RS[RS[ RS[ RS[RS[RS[RS[R S[R!S[R"S[R#S[R$S[R%S[R&S[R'S[S[ S[3,          R(S[S[S[ S[3,          ,          R)S[ R*S[R+S[R,S[ R-R.R/S[S[ S[3,          R0S[R1S[R2S[R3S[/1# )4rq   r1  api_keyproviderapi_modeacp_commandacp_argsNcommandargsmodelmax_iterations
tool_delayenabled_toolsetsdisabled_toolsetssave_trajectoriesverbose_logging
quiet_modeephemeral_system_promptlog_prefix_chars
log_prefixproviders_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collection
session_idtool_progress_callbacktool_start_callbacktool_complete_callbackthinking_callbackreasoning_callbackclarify_callbackstep_callbackstream_delta_callbacktool_gen_callbackstatus_callback
max_tokensreasoning_configprefill_messagesplatformskip_context_filesskip_memoryparent_session_iditeration_budgetr~   fallback_modelcheckpoints_enabledcheckpoint_max_snapshotspass_session_idpersist_session)	rP   r   r   floatr   r   callabler   r   )rs   rn   s   "rE   rt   r.    s    w ww w 	w
 w w s)d"w w 3i$w w w w s)w  9w  w  !w" #w$ "%%w& 'w( )w*  9+w,  9-w. c/w0 1w2 &*3w4 #&5w6 7w8 !)9w: &;w< !)=w> $?w@ %AwB #CwD  EwF  (GwH $IwJ "KwL MwN sCx.OwP tCH~.QwR SwT !UwV WwZ [w\ ,]w^ S#X_wb "cwd #&ewf gwh iwrH   c4                3   \        4        \        V	\        4      '       d   T	M
\        V	4      V n        Wn        T-;'       g    \        V
4      V n        Wn        Wn        Wn	        VV n
        VV n        V(V n        RV n        RV n        V)V n        V2V n        V3V n        V/V n        VV n        V'       d   V R2MRV n        T;'       g    RV n        \        V\        4      '       d5   VP-                  4       '       d   VP-                  4       P/                  4       MRp4T4;'       g    RV n        T;'       g    TV n        \5        T;'       g    T;'       g    . 4      V n        VR9   d   W@n        MV P0                  R8X  d	   RV n        MV4f!   RV P:                  9   d   RV n        RV n        MtV P0                  R	8X  g   V4f!   R
V P:                  9   d   RV n        R	V n        M?V P:                  P=                  R4      P?                  R4      '       d	   RV n        MRV n        V P8                  R8X  d   V PA                  4       '       d   RV n        V P0                  R8X  g   V PC                  4       '       d(   \D        PF                  ! R RR7      PI                  4        VV n%        VV n&        VV n'        VV n(        VV n)        RV n*        V V n+        V!V n,        V"V n-        V$V n.        V#V n/        RV n0        RV n1        RV n2        RV n3        \D        Ph                  ! 4       V n5        ^ V n6        . V n7        \D        Pp                  ! 4       V n9        VV n:        VV n;        VV n<        VV n=        VV n>        VV n?        Wn@        WnA        V%V nB        V&V nC        T';'       g    . V nD        V PC                  4       p5RV P                  P/                  4       9   p6V P8                  R8H  p7T5;'       d    T6;'       g    T7T nE        RV nF        RV nG        RV nH        RV nI        RV nJ        \        P                  ! 4       V nL        RV nM        RV nN        ^ V nO        ^ RIPHQp8HRp9 V8! \        R7       V P                  '       d   V9! 4        \        P                  R4       MNV P                  '       d=   R F6  p:\        P                  ! V:4      P                  \        P                  4       K8  	  RV nZ        RV n[        RV n\        RV n]        / V n^        RV n_        RV n`        V P8                  R8X  d   ^ RIaHbp;Hcp< V P0                  R	8H  p=V='       d   T;'       g    V<! 4       ;'       g    RMT;'       g    Rp>V>V nd        V>V ne        Wnf        ^ RIaHgp? V?! V>4      V n`        V;! V>V4      V n_        RV nh        / V ni        V P                  '       gM   \        RV P                   R24       V>'       d,   \        V>4      ^8  d   \        RV>R,           R V>RR  24       EM]V'       d   V'       d   R!VR"V/p@V P0                  R#8X  d   V P2                  X@R$&   V P6                  V@R%&   TpARVAP/                  4       9   d   R&R'R(R)R*R+/X@R,&   EMcR-XAP/                  4       9   d   ^ R.IlHmpB VB! 4       X@R,&   EM<R/XAP/                  4       9   d   R0R1/X@R,&   EM^ R2InHopC TC! V P0                  ;'       g    R3V P                  RR47      w  pDpEVDea   R!XDP                  R"\        VDP*                  4      /p@\        VDR54      '       d+   XDP                  '       d   \        XDP                  4      X@R,&   MV P0                  ;'       g    RP-                  4       P/                  4       pFVF'       d(   XFR9  d!   \        R6XF R7VFP                  4        R824      hR!\        P                  ! R9R4      R"\        R,R&R'R(R)R*R+//p@X@V ni        \        V@P                  R"R4      4      P/                  4       pGRVG9   d}   RV P                  ;'       g    RP/                  4       9   dT   X@P                  R,4      ;'       g    / pHVHP                  R:R4      pIR;pJVJVI9  d   XI'       d   XI R<XJ 2XHR:&   MXJXHR:&   XHX@R,&   X@P                  R!R4      V nd         V P                  V@R=RR>7      V nh        V P                  '       g   \        RV P                   24       V'       d   \        R?V 24       X@P                  R!R@4      pKVK'       d4   XKRA8w  d-   \        XK4      ^8  d   \        RBXKR,           R VKRR  24       M \        RCXK'       d
   XKRD,          MR@ RE24       \        V.\4        4      '       dc   V. UMu. uFO  pM\        VM\        4      '       g   K  XMP                  RG4      '       g   K4  XMP                  RH4      '       g   KM  XMNKQ  	  upMV n{        MT\        V.\        4      '       d8   V.P                  RG4      '       d!   V.P                  RH4      '       d
   V..V n{        M. V n{        ^ V n|        RV n}        V P                  '       d   V P                  ^ ,          MRV n~        V P                  '       d   V P                  '       g   \        V P                  4      ^8X  d5   V P                  ^ ,          pN\        RIVNRH,           RJVNRG,           RK24       MI\        RL\        V P                  4       RM2RNP                  RO V P                   4       4      ,           4       E\        VVV P                  RP7      V n        E\        4       V n        V EP                  '       d   V EP                   UOu0 uF  pOVORQ,          RR,          kK  	  upOV n        E\	        V EP                  4      pPV P                  '       g   \        RS\        V EP                  4       RTRUP                  XP4       24       V'       d   \        RVRUP                  V4       24       V'       d   \        RWRUP                  V4       24       MV P                  '       g   \        RX4       V EP                  '       dc   V P                  '       gQ   E\        4       pQVQEP                  4        URUSu. uF  w  pRpSVS'       d   K  XRNK  	  pTpRpSVT'       d   \        RYXT 24       V P                  '       d   V P                  '       g   \        RZ4       V P                  '       db   V P                  '       gP   \        V P                  4      ^<8  d   V P                  R[,          R ,           MV P                  pU\        R\VU R]24       V P                  '       d;   V P                  '       g)   V7'       d   R^MR_pV\        R`VV RUV P                   Ra24       E\        EP                  ! 4       V n        V'       d	   VV n        MRV EP                  EP                  Rb4      pWE\        EP                  ! 4       EP                  Rc,          pXVW RdVX 2V n        E\        4       pYVYRe,          V n        V EP                   EP#                  RRRf7       V EP                   RgV EP                   Rh2,          V n        . V n        RV n        ^ RiIHpZ VZ! V0V1Rj7      V n        V+V n        V,V n        ^ V n        V EP0                  '       d    V EP0                  EP7                  V EP                  V P                  ;'       g"    \        EP8                  P                  RkRl4      V P                  RmV P                  RnV&RoV%/RV EP2                  Rp7       ^ RrIHp[ V[! 4       V n         ^ RsIHp\ V\! 4       p]RV n        RV n        RV n        ^
V n        ^V n        ^ V n        ^ V n        V*'       g    X]P                  Rt/ 4      p^V^P                  RuR4      V n        V^P                  RvR4      V n        E\U        V^P                  Rw^
4      4      V n        E\U        V^P                  Rx^4      4      V n        V EPH                  '       g   V EPJ                  '       dR   ^ RyIHp_ V_! X^P                  RzR{4      V^P                  R|R}4      R~7      V n        V EPF                  EP[                  4        RV n        V*'       Eg    X^'       d   X^P                  RGR4      MRp`V`'       g    ^ RIHpa VaEPc                  4       pbVbEPd                  '       d}   XbP                  '       g   XbP*                  '       dY   Rp` ^ RIHpcHpd Vc! 4       peRVeEPi                  Rt/ 4      RG&   Vd! Ve4       V P                  '       g   \        R4       \        R4       X`'       Ed   ^ RIHpf ^ RIHpg Vf! 4       V n        Vg! X`4      phVh'       d5   XhEPs                  4       '       d   V EP\                  EPu                  Xh4       V EP\                  EPv                  '       d   ^ RIHpi RV EP                  RT(;'       g    RlR\        Xi! 4       4      RR/pj ^ RIHpk Vk! 4       plVlVjR&   RVjR&   V EP\                  EP~                  ! R/ XjB  \        P                  RX`4       M\        EP                  RX`4       RV n        V EP\                  '       d   V EP                  e   V EP\                  EP                  4        F_  pnRRQRQVn/poV EP                  EP                  Vo4       VnP                  RRR4      ppVp'       g   KB  V EP                  EP                  Xp4       Ka  	  ^
V n         X]P                  R/ 4      pqE\U        VqP                  R^
4      4      V n        X]P                  R/ 4      pr\        Vr\        4      '       g   / prXrP                  RR34      V n        X]P                  R/ 4      ps\        Vs\        4      '       g   / psE\        XsP                  RR4      4      pt\        VsP                  RR4      4      P/                  4       R9   puVsP                  R4      ;'       g    RpvE\        XsP                  RR4      4      pwE\U        VsP                  R^4      4      pxX]P                  RH/ 4      py\        Vy\        4      '       d   XyP                  R4      pzMRpzXze    E\U        Xz4      pzXzEf   X]P                  R4      p{\        V{\4        4      '       d   X{ F  p|\        V|\        4      '       g   K  X|P                  R"4      ;'       g    RP=                  R4      p}V}'       g   KO  X}V P*                  P=                  R4      8X  g   Kq  X|P                  R/ 4      p~\        V~\        4      '       dU   X~P                  V P                  / 4      p\        V\        4      '       d#   XP                  R4      pVe    E\U        X4      pz M	  E\        V P                  Xt^XxXwXvV P                  V P*                  E\        V R!R4      XzV P0                  R7      V n        XuV n        E\        \        P                  ! R4      ;'       g    RR7      V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        RV n        RV n        R@V n        V P                  '       g   Xu'       dV   \        RV EP                  EP                  R< RE\U        Xt^d,          4       RV EP                  EP                  R< RK24       M&\        RV EP                  EP                  R< R24       V EP                  pRHV P                  RGV P0                  R"V P*                  RV P8                  R!E\        V R!R4      R\        V P                  4      RV P                  RVP                  RVP*                  RE\        VR!R4      RVP0                  RVEP                  RVEP                  /V n        V P8                  R8X  dD   V EP                  EP                  RV P                  RV P                  RV P                  /4       R# R#   \         d   pL\        RFTL 24      hRpL?Lii ; iu upMi u upOi u upSpRi   \         d#   pL\        EP;                  RqTL4        RpL?LE	LRpL?Lii ; i  \         d    / p] E	L{i ; i  \         d     ELZi ; i  \         d     ELi ; i  \         d     ELi ; i  \         d     ELi ; i  \         d*   pm\        EP;                  RTm4       RT n         Rpm?mELRpm?mii ; i  \         d     EL i ; i  E\        E\        3 d    Rpz ELi ; i  E\        E\        3 d     ELi ; i)ah  
Initialize the AI Agent.

Args:
    base_url (str): Base URL for the model API (optional)
    api_key (str): API key for authentication (optional, uses env var if not provided)
    provider (str): Provider identifier (optional; used for telemetry/routing hints)
    api_mode (str): API mode override: "chat_completions" or "codex_responses"
    model (str): Model name to use (default: "anthropic/claude-opus-4.6")
    max_iterations (int): Maximum number of tool calling iterations (default: 90)
    tool_delay (float): Delay between tool calls in seconds (default: 1.0)
    enabled_toolsets (List[str]): Only enable tools from these toolsets (optional)
    disabled_toolsets (List[str]): Disable tools from these toolsets (optional)
    save_trajectories (bool): Whether to save conversation trajectories to JSONL files (default: False)
    verbose_logging (bool): Enable verbose logging for debugging (default: False)
    quiet_mode (bool): Suppress progress output for clean CLI experience (default: False)
    ephemeral_system_prompt (str): System prompt used during agent execution but NOT saved to trajectories (optional)
    log_prefix_chars (int): Number of characters to show in log previews for tool calls/responses (default: 100)
    log_prefix (str): Prefix to add to all log messages for identification in parallel processing (default: "")
    providers_allowed (List[str]): OpenRouter providers to allow (optional)
    providers_ignored (List[str]): OpenRouter providers to ignore (optional)
    providers_order (List[str]): OpenRouter providers to try in order (optional)
    provider_sort (str): Sort providers by price/throughput/latency (optional)
    session_id (str): Pre-generated session ID for logging (optional, auto-generated if not provided)
    tool_progress_callback (callable): Callback function(tool_name, args_preview) for progress notifications
    clarify_callback (callable): Callback function(question, choices) -> str for interactive user questions.
        Provided by the platform layer (CLI or gateway). If None, the clarify tool returns an error.
    max_tokens (int): Maximum tokens for model responses (optional, uses model default if not set)
    reasoning_config (Dict): OpenRouter reasoning configuration override (e.g. {"effort": "none"} to disable thinking).
        If None, defaults to {"enabled": True, "effort": "medium"} for OpenRouter. Set to disable/customize reasoning.
    prefill_messages (List[Dict]): Messages to prepend to conversation history as prefilled context.
        Useful for injecting a few-shot example or priming the model's response style.
        Example: [{"role": "user", "content": "Hi!"}, {"role": "assistant", "content": "Hello!"}]
    platform (str): The interface platform the user is on (e.g. "cli", "telegram", "discord", "whatsapp").
        Used to inject platform-specific formatting hints into the system prompt.
    skip_context_files (bool): If True, skip auto-injection of SOUL.md, AGENTS.md, and .cursorrules
        into the system prompt. Use this for batch processing and data generation to avoid
        polluting trajectories with user-specific persona or project instructions.
N r   chat_completionscodex_responsesanthropic_messagesopenai-codexzchatgpt.com/backend-api/codex	anthropicapi.anthropic.com/
/anthropic
openrouterc                      \        4       # rU   )r   rd   rH   rE   <lambda>"AIAgent.__init__.<locals>.<lambda>  s    35rH   TtargetdaemonFclaude5mffffff?g?initializing)setup_loggingsetup_verbose_logging)r   z=Verbose logging enabled (third-party library logs suppressed))build_anthropic_clientresolve_anthropic_token_is_oauth_tokenu&   🤖 AI Agent initialized with model: z (Anthropic native)u   🔑 Using token: N   N...r;  r1  copilot-acpr@  rA  zHTTP-Refererz%https://hermes-agent.nousresearch.comzX-OpenRouter-TitlezHermes AgentzX-OpenRouter-Categorieszproductivity,cli-agentdefault_headersapi.githubcopilot.comcopilot_default_headersapi.kimi.com
User-AgentKimiCLI/1.3resolve_provider_clientauto)rB  	raw_codex_default_headersz
Provider 'z:' is set in config.yaml but no API key was found. Set the zU_API_KEY environment variable, or switch to a different provider with `hermes model`.OPENROUTER_API_KEYzx-anthropic-betaz&fine-grained-tool-streaming-2025-05-14r  
agent_initreasonsharedu   🔗 Using custom base URL: nonez	dummy-keyu   🔑 Using API key: u;   ⚠️  Warning: API key appears invalid or missing (got: ':N   Nz...')z$Failed to initialize OpenAI client: r<  rB  u   🔄 Fallback model:  ()u   🔄 Fallback chain (z providers):     → c              3   L   "   T F  qR ,           RVR,           R2x  K  	  R# 5i)rB  r  r<  r  Nrd   )r   r'  s   & rE   r   #AIAgent.__init__.<locals>.<genexpr>  s%     "cNbj\AjM?!#DNbs   "$)rE  rF  rI  r   ra   u   🛠️  Loaded z tools: , u      ✅ Enabled toolsets: u      ❌ Disabled toolsets: u@   🛠️  No tools loaded (all tools filtered out or unavailable)u=   ⚠️  Some tools may not work due to missing requirements: u   📝 Trajectory saving enabledN<   Nu   🔒 Ephemeral system prompt: 'z' (not saved to trajectories)znative AnthropiczClaude via OpenRouteru   💾 Prompt caching: ENABLED (z TTL)%Y%m%d_%H%M%SN   Nr  sessions)parentsr  session_.json)CheckpointManager)enabledmax_snapshotsHERMES_SESSION_SOURCEclirC  r_  r^  )rS  sourcerB  model_configuser_idrd  zESession DB create_session failed (session_search still available): %s)	TodoStore)load_configmemorymemory_enableduser_profile_enablednudge_intervalflush_min_turns)MemoryStorememory_char_limiti  user_char_limiti_  )r  r  )HonchoClientConfighoncho)r  save_configu5     ✓ Auto-migrated Honcho to memory provider plugin.z(    Your config and data are preserved.
)MemoryManager)load_memory_providerr
   rS  ra  r   agent_contextprimary)get_active_profile_nameagent_identityhermesagent_workspacezMemory provider '%s' activatedz/Memory provider '%s' not found or not availablez&Memory provider plugin init failed: %sr   skillscreation_nudge_intervalagenttool_use_enforcementcompression	threshold      ?r  summary_modeltarget_ratio皙?protect_last_ncontext_lengthcustom_providersmodels)rB  threshold_percentprotect_first_nr  summary_target_ratiosummary_model_overriderI  r1  r;  config_context_lengthr<  TERMINAL_CWD)working_dir        unknownu   📊 Context limit: z tokens (compress at z% = z# tokens (auto-compression disabled)r=  client_kwargsuse_prompt_cachingcompressor_modelcompressor_base_urlcompressor_api_keycompressor_providercompressor_context_lengthcompressor_threshold_tokensanthropic_api_keyanthropic_base_urlis_anthropic_oauth>   rp  ro  rq  )tools	run_agenttrajectory_compressorcron
hermes_cli)r  rw  customrd   )true1yes)r|   rO   rP   rB  rC  r~   re  rD  rG  rH  rI  rJ  ra  	_print_fnbackground_review_callbackrb  ri  rj  _credential_poolrK  rL  r1  r   r7  r<  r>  r   r?  r=  r8  rstripendswith_is_direct_openai_url_is_openrouter_urlr   ThreadstartrT  rU  rV  rW  rX  _reasoning_deltas_firedrY  rZ  r[  r]  r\  _last_reported_tool_executing_tools_interrupt_requested_interrupt_messageRLock_client_lock_delegate_depth_active_childrenr   _active_children_lockrM  rN  rO  rP  rQ  rR  rE  rF  r^  r_  r`  _use_prompt_caching
_cache_ttl_budget_caution_threshold_budget_warning_threshold_budget_pressure_enabled_context_pressure_warnedtime_last_activity_ts_last_activity_desc_current_tool_api_call_counthermes_loggingr  r  _hermes_homer  infor   	getLoggersetLevelERROR_stream_callback_stream_needs_break_persist_user_message_idx_persist_user_message_override_anthropic_image_fallback_cache_anthropic_client_is_anthropic_oauthagent.anthropic_adapterr  r  r;  _anthropic_api_key_anthropic_base_urlr  client_client_kwargsprintrQ   hermes_cli.modelsr  agent.auxiliary_clientr  hasattrr  r   RuntimeErrorupperr   getenvr   r   _create_openai_clientr   _fallback_chain_fallback_index_fallback_activated_fallback_modelr  r   r  setvalid_tool_namessortedr   itemsr   r  session_startrS  r  uuiduuid4hexr   logs_dirmkdirsession_log_file_session_messages_cached_system_prompttools.checkpoint_managerr  _checkpoint_mgr_session_db_parent_session_id_last_flushed_db_idxcreate_sessionenvironr   tools.todo_toolr  _todo_storehermes_cli.configr  _memory_store_memory_enabled_user_profile_enabled_memory_nudge_interval_memory_flush_min_turns_turns_since_memory_iters_since_skillr   tools.memory_toolr  load_from_disk_memory_managerplugins.memory.honcho.clientr  from_global_configr  r  
setdefaultagent.memory_managerr  plugins.memoryr  is_availableadd_provider	providershermes_constantshermes_cli.profilesr  initialize_allr   get_all_tool_schemasr   add_skill_nudge_interval_tool_use_enforcementrk  r   rN   r&   r`   context_compressorcompression_enabledr'   _subdirectory_hints_user_turn_countsession_prompt_tokenssession_completion_tokenssession_total_tokenssession_api_callssession_input_tokenssession_output_tokenssession_cache_read_tokenssession_cache_write_tokenssession_reasoning_tokenssession_estimated_cost_usdsession_cost_statussession_cost_sourcer  threshold_tokens_primary_runtimeupdate)rC   r1  r;  r<  r=  r>  r?  r@  rA  rB  rC  rD  rE  rF  rG  rH  rI  rJ  rK  rL  rM  rN  rO  rP  rQ  rR  rS  rT  rU  rV  rW  rX  rY  rZ  r[  r\  r]  r^  r_  r`  ra  rb  rc  
session_dbrd  re  rf  credential_poolrg  rh  ri  rj  provider_nameis_openrouter	is_claudeis_native_anthropicr  r  quiet_loggerr  r  _is_native_anthropiceffective_key_is_oatr  effective_baser  r  _routed_clientr  	_explicit_effective_baseheadersexisting_beta_FINE_GRAINEDkey_useder'  fbr   r   requirementsra   	availablemissing_reqsprompt_previewr  timestamp_str
short_uuidr   r  r  _load_agent_config
_agent_cfg
mem_configr  _mem_provider_name_HCC_hcfg_lc_sc_cfg_MemoryManager	_load_mem_mp_ghh_init_kwargsr  _profile_mpe_schema_wrapped_tnameskills_config_agent_section_compression_cfgcompression_thresholdrd  compression_summary_modelcompression_target_ratiocompression_protect_last
_model_cfg_config_context_length_custom_providers	_cp_entry_cp_url
_cp_models_cp_model_cfg_cp_ctx_ccs   &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&                                                                              rE   rF   AIAgent.__init__  s   z 	(44U#e*
, !1 S SON4S$!2.$'>$ 
 *.'"4.. / 0.8ZL*b B4>x4M4MRZR`R`RbRb(..0hl%++&11'X33334TT$M]]n,-DM#)HDL`L`)`-DM*DM]]k)m.CH[_c_s_sHs0DM'DM!!((-66|DD 1DM.DM
 ==..43M3M3O3O-DM
 ==L(D,C,C,E,E5 eg&<##6 &<#!2"4',$ 0*%:".!2#'  !& %*!"&%OO-  ! "%.^^%5" "3!2.*+F((@% !1!2 % 0 0 6 6B
 //1

 0 0 22	"mm/CC$1$?$?i#W#WDW 
 *-&),&(,%
 ).% )-		(6 )-$%
 	H,/!#KKWX
%L %%l3<<W]]K% !% $) 
 *.&.2+
 @B, "&#( ==00_ $(==K#? L`WGG(?(AGGRgngtgtrtM(DL&3D#'/$J'.}'=D$%;M8%TD"DK"$D???>tzzlJ]^_ S%7"%<.}R/@.A]SUSVEWDXYZ8 "+GZ J==M1/3/?/?M),,0MMM&)!)>#7#7#99&(O,n13K8M"34
 -0D0D0FFI7N7PM"34#~';';'==$m8M"34
 K$;MM++V4::%O!!-!>#9#9"C(?(?$@%M
 ~/ABB~GfGfGf;?@_@_;`&78
 "&!4!4" ; ; = C C EI Y6V%V*( 422;//2C1D E_`  "299-A2#F"$7)*,S0.57O,%M #0D "-"3"3J"CDJJLO.8

@P@Pb?W?W?Y3Y'++,=>DD" ',> C H 5$9Fq6X 236C 237>M"34(,,Y;DLO"88|dh8iB4::,OP <XJGH,00FCHH$;HPR@R 4Xb\N#hrsm_UV [mu\deh\i  |B  \C  CH  I  J nd++)$)aa& +,55+< ABw >$D  --.2D2DZ2P2PUcUgUghoUpUp$2#3D #%D  #( :>:N:N:Nt33A6TX4''(A-))!,-bk]"R
^<LANO-c$2F2F.G-HVll"cdNbNb"ccd e *-/

 !$:::JN**$U*$T*%5f%=%=*$UD! 5 56J???(TZZ(9$))JBWAXYZ $5dii@P6Q5RST$6tyyAR7S6TUVTU :::dooo57L8D8J8J8L^8L_T9T]DD8LL^UVbUcde !!!$///23 '''JMdNjNjJknpJpT99#>Fvz  wS  wSN3N3CC`ab ###DOOO+>'D[F26("T__<MUST &\\^(DO !..77HM))"-J!.q=DO &'#j0D48 $(4??:K50Q Q 8: 59" 	?0'2 
 &"3$%!  //#==ZZBJJNN;RTY,Z**($*=*=*,<$j"
 !&*&=&= 0 0 	.$;	K+-J
 "$%*"&(#'($#$ "#'^^Hb9
'1~~6F'N$-7^^<RTY-Z*.1*..AQSU2V.W+/2:>>BSUV3W/X,'''4+E+E+E=)4*4..9Ld*S(27H$(O*D& &&557  ${:,GQZ^^J%CWY" *[ $ 7 7 9 ===emmmu~~~19.% d'*uLT" =j I #D	 $(??? %&] ^ %&Q R &%TP+9+;D(#$67Cs//11,,99#>++555L($//&(9(9E)3tv;+Y	(!S'>'@H=EL)9:>FL):; ,,;;KlK$DFXY%VXjk/3, DJJ$://DDF"J
GD

!!(+ VR06))--f5 G &("	&NN8R8M),]->->?XZ\-])^D& $4.$//N%3%7%78NPV%W"
 &>>-<*D11! %&6&:&:;&M N!"2"6"6y$"GHNNPThh$4$8$8$I$Q$QT!#()9)=)=nd)S#T #&'7';';<Lb'Q#R   ^^GR0
j$''%/^^4D%E"%)"!-.),-C)D&
 ") */A B+T22!2I%i66 (}}Z8>>BFFsKGw7dmm.B.B3.G#G%.]]8R%@
%j$77,6NN4::r,JM)->>*7*;*;<L*M#*#6%-ADW(>  "3" #4**33!9#<]]D)R0"8]]#
 $7 #:		.199T$
  !" &'")*&$%!!"$%!%&")*&*+'()%*-'#, #) ",T-D-D-S-STU,VVklo  qF  GJ  qJ  mK  lL  LP  QU  Qh  Qh  Qy  Qy  z{  P|  |}  ~  ,T-D-D-S-STU,VVyz{ %%TZZwtY3T$"5"56 $":":		!3<< '#y""=!3<<'););)3+?+?!
  ==00!!((#T%<%<$d&>&>$d&>&>*  1U  O"%I!#MNNO$< %V  _D  	 []^ 	&  	J	2  : $- % $%
 % 0  ) ! !  ,GN'+$$,$  		> z* .)-&.( -6z+B %-(,%-s  *Ab AAb 2Ab   Ab :Ab5Ab50Ab5	Ab51Ab:Ab?-Ab?$5Ac AAc =Ac5 B'Ad	 A,AAd	 CAe CAe C3)Ad- DAd- D/Ad- EAd- E-Ad E1Ad- FAd- FAe F"'Ae G
Ae G!:Ae HAe H9Ae IAd? I'4Ae JAe M#3Af SAf W8Af6bAb2bAb-b-Ab2cAc2cAc-c-Ac2c5AddAdd	AddAddAd*d&Ad- d)Ad*d*Ad- d-Ad<d8Ae d;Ad<d<Ae d?Aee
Ae eAeeAe eAfeAf f AffAffAffAf3f2Af3f6AggAgc                   ^ V n         ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        ^ V n        RV n	        RV n
        RV n        ^ V n        \        V R4      '       d   V P                  '       dz   ^ V P                  n        ^ V P                  n        ^ V P                  n        ^ V P                  n        RV P                  n        RV P                  n        RV P                  n        R# R# R# )a3  Reset all session-scoped token counters to 0 for a fresh session.

This method encapsulates the reset logic for all session-level metrics
including:
- Token usage counters (input, output, total, prompt, completion)
- Cache read/write tokens
- API call count
- Reasoning tokens
- Estimated cost tracking
- Context compressor internal counters

The method safely handles optional attributes (e.g., context compressor)
using ``hasattr`` checks.

This keeps the counter reset logic DRY and maintainable in one place
rather than scattering it across multiple methods.
r  r  r  rc  FN)ri  rk  rl  rg  rh  rm  rn  ro  rj  rp  rq  rr  rf  r*  rc  last_prompt_tokenslast_completion_tokenslast_total_tokenscompression_count_context_probed_context_probe_persistable_previous_summaryrW   s   &rE   reset_session_stateAIAgent.reset_session_state  s    & %&!$%!%&"%&")*&)*&*+'()%!"*-'#, #)  !" 4-..43J3J3J9:D##6=>D##:89D##589D##56;D##3AFD##>8<D##5 4K.rH   c                   ^ RI p^ RIHp V'       g	   V! W$4      pV P                  pV P                  p	Wn        W n        T;'       g    V P
                  V n        WPn        V'       d   W0n        VR8X  d   ^ RIH	p
H
pHp T;'       g&    V P                  ;'       g    V! 4       ;'       g    RpWn        Wn        T;'       g    \        V RR4      V n        V
! WP                  4      V n        V! V4      V n        RV n        / V n        McT;'       g    V P                  pT;'       g    V P
                  pRVRV/V n        V P'                  \)        V P$                  4      R	R
R7      V n        VR8H  pRV P
                  ;'       g    RP+                  4       9   ;'       d    RVP+                  4       9   ;'       g    TV n        \/        V R4      '       d   V P0                  '       d   ^ RIHp V! V P                  V P
                  V P                  V P                  R7      pV P                  V P0                  n        V P
                  V P0                  n        V P                  V P0                  n        V P                  V P0                  n        VV P0                  n        \9        VV P0                  P:                  ,          4      V P0                  n        RV n        \/        V R4      '       d   V P0                  '       d   V P0                  MRpRV P                  RV P                  RV P
                  RV P                  R\        V RR4      R\)        V P$                  4      RV P,                  RV'       d   VP                  MV P                  RV'       d   VP
                  MV P
                  RV'       d   \        VRR4      MRRV'       d   VP                  MV P                  RV'       d   VP6                  M^ RV'       d   VP<                  M^ /V n         VR8X  d@   V P@                  PC                  RV P                  RV P                  RV P                   /4       RV n"        ^ V n#        VPH                  ! R WW4       R# )!a  Switch the model/provider in-place for a live agent.

Called by the /model command handlers (CLI and gateway) after
``model_switch.switch_model()`` has resolved credentials and
validated the model.  This method performs the actual runtime
swap: rebuilding clients, updating caching flags, and refreshing
the context compressor.

The implementation mirrors ``_try_activate_fallback()`` for the
client-swap logic but also updates ``_primary_runtime`` so the
change persists across turns (unlike fallback which is
turn-scoped).
N)determine_api_moderq  r  r  r  r   r$  r;  r1  switch_modelTr  rw  r~  rc  get_model_context_lengthr1  r;  r<  rB  r<  r=  r  r  r  r  r  r  r  r  r  r  r  Fz+Model switched in-place: %s (%s) -> %s (%s))%r   hermes_cli.providersr  rB  r<  r1  r=  r;  r"  r  r  r  r#  r`   r$  r   r!  r%  r&  r.  r   r7  r
  r*  rc  agent.model_metadatar  r  r   r  rs  r?  rt  ru  r1  r0  r  )rC   	new_modelnew_providerr;  r1  r=  r   r  	old_modelold_providerr  r  r  r~  r  r{  r  new_context_lengthr  s   &&&&&&             rE   r  AIAgent.switch_model  s    	; ),AHJJ	}} 
$ 11DMM "L ++ 
 $VVt||VV7N7PVVTVM(L&3#'/']']74AVX\3]D$%;77&D" (7}'ED$DK"$D#33t||M%66N=N#D 44T(()% 5 DK '*>>dmm11r88::\\x9??K\?\ # #" 	  4-..43J3J3JE!9

	" -1JJD##)/3}}D##,.2llD##+/3}}D##,5GD##27:"T%<%<%N%NN8D##4
 &*" *17K)L)LQUQhQhQhd%%nrTZZwtY3T$"5"56 $":":S		djj!33<<DMM '#y""="!33<<DMM's););)33+?+?A!
 ++!!((#T%<%<$d&>&>$d&>&>*  $)  9Y	
rH   c                |     V P                   ;'       g    \        pV! V/ VB  R#   \        \        3 d     R# i ; i)a  Print that silently handles broken pipes / closed stdout.

In headless environments (systemd, Docker, nohup) stdout may become
unavailable mid-session.  A raw ``print()`` raises ``OSError`` which
can crash cron jobs and lose completed work.

Internally routes through ``self._print_fn`` (default: builtin
``print``) so callers such as the CLI can inject a renderer that
handles ANSI escape sequences properly (e.g. prompt_toolkit's
``print_formatted_text(ANSI(...))``) without touching this method.
N)r  r'  rM   rN   )rC   rA  kwargsfns   &*, rE   _safe_printAIAgent._safe_print  s<    	((5B$ 		s   & & ;;forcec                    < V ^8  d   QhRS[ /# )rq   r  r   )rs   rn   s   "rE   rt   r.    s     * *D *rH   c                   V'       g   \        V RR4      '       d   R# V'       g+   V P                  4       '       d   V P                  '       g   R# V P                  ! V/ VB  R# )u  Verbose print — suppressed when actively streaming tokens.

Pass ``force=True`` for error/warning messages that should always be
shown even during streaming playback (TTS or display).

During tool execution (``_executing_tools`` is True), printing is
allowed even with stream consumers registered because no tokens
are being streamed at that point.

After the main response has been delivered and the remaining tool
calls are post-response housekeeping (``_mute_post_response``),
all non-forced output is suppressed.
_mute_post_responseFN)r`   _has_stream_consumersr  r  )rC   r  rA  r  s   &$*,rE   _vprintAIAgent._vprint  sK     '<eDD3355d>S>S>S$)&)rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s      T rH   c                    V P                   e   R# \        \        RR4      pVf   R#  \        VP	                  4       4      #   \
        \        \        3 d     R# i ; i)aZ  Return True when quiet-mode spinner output has a safe sink.

In headless/stdio-protocol environments, a raw spinner with no custom
``_print_fn`` falls back to ``sys.stdout`` and can corrupt protocol
streams such as ACP JSON-RPC. Allow quiet spinners only when either:
- output is explicitly rerouted via ``_print_fn``; or
- stdout is a real TTY.
NTrv   F)r  r`   rx   r   r]   AttributeErrorrN   rM   )rC   r{   s   & rE   _should_start_quiet_spinner#AIAgent._should_start_quiet_spinner  sV     >>%h->	((
G4 		s   A AAc                $   < V ^8  d   QhRS[ RR/# rq   messagerr   Nr   )rs   rn   s   "rE   rt   r.    s     U UC UD UrH   c                    V P                  V P                   V 2RR7       V P                  '       d    V P                  RV4       R# R#   \         d     L6i ; i  \         d    \        P                  RRR7        R# i ; i)uh  Emit a lifecycle status message to both CLI and gateway channels.

CLI users see the message via ``_vprint(force=True)`` so it is always
visible regardless of verbose/quiet mode.  Gateway consumers receive
it through ``status_callback("lifecycle", ...)``.

This helper never raises — exceptions are swallowed so it cannot
interrupt the retry/fallback logic.
Tr  	lifecyclez%status_callback error in _emit_statusexc_infoN)r  rL  r   r]  r  r   )rC   r  s   &&rE   _emit_statusAIAgent._emit_status  s    	LLDOO,WI6dLC U$$[':    		
  UDtTUs"   !A A AA"BBc                &   < V ^8  d   QhRS[ RS[/# )rq   r1  rr   r   )rs   rn   s   "rE   rt   r.    s     C Cc CT CrH   c                n    T;'       g    V P                   P                  4       pRV9   ;'       d    RV9  # )z8Return True when a base URL targets OpenAI's native API.zapi.openai.comrw  )r8  r7  )rC   r1  urls   && rE   r  AIAgent._is_direct_openai_url  s6    //4//6683&BB<s+BBrH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     4 4D 4rH   c                     RV P                   9   # )z1Return True when the base URL targets OpenRouter.rw  )r8  rW   s   &rE   r  AIAgent._is_openrouter_url  s    t3333rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     v v4 vrH   c                    RV P                   9   ;'       g+    V P                   P                  R4      P                  R4      # )zRReturn True when the base URL targets Anthropic (native or /anthropic proxy path).rt  ru  rv  )r8  r  r  rW   s   &rE   _is_anthropic_urlAIAgent._is_anthropic_url  s9    "d&:&::uud>R>R>Y>YZ]>^>g>ght>uurH   c                &   < V ^8  d   QhRS[ RS[/# )rq   r4  rr   )r   r   )rs   rn   s   "rE   rt   r.    s     	% 	%s 	%t 	%rH   c                >    V P                  4       '       d   RV/# RV/# )zReturn the correct max tokens kwarg for the current provider.

OpenAI's newer models (gpt-4o, o-series, gpt-5+) require
'max_completion_tokens'. OpenRouter, local models, and older
OpenAI models use 'max_tokens'.
max_completion_tokensr^  )r  r9  s   &&rE   _max_tokens_paramAIAgent._max_tokens_param  s)     %%''+U33e$$rH   c                &   < V ^8  d   QhRS[ RS[/# rq   r   rr   r   )rs   rn   s   "rE   rt   r.    s     % %c %d %rH   c                j    V'       g   R# V P                  V4      p\        VP                  4       4      # )a  
Check if content has actual text after any reasoning/thinking blocks.

This detects cases where the model only outputs reasoning but no actual
response, which indicates an incomplete generation that should be retried.
Must stay in sync with _strip_think_blocks() tag variants.

Args:
    content: The assistant message content to check

Returns:
    True if there's meaningful content after think blocks, False otherwise
F)_strip_think_blocksr   r   )rC   r   r  s   && rE   _has_content_after_think_block&AIAgent._has_content_after_think_block  s/      **73 GMMO$$rH   c                &   < V ^8  d   QhRS[ RS[ /# r  r   )rs   rn   s   "rE   rt   r.    s      3 3 rH   c                   V'       g   R# \         P                  ! RRV\         P                  R7      p\         P                  ! RRV\         P                  \         P                  ,          R7      p\         P                  ! RRV\         P                  R7      p\         P                  ! RRV\         P                  R7      p\         P                  ! RRV\         P                  R7      pV# )zKRemove reasoning/thinking blocks from content, returning only visible text.r   z<think>.*?</think>flagsz<thinking>.*?</thinking>z<reasoning>.*?</reasoning>z0<REASONING_SCRATCHPAD>.*?</REASONING_SCRATCHPAD>z8</?(?:think|thinking|reasoning|REASONING_SCRATCHPAD)>\s*)r  r   DOTALL
IGNORECASE)rC   r   s   &&rE   r  AIAgent._strip_think_blocks  s     &&.G299M&&4b'UWUbUbIbc&&6G299U&&LbRYacajajk&&TVXZaikivivwrH   c          	      X   < V ^8  d   QhRS[ RS[ RS[S[S[ S[3,          ,          RS[/# )rq   user_messageassistant_contentr   rr   )rP   r   r   r   r   )rs   rn   s   "rE   rt   r.    sL     Ee EeEe Ee tCH~&	Ee
 
EerH   c                  a
a \         ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   R# T P                  T;'       g    R4      P                  4       P                  4       o
S
'       g   R# \	        S
4      R8  d   R# \        \        P                  ! RS
4      4      pV'       g   R# RpRpT;'       g    RP                  4       P                  4       o\         ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      ;'       g    RS9   ;'       g    R	S9   p\         ;QJ d    V
3R
 lV 4       F  '       g   K   RM	  RM! V
3R
 lV 4       4      p\         ;QJ d    V
3R lV 4       F  '       g   K   RM	  RM! V
3R lV 4       4      p	T;'       g    T	;'       d    T# )zNDetect a planning/ack message that should continue instead of ending the turn.c              3   z   "   T F1  p\        V\        4      ;'       d    VP                  R 4      R8H  x  K3  	  R# 5i)r   r   N)rO   r   r   r   r   s   & rE   r   =AIAgent._looks_like_codex_intermediate_ack.<locals>.<genexpr>  s/     Whsz#t$BBF)BBhs   ;;TFr   i  u@   \b(i['’]ll|i will|let me|i can do that|i can help with that)\bc              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   )r   marker	user_texts   & rE   r   r  Q  s     D2C)#2C   z~/ru  c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   r   r  assistant_texts   & rE   r   r  U  s     '^~V.(@~r  c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   r  s   & rE   r   r  V  s      *
3Dn$3Dr  )z	look intozlook atinspectscancheckanalyzreviewexplorereadr  runtestfixr   r   findwalkthroughzreport back	summarize)	directoryzcurrent directoryzcurrent dirr   repo
repositorycodebaseprojectfolder
filesystemz	file treefilesr   )r   r  r   r7  rQ   r   r  r   )rC   r  r  r   has_future_ackaction_markersworkspace_markersuser_targets_workspaceassistant_mentions_actionassistant_targets_workspacer  r  s   &&&&      @@rE   "_looks_like_codex_intermediate_ack*AIAgent._looks_like_codex_intermediate_ack  so    3WhW333WhWWW112C2I2IrJPPRXXZ~%IIY[ij
 
*
  "''R..0668	CD2CDCCCD2CDD    y    i 	
 %(C'^~'^CCC'^~'^$^!&)c *
3D*
ccc *
3D*
 '
# 'EE*EddKddrH   c                0   < V ^8  d   QhRS[ S[,          /# r   r   rP   )rs   rn   s   "rE   rt   r.  \  s     @ @x} @rH   c                `   . p\        VR4      '       d.   VP                  '       d   VP                  VP                  4       \        VR4      '       d?   VP                  '       d-   VP                  V9  d   VP                  VP                  4       \        VR4      '       d   VP                  '       d   VP                   F  p\        V\        4      '       g   K  VP                  R4      ;'       gD    VP                  R4      ;'       g+    VP                  R4      ;'       g    VP                  R4      pV'       g   K  WB9  g   K  VP                  V4       K  	  \        VRR4      pV'       g   \        V\        4      '       d   V'       d   RpV Fz  p\        P                  \        P                  ,          p\        P                  ! WuVR	7       F6  p	V	P                  4       p
V
'       g   K  W9  g   K%  VP                  V
4       K8  	  K|  	  V'       d   R
P                  V4      # R# )a  
Extract reasoning/thinking content from an assistant message.

OpenRouter and various providers can return reasoning in multiple formats:
1. message.reasoning - Direct reasoning field (DeepSeek, Qwen, etc.)
2. message.reasoning_content - Alternative field (Moonshot AI, Novita, etc.)
3. message.reasoning_details - Array of {type, summary, ...} objects (OpenRouter unified)

Args:
    assistant_message: The assistant message object from the API response
    
Returns:
    Combined reasoning text, or None if no reasoning found
	reasoningreasoning_contentreasoning_detailssummarythinkingr   r   Nr   

)<think>(.*?)</think>z<thinking>(.*?)</thinking>z<reasoning>(.*?)</reasoning>z2<REASONING_SCRATCHPAD>(.*?)</REASONING_SCRATCHPAD>)r*  r4  r   r5  r6  rO   r   r   r`   rP   r  r  r  findallr   r  )rC   assistant_messagereasoning_partsdetailr7  r   inline_patternspatternr  blockr  s   &&         rE   _extract_reasoningAIAgent._extract_reasoning\  s     $k227H7R7R7R""#4#>#>? $&9::?P?b?b?b 22/I&&'8'J'JK $&9::?P?b?b?b+==fd++ 

9- . .!::j1. .!::i0. . "::f-	  w7#A'..w7 > +Y=:gs#;#;O +		BMM1ZZFE#kkmGw7#A'..w7 G + ;;//rH   c                   < V ^8  d   QhRS[ S[,          RS[RS[S[S[S[3,          ,          RS[ S[S[S[S[3,          ,          ,          RS[S[S[3,          /# )rq   finish_reasonapprox_tokensapi_messagesconversation_historyrr   )r   rP   r   r   r   r   )rs   rn   s   "rE   rt   r.    sq     B
 B
  }	B

 B
 4S>*B
 'tDcN';<B
 
c3hB
rH   c                  V P                  V4      p\        \        VRR4      ;'       g#    \        VRR4      ;'       g    \        VRR4      4      p\        VRR4      ;'       g    RpV P                  V4      P	                  4       p	TT;'       g    R\        V4      T;'       g    R3p
V
\        V RR4      8H  p\        V RR4      p\        VR	^ 4      ;'       g    ^ p\        VR
^ 4      ;'       g    ^ p\        T;'       d(    V\        \        VR,          4      V4      8  ;'       g    \        V4      ^P8  4      p\        \        V RR4      ;'       g    R4      p\        V4      p\        VR8H  \        VRR4      VV.4      p\        V P                  ;'       d    T;'       d    T;'       d    V	'       * 4      pWn        RVRVRVRVRVRVRV/# )a  Classify think-only/empty responses so we can retry, compress, or salvage.

We intentionally do NOT short-circuit all structured-reasoning responses.
Prior discussion/PR history shows some models recover on retry. Instead we:
- compress immediately when the pattern looks like implicit context pressure
- salvage reasoning early when the same reasoning-only payload repeats
- otherwise preserve the normal retry path
r4  Nr5  r6  r   r   _last_empty_content_signaturerc  r  rs  皙?r1  lengthr  Freasoning_texthas_structured_reasoningrepeated_signatureshould_compressis_local_customis_large_session
is_resumed)rB  r   r`   r  r   r   r   rQ   r%   r   rd  rJ  )rC   r<  rE  rF  rG  rH  rM  rN  r   stripped_content	signaturerO  
compressorctx_lenrs  rR  rQ  rS  context_pressure_signalsrP  s   &&$$$$              rE    _classify_empty_content_response(AIAgent._classify_empty_content_response  s"   " 001BC#'%{D9 E E(*=tDE E(*=tD$
 
 +Y=CC33G<BBD  b)*R	
	 ''$8WY]*^^T#7>
*&6:??a":/A1EJJSS#c'C-.@BR*SS & &< 2%
 ,GD*b,I,O,ORP./
#&)
$5u= 	$
  $$ % %% %(% % %$	
 .7*n&(@ "4 0*
 	
rH   c                $   < V ^8  d   QhRS[ RR/# )rq   task_idrr   Nr   )rs   rn   s   "rE   rt   r.    s     V Vs Vt VrH   c                \    \        V4        \        V4       R#   \         d9   pT P                  '       d   \        P                  ! RT RT 24        Rp?LLRp?ii ; i  \         d@   pT P                  '       d#   \        P                  ! RT RT 24        Rp?R#  Rp?R# Rp?ii ; i)z3Clean up VM and browser resources for a given task.zFailed to cleanup VM for task : Nz#Failed to cleanup browser for task )r   r   rH  r   r   r   )rC   r\  r  s   && rE   _cleanup_task_resourcesAIAgent._cleanup_task_resources  s    	Qw	VG$	  	Q###"@	A3 OP	Q
  	V###"EgYbQRPS TUU $	Vs+    A! A.AA!B+,.B&&B+u  Review the conversation above and consider saving to memory if appropriate.

Focus on:
1. Has the user revealed things about themselves — their persona, desires, preferences, or personal details worth remembering?
2. Has the user expressed expectations about how you should behave, their work style, or ways they want you to operate?

If something stands out, save it using the memory tool. If nothing is worth saving, just say 'Nothing to save.' and stop.a  Review the conversation above and consider saving or updating a skill if appropriate.

Focus on: was a non-trivial approach used to complete a task that required trial and error, or changing course due to experiential findings along the way, or did the user expect or desire a different method or outcome?

If a relevant skill already exists, update it with what you learned. Otherwise, create a new skill if the approach is reusable.
If nothing is worth saving, just say 'Nothing to save.' and stop.u  Review the conversation above and consider two things:

**Memory**: Has the user revealed things about themselves — their persona, desires, preferences, or personal details? Has the user expressed expectations about how you should behave, their work style, or ways they want you to operate? If so, save using the memory tool.

**Skills**: Was a non-trivial approach used to complete a task that required trial and error, or changing course due to experiential findings along the way, or did the user expect or desire a different method or outcome? If a relevant skill already exists, update it. Otherwise, create a new one if the approach is reusable.

Only act if there's something genuinely worth saving. If nothing stands out, just say 'Nothing to save.' and stop.c                @   < V ^8  d   QhRS[ S[,          RS[RS[RR/# )rq   messages_snapshotreview_memoryreview_skillsrr   N)r   r   r   )rs   rn   s   "rE   rt   r.    s=     h h:h h 	h
 
hrH   c                   a aa ^ RI pV'       d   V'       d   S P                  oM!V'       d   S P                  oMS P                  oVVV 3R lpVP                  ! VRRR7      pVP                  4        R# )ax  Spawn a background thread to review the conversation for memory/skill saves.

Creates a full AIAgent fork with the same model, tools, and context as the
main session. The review prompt is appended as the next user turn in the
forked conversation. Writes directly to the shared memory/skill stores.
Never modifies the main conversation history or produces user-visible output.
Nc                    < ^ RI p ^ RIpRp \        VP                  R4      ;_uu_ 4       pV P	                  V4      ;_uu_ 4        V P                  V4      ;_uu_ 4        \        SP                  ^RSP                  SP                  R7      pSP                  Vn
        SP                  Vn        SP                  Vn        ^ Vn        ^ Vn        VP                  SSR7       RRR4       RRR4       RRR4       . p\!        VR. 4       EF  p\#        V\$        4      '       d   VP'                  R4      R8w  d   K2   \(        P*                  ! VP'                  R	R
4      4      pTP'                  R4      '       g   Kr  TP'                  RR4      pTP'                  RR4      pRTP1                  4       9   d   TP3                  T4       K  RTP1                  4       9   d   TP3                  T4       K  RTP1                  4       9   g   T'       dA   RTP1                  4       9   d,   TR8X  d   RM
TR8X  d   RMTp	TP3                  T	 R24       EKC  RT9   d,   TR8X  d   RM
TR8X  d   RMTp	TP3                  T	 R24       EKu  RTP1                  4       9   g   RTP1                  4       9   g   EK  TR8X  d   RM
TR8X  d   RMTp	TP3                  T	 R24       EK  	  V'       dY   RP5                  \$        P7                  V4      4      p
SP9                  RV
 24       SP:                  pV'       d    V! RV
 24       Te2   \!        TRR4      pTe    TPC                  TR RR!7       RTn"        R# R# R#   + '       g   i     EL; i  + '       g   i     EL; i  + '       g   i     EL; i  \(        P,                  \.        3 d     EK  i ; i  \<         d     Li ; i  \<         d!   p\>        PA                  RT4        Rp?LRp?ii ; i  \<         d     R# i ; i  TeA   \!        TRR4      pTe/    TPC                  TR RR!7       RTn"        i   \<         d     i i ; ii i ; i)"rK   Nr  T)rB  rC  rI  ra  r<  )r  rH  r>  r   r   r   {}successr  r   r|  createdupdatedaddedr`  r  MemoryuserzUser profilez updatedzEntry addedremovedreplacedu    · u     💾 u   💾 z)Background memory/skill review failed: %sr%  bg_review_doner  )#
contextlibr   r  devnullredirect_stdoutredirect_stderrr,  rB  ra  r<  rJ  rK  rL  rM  ra  run_conversationr`   rO   r   r   r   r   r   r   r7  r   r  fromkeysr  r  r   r  r   _close_openai_clientr%  )rq  _osreview_agent_devnullactionsr   rR   r  r|  labelr7  _bg_cbr  r%  rb  promptrC   s                 rE   _run_review5AIAgent._spawn_background_review.<locals>._run_review-  s   (LK!#++s++x//99//99#*"jj'(#'!%!%$L 261C1CL.373G3GL09=9S9SL6:;L79:L6 11%+-> 2  : : ,. "<1DbIC%c400CGGFOv4M !#zz#'')T*BC  88I.. "hhy"5G!XXh3F GMMO3w/"gmmo5w/ GMMO35GMMOC[,2h,>V\`fVfNlr%'9:&'1,2h,>V\`fVfNlr%'9:"gmmo5w}}9V,2h,>V\`fVfNlr%'9:/ J2 $kk$--*@AG$$wwi%89!<<F!"U7)#45  +$\8TBF)!(== &/? >  37L/ * , :99 :99 ,++: !00)< ! !6  ) ! !  MH!LLM  ) ! !  +$\8TBF)!(== &/? >  37L/( ! ! * ,s  O NN	BM/"N	*N2A	O <&N+"O 9BO BO +4O  AO -O P /N :	N	N	NN(	"	O +OO 
OO OO P OO P
*P P P

P PPQ%6QQ%Q Q%Q  Q%Tz	bg-review)r|  r}  ra   )r   _COMBINED_REVIEW_PROMPT_MEMORY_REVIEW_PROMPT_SKILL_REVIEW_PROMPTr  r  )rC   rb  rc  rd  r   r  tr~  s   ff&&   @rE   _spawn_background_review AIAgent._spawn_background_review  sY     	 ]11F//F..FN	!` K;O		rH   c                4   < V ^8  d   QhRS[ S[,          RR/# r   r   r   )rs   rn   s   "rE   rt   r.    s     * *T$Z *D *rH   c                   \        V RR4      p\        V RR4      pVe   Vf   R# ^ Tu;8:  d   \        V4      8  dC   M R# W,          p\        V\        4      '       d   VP	                  R4      R8X  d   W4R&   R# R# R# R# )am  Rewrite the current-turn user message before persistence/return.

Some call paths need an API-only user-message variant without letting
that synthetic text leak into persisted transcripts or resumed session
history. When an override is configured for the active turn, mutate the
in-memory messages list in place so both persistence and returned
history stay clean.
r  Nr  r   rm  r   )r`   rQ   rO   r   r   )rC   r   idxoverrider   s   &&   rE   $_apply_persist_user_message_override,AIAgent._apply_persist_user_message_override  s{     d7>4!A4Hs{#c(m##-C#t$$F)B!)I *C$ $rH   c                F   < V ^8  d   QhRS[ S[,          RS[ S[,          /# rq   r   rH  r  )rs   rn   s   "rE   rt   r.    s(     K Kd K4PT: KrH   c                    V P                   '       g   R# V P                  V4       Wn        V P                  V4       V P	                  W4       R# )zSave session state to both JSON log and SQLite on any exit path.

Ensures conversations are never lost, even on errors or early returns.
Skipped when ``persist_session=False`` (ephemeral helper flows).
N)rj  r  r>  _save_session_log_flush_messages_to_session_db)rC   r   rH  s   &&&rE   _persist_sessionAIAgent._persist_session  sC     ###11(;!)x(**8JrH   c                F   < V ^8  d   QhRS[ S[,          RS[ S[,          /# r  r  )rs   rn   s   "rE   rt   r.    s*     .F .Fd4j .FX\]aXb .FrH   c                   V P                   '       g   R# V P                  V4        V P                   P                  V P                  V P                  ;'       g    RV P
                  R7       V'       d   \        V4      M^ p\        W0P                  4      pWR  EFg  pVP                  RR4      pVP                  R4      pRp\        VR4      '       d[   VP                  '       dI   VP                   U	u. uF1  p	RV	P                  P                  R	V	P                  P                  /NK3  	  pp	M.\        VP                  R4      \         4      '       d
   VR,          pV P                   P#                  V P                  TTVP                  R
4      TVP                  R4      VP                  R4      VR8X  d   VP                  R4      MRVR8X  d   VP                  R4      MRVR8X  d   VP                  R4      MRR7
       EKj  	  \        V4      V n        R# u up	i   \$         d"   p
\&        P)                  RT
4        Rp
?
R# Rp
?
ii ; i)u  Persist any un-flushed messages to the SQLite session store.

Uses _last_flushed_db_idx to track which messages have already been
written, so repeated calls (from multiple exit paths) only write
truly new messages — preventing the duplicate-write bug (#860).
Nr  )r  rB  r   r  r   r   ra   r   r   tool_call_idrE  	assistantr4  r6  codex_reasoning_items)
rS  r   r   r   r   r  rE  r4  r6  r  z$Session DB append_message failed: %s)rB  r  ensure_sessionrS  ra  rB  rQ   r   rD  r   r*  r   r   ra   r   rO   r   append_messager   r  r   )rC   r   rH  	start_idx
flush_fromr   r   r   tool_calls_datar   r  s   &&&        rE   r  %AIAgent._flush_messages_to_session_db  s    11(;$	F ++}}--jj , 
 6J01qIY(A(ABJ,wwvy1''),"&3--#... #&..'"0B  !1!1;@U@UV"0 $ 'O   5t<<&),&7O  //##!ggk2.!$!8"%''/":6:k6Icggk2tFJkFYcgg.A&B_cNRVaNa#''2I*Jgk 0  -. ),HD%%'&  	FNNA1EE	Fs=   2H H 5A2H (H 67H-C*H H I
)II
c                F   < V ^8  d   QhRS[ S[,          RS[ S[,          /# r   r  )rs   rn   s   "rE   rt   r.    s#     - -4: -$t* -rH   c                    V'       g   . # Rp\        \        V4      ^,
          RR4       F#  pW,          P                  R4      R8X  g   K!  Tp M	  Vf   VP                  4       # VRV # )am  
Get messages up to (but not including) the last assistant turn.

This is used when we need to "roll back" to the last successful point
in the conversation, typically when the final assistant message is
incomplete or malformed.

Args:
    messages: Full message list
    
Returns:
    Messages up to the last complete assistant turn (ending with user/tool message)
Nr   r  )rangerQ   r   copy)rC   r   last_assistant_idxis   &&  rE   "_get_messages_up_to_last_assistant*AIAgent._get_messages_up_to_last_assistant  sq     I "s8}q("b1A{v&+5%&" 2
 %==?" ++,,rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     ? ?# ?rH   c           
        V P                   '       g   R# . pV P                    FN  pVR,          pRVR,          RVP                  RR4      RVP                  R/ 4      RR/pVP                  V4       KP  	  \        P                  ! VR	R
7      # )z
Format tool definitions for the system message in the trajectory format.

Returns:
    str: JSON string representation of tool definitions
z[]r   ra   descriptionr   
parametersrequiredNFr   )r  r   r   r   r   )rC   formatted_toolsr   funcformatted_tools   &    rE    _format_tools_for_system_message(AIAgent._format_tools_for_system_message  s     zzz JJD
#DVtxxr:dhh|R8D	N "">2  zz/>>rH   c                ~   < V ^8  d   QhRS[ S[S[S[3,          ,          RS[RS[RS[ S[S[S[3,          ,          /# )rq   r   
user_query	completedrr   r   r   rP   r   r   )rs   rn   s   "rE   rt   r.    sa     c cd4S>6J cX[ chl cquvz{~  AD  |D  wE  rF crH   c           	     B	   . pRV P                  4        R2pVP                  RRRV/4       VP                  RRRV/4       ^pV\        V4      8  Ed   W,          pVR,          R8X  Ed   R	V9   Ed   VR	,          '       Ed   R
pVP                  R4      '       d+   VR,          P	                  4       '       d   RVR,           R2pVP                  R4      '       d>   VR,          P	                  4       '       d!   V\        VR,          4      R,           ,          pVR	,           F  p	V	'       d   \        V	\        4      '       g   K#   \        V	R,          R,          \        4      '       d%   \        P                  ! V	R,          R,          4      MV	R,          R,          p
RV	R,          R,          RV
/pVR\        P                  ! VRR7       R2,          pK  	  RV9  d
   RV,           pVP                  RRRVP                  4       /4       . pV^,           pV\        V4      8  Ed   W,          R,          R8X  d   W,          pRpVR,          p VP	                  4       P!                  R"4      '       d   \        P                  ! V4      p\        T4      pT\        TR	,          4      8  d   TR	,          T,          R,          R,          MRpT\        P                  ! RTP                  RR
4      RTRT/RR7      ,          pTR ,          pTP                  T4       T^,          pEK  V'       d.   VP                  RRRRP%                  V4      /4       V^,
          pMR
pVP                  R4      '       d+   VR,          P	                  4       '       d   RVR,           R2pVR,          ;'       g    R
pV\        V4      ,          pRV9  d
   RV,           pVP                  RRRVP	                  4       /4       M*VR,          R!8X  d   VP                  RRRVR,          /4       V^,          pEK  V#   \        P                   d5    \        P                  ! RT	R,          R,          R,           24       / p
 ELi ; i  \        P                  \"        3 d     ELi ; i)#a)  
Convert internal message format to trajectory format for saving.

Args:
    messages (List[Dict]): Internal message history
    user_query (str): Original user query
    completed (bool): Whether the conversation completed successfully
    
Returns:
    List[Dict]: Messages in trajectory format
a  You are a function calling AI model. You are provided with function signatures within <tools> </tools> XML tags. You may call one or more functions to assist with the user query. If available tools are not relevant in assisting with user query, just respond in natural conversational language. Don't make assumptions about what values to plug into functions. After calling & executing the functions, you will be provided with function results within <tool_response> </tool_response> XML tags. Here are the available tools:
<tools>
a  
</tools>
For each function call return a JSON object, with the following pydantic model json schema for each:
{'title': 'FunctionCall', 'type': 'object', 'properties': {'name': {'title': 'Name', 'type': 'string'}, 'arguments': {'title': 'Arguments', 'type': 'object'}}, 'required': ['name', 'arguments']}
Each function call should be enclosed within <tool_call> </tool_call> XML tags.
Example:
<tool_call>
{'name': <function-name>,'arguments': <args-dict>}
</tool_call>fromsystemr4  humanr   r  r   r   r4  z<think>
z

</think>
r   
r   r   z2Unexpected invalid JSON in trajectory conversion: Nd   Nra   z<tool_call>
Fr   z
</tool_call>
<think>z<think>
</think>
gptr   z<tool_response>
r  r  z
</tool_response>rm  ){[)r  r   rQ   r   r   r8   rO   r   rP   r   r   r   r   r   r   r  
startswithr  r  )rC   r   r  r  
trajectory
system_msgr  r   r   r   r   tool_call_jsonr  jtool_msgtool_responsetool_content
tool_indexr   raw_contents   &&&&                rE   _convert_to_trajectory_format%AIAgent._convert_to_trajectory_format  s    

 ==?@ Af
f 	 	HZ
 	 	GZ
 	 #h-+C6{k)3&3|+<+< !G ww{++K0@0F0F0H0H$-c+.>-?|"Lwwy))c)n.B.B.D.D  #>s9~#NQU#UU &)%6%6	(
9d0K0KX+Zdenoyez  |G  fH  JM  [N  [N

9Z3H3U(V  T]  ^h  Ti  ju  TvI #Ij$9&$A'*  ]4::n[`3a2bbr#ss! &7( !/"7'"A%%!1'  &(NAAc(m+F0Cv0M#+;(; (0	':!+113>>zJJ/3zz,/G &)%8
  *CL0A,BB  -j9*EfM!* "
 &*HLL,L"I%|5 ).	*/ /
 &)==&--m<Q &"))"F#TYY~%>+  E
 !G ww{++K0@0F0F0H0H$-c+.>-?|"L #&i."6"6BK:;GGG !/"7'"A%%' 
 V&!!GS^# 
 FAy  $33 + $OO.`ajkuav  xC  bD  EI  bJ  aK  -L  M(*I	+F !% 4 4nE ! !s&   AP3;Q? 3AQ<;Q<?RRc                R   < V ^8  d   QhRS[ S[S[S[3,          ,          RS[RS[/# )rq   r   r  r  r  )rs   rn   s   "rE   rt   r.    s5     D Dd38n)= D3 D[_ DrH   c                ~    V P                   '       g   R# V P                  WV4      p\        W@P                  V4       R# )z
Save conversation trajectory to JSONL file.

Args:
    messages (List[Dict]): Complete message history
    user_query (str): Original user query
    completed (bool): Whether the conversation completed successfully
N)rG  r  _save_trajectory_to_filerB  )rC   r   r  r  r  s   &&&& rE   _save_trajectoryAIAgent._save_trajectory  s3     %%%77iX
 ZZCrH   c                &   < V ^8  d   QhRS[ RS[/# rq   errorrr   )r   rP   )rs   rn   s   "rE   rt   r.    s     && &&I &&# &&rH   c                   ^ RI p\        V 4      pRV9   g   RV9   d   VP                  RW!P                  4      pV'       d    VP	                  ^4      P                  4       MRpVP                  RV4      pV'       d    VP	                  ^4      P                  4       MRp\        V RR4      p. pV'       d   VP                  RV 24       VP                  V4       V'       d   VP                  R	V 24       R
P                  V4      # \        V RR4      p	\        V	\        4      '       d   \        V	P                  R4      \        4      '       d"   V	P                  R/ 4      P                  R4      MV	P                  R4      p
V
'       d+   \        V RR4      pV'       d   RV R2MRpV V
R,           2# \        V RR4      pV'       d   RV R2MRpV VR,           2# )zExtract a human-readable one-liner from an API error.

Handles Cloudflare HTML error pages (502, 503, etc.) by pulling the
<title> tag instead of dumping raw HTML.  Falls back to a truncated
str(error) for everything else.
Nz	<!DOCTYPE<htmlz<title[^>]*>([^<]+)</title>z!HTML error page (title not found)z2Cloudflare Ray ID:\s*<strong[^>]*>([^<]+)</strong>status_codezHTTP zRay u    — bodyr  r  r^  r   Ni,  NNi  N)r  rP   r   r  groupr   r`   r   r  rO   r   r   )r  _rerawmtitlerayray_idr  r   r  r   prefixs   &           rE   _summarize_api_errorAIAgent._summarize_api_error  s    	%j #C

93OA*+AGGAJ$$&1TE**RTWXC-0SYYq\'')dF!%=KEu[M23LLtF8_-<<&& ufd+dD!!:DTXXgEVX\:]:]$((7B'++I6cgckcklucvC%e]DA4?5R0R #d)-- e]D9,75R(R#d)%%rH   c                F   < V ^8  d   QhRS[ S[,          RS[ S[,          /# )rq   keyrr   r2  )rs   rn   s   "rE   rt   r.    s#     ) )(3- )HSM )rH   c                \    V'       g   R # \        V4      ^8:  d   R# VR,           RVRR   2# )Nz***r  r  r  rQ   )rC   r  s   &&rE   _mask_api_key_for_logsAIAgent._mask_api_key_for_logs  s1    s8r>b'#c"#hZ((rH   c                &   < V ^8  d   QhRS[ RS[ /# )rq   	error_msgrr   r   )rs   rn   s   "rE   rt   r.    s      c c rH   c                    V'       g   R# VP                  4       P                  R4      '       g   RV9   d   R# RP                  VP                  4       4      p\	        V4      ^8  d   VR,          R,           pV# )z
Clean up error messages for user display, removing HTML content and truncating.

Args:
    error_msg: Raw error message from API or exception
    
Returns:
    Clean, user-friendly error message
zUnknown errorz<!DOCTYPE htmlr  z:Service temporarily unavailable (HTML error page returned)rn  :N   Nr  )r   r  r  splitrQ   )rC   r  r  s   && rE   _clean_error_messageAIAgent._clean_error_message  sg     " ??''(899W	=QO ((9??,- w<#dme+GrH   c                <   < V ^8  d   QhRS[ RS[S[S[3,          /# r  )r   r   rP   r   )rs   rn   s   "rE   rt   r.  	  s#     > >) >S#X >rH   c                   / p\        V RR4      pRp\        V\        4      '       d9   \        VP                  R4      \        4      '       d   VP                  R4      MTp\        V\        4      '       EdB   VP                  R4      ;'       g    VP                  R4      p\        V\        4      '       d*   VP                  4       '       d   VP                  4       VR&   VP                  R4      ;'       g    VP                  R4      p\        V\        4      '       d*   VP                  4       '       d   VP                  4       VR&   R F!  pVP                  V4      pVR9  g   K  WqR&    M	  VP                  R
4      pVR9  d1   RV9  d*    \        P                  ! 4       \        V4      ,           VR&   \        V RR4      p	\        V	RR4      p
V
'       d   V
P                  R4      ;'       g    V
P                  R4      pV'       d1   RV9  d*    \        P                  ! 4       \        V4      ,           VR&   V
P                  R4      pV'       d   RV9  d   WR&   RV9  d.   \	        V 4      P                  4       pV'       d   VR,          VR&   RV9  Ed/   VP                  R4      ;'       g    R	p\        V\        4      '       d   \        P                  ! RV\        P                  4      pV'       dk   \        VP                  ^4      4      pVP                  ^4      P                  4       R8X  d
   VR,          MTp\        P                  ! 4       V,           VR&   V# \        P                  ! RV\        P                  4      pV'       d8   \        P                  ! 4       \        VP                  ^4      4      ,           VR&   V#   \        \        3 d     EL(i ; i  \        \        3 d     ELi ; i)z;Extract structured rate-limit details from provider errors.r  Nr  coder  r  error_descriptionreset_atr   retry_afterresponser  retry-afterRetry-Afterzx-ratelimit-resetr  z/quotaResetDelay[:\s\"]+(\\d+(?:\\.\\d+)?)(ms|s)msg     @@z?retry\s+(?:after\s+)?(\d+(?:\.\d+)?)\s*(?:sec|secs|seconds|s\b))	resets_atr  )Nr   )r`   rO   r   r   rP   r   r  rk  r   rN   r  r   r  r  r7  )r  contextr  payloadr  r  r  r4  r  r  r  ratelimit_resetraw_messagedelay_matchseconds	sec_matchs   &               rE   _extract_api_error_context"AIAgent._extract_api_error_context	  s)    #%ufd+dD!!+5dhhw6G+N+Ndhhw'TXGgt$$[[(@@GKK,@F&#&&6<<>>$*LLN!kk),PP<O0PG'3''GMMOO%,]]_	"0C(
**/J'	 1
 "++m4K*,71J*.))+k8J*JGJ' 5*d3(It4!++m4RRM8RKz8*.))+k8J*JGJ' &kk*=>O:W#<&5
#G#e***,K%0%6	"W$kk),22G'3'' ii(Z\cegerers!+"3"3A"67E0;0A0A!0D0J0J0LPT0TefnZ_G*.))+*?GJ'  !#		Z!I
 !.2iikE)//RSBT<U.U
+M ":.  ":. s$   (O (O$ O! O!$O98O9c                L   < V ^8  d   QhRS[ RS[S[S[S[ 3,          ,          /# rq   r  rr   )r   r   r   rP   )rs   rn   s   "rE   rt   r.  E	  s+      C HTRUWZRZ^D\ rH   c                    Vf   R# \        VRR4      pV'       g   R# ^ RIHp \        W P                  V P
                  R7      pV! V4      pVP                  RR4       VP                  VR&   VP                  VR&   V# )zLToken buckets for ``post_api_request`` plugins (no raw ``response`` object).Nusage)asdictr<  r=  	raw_usageprompt_tokenstotal_tokens)	r`   dataclassesr  r2   r<  r=  popr  r  )rC   r  r  r  cur7  s   &&    rE   #_usage_summary_for_api_request_hook+AIAgent._usage_summary_for_api_request_hookE	  sp    Hgt4	&YW*K&#%#3#3 "$//rH   r  c          	      h   < V ^8  d   QhRS[ S[S[3,          RS[RS[S[,          RS[S[,          /# )rq   
api_kwargsr  r  rr   )r   rP   r   r   r   r	   )rs   rn   s   "rE   rt   r.  U	  sJ     P PcNP 	P
 	"P 
$PrH   c                   \         P                  ! V4      pVP                  RR4       VP                  4        UUu/ uF  w  rVVf   K  WVbK  	  pppRp \	        V P
                  RR4      pR\        P                  ! 4       P                  4       RV P                  RTRR	R
RV P                  P                  R4       V P                  R8X  d   RMR 2RRRV P!                  V4       2RR/RV//p	Ve   R\#        V4      P$                  R\'        V4      /p
R) F  p\	        W;R4      pVf   K  WV&   K  	  \	        VRR4      pVe   WR&   \	        VRR4      pVe!    \	        VRR4      V
R&   VP(                  V
R&   WR&   \        P                  ! 4       P+                  R4      pV P,                  RV P                   R V R!2,          pVP/                  \0        P2                  ! V	R"^\&        R#7      R$R%7       V P5                  V P6                   R&V 24       \9        R'4      '       d(   \;        \0        P2                  ! V	R"^\&        R#7      4       V# u uppi   \         d"   p\        P                  RT4        Rp?ELRp?ii ; i  \         d"   p\        P                  RT4        Rp?EL1Rp?ii ; i  \         d7   pT P<                  '       d   \>        P@                  ! R(T 24        Rp?R# Rp?ii ; i)*z
Dump a debug-friendly HTTP request record for the active inference API.

Captures the request body from api_kwargs (excluding transport-only keys
like timeout). Intended for debugging provider-side 4xx failures where
retries are not useful.
timeoutNr;  z,Could not extract API key for debug dump: %sr#  rS  r  requestmethodPOSTr  ru  rp  z
/responsesz/chat/completionsr  AuthorizationzBearer zContent-Typezapplication/jsonr  r   r  r  r  response_statusresponse_textz,Could not extract error response details: %sr  r  request_dump_r  r  F)r   indentdefaultr  r  u$   🧾 Request debug dump written to: HERMES_DUMP_REQUEST_STDOUTz*Failed to dump API request debug payload: )r  
request_idr  paramr   )!r  deepcopyr  r6  r`   r%  r   r  r   r   r  	isoformatrS  r1  r  r=  r  r   re   rP   r   r  r;  
write_textr   r   r  rL  r<   r'  rH  r   r   )rC   r  r  r  r  kvr;  r  dump_payload
error_info	attr_name
attr_value	body_attrresponse_objr#  	dump_file
dump_errors   &&$$              rE   _dump_api_request_debugAIAgent._dump_api_request_debugU	  s   B	==,DHHY%%)ZZ\C\TQQDAD\DCGP!$++y$?
 X\\^557doo&fdmm22378ZkIk  rE  9F  G'743N3Nw3W2X)Y&(:  D	,L  DK00s5z.
 "XI!(4!@J!-0:9- "X
 $E648	()2v&&uj$?+X8?m]a8b
#456B6G6G
?3 )3W% //0BCI-7H)TY(ZZI  

<eAsS  ! 
 LLDOO,,PQZP[\];<<djjE!UXYZw D
  PKQOOPJ % X%SUVWWX$  	###"LZL YZ	s   ;J4 I
IJ4 I -B;J4 -.J4 J ;CJ4 J4 J!I=7J4 =JJ4 J1J,&J4 ,J11J4 4K5?+K00K5c                &   < V ^8  d   QhRS[ RS[ /# r  r   )rs   rn   s   "rE   rt   r.  	  s        rH   c                    V '       g   V # \        V 4      p \        P                  ! RRV 4      p \        P                  ! RRV 4      p V P                  4       # )zCConvert REASONING_SCRATCHPAD to think tags and clean up whitespace.z\n+(<think>)z\n\1z(</think>)\n+z\1\n)r8   r  r   r   )r   s   &rE   _clean_session_contentAIAgent._clean_session_content	  sG     N-g6&&'7;&&)7G<}}rH   c                F   < V ^8  d   QhRS[ S[S[S[3,          ,          /# )rq   r   r   r   rP   r   )rs   rn   s   "rE   rt   r.  	  s'     @D @D$tCH~*> @DrH   c                   T;'       g    V P                   pV'       g   R#  . pV Fg  pVP                  R4      R8X  d>   VP                  R4      '       d'   \        V4      pV P                  VR,          4      VR&   VP	                  V4       Ki  	  V P
                  P                  4       '       d    \        P                  ! V P
                  P                  RR7      4      pVP                  R\        VP                  R. 4      4      4      pV\        V4      8  d$   \        P                  ! R	V\        V4      4       R#  R
V P                  RV P                  RV P                   RV P"                  RV P$                  P'                  4       R\(        P*                  ! 4       P'                  4       RV P,                  ;'       g    RRV P.                  ;'       g    . R\        V4      RV/
p\1        V P
                  V^\2        R7       R#   \         d     Li ; i  \         d=   pT P4                  '       d    \        P6                  ! RT 24        Rp?R#  Rp?R# Rp?ii ; i)a  
Save the full raw session to a JSON file.

Stores every message exactly as the agent sees it: user messages,
assistant messages (with reasoning, finish_reason, tool_calls),
tool responses (with tool_call_id, tool_name), and injected system
messages (compression summaries, todo snapshots, etc.).

REASONING_SCRATCHPAD tags are converted to <think> blocks for consistency.
Overwritten after each turn so it always reflects the latest state.
Nr   r  r   r  r  message_countr   zHSkipping session log overwrite: existing has %d messages, current has %drS  rB  r1  ra  r7  last_updatedsystem_promptr   r  )r   r!  zFailed to save session log: )r>  r   r   r6  r   r=  existsr   r   	read_textrQ   r   r   r   rS  rB  r1  ra  r7  r&  r   r  r?  r  r;   rP   rH  r   )rC   r   r  r   r   existing_countentryr  s   &&      rE   r  AIAgent._save_session_log	  s    55t550	DG776?k1cggi6H6Hs)C%)%@%@Y%PC	Ns#	   $$++--
#zz$*?*?*I*ISZ*I*[\H%-\\/3x||T^`bGcCd%eN%G4f*CL  5 dooDMMDMM!3!3!=!=!? 8 8 :!;!;!A!Ar))rWGE %%	! ! .  	D###">qc BCC $	DsP   3H AH 2BH  BH H .H HH HH I $+II c                $   < V ^8  d   QhRS[ RR/# r  r   )rs   rn   s   "rE   rt   r.  	  s     %V %V %V %VrH   c                   RV n         Wn        \        R4       V P                  ;_uu_ 4        \	        V P
                  4      pRRR4       X F  p VP                  V4       K  	  V P                  '       gH   \        RV'       d   \        V4      ^(8  d   RVR,           R2MV'       d   RV R2MR	,           4       R# R#   + '       g   i     L; i  \         d"   p\        P                  RT4        Rp?K  Rp?ii ; i)
a  
Request the agent to interrupt its current tool-calling loop.

Call this from another thread (e.g., input handler, message receiver)
to gracefully stop the agent and process a new message.

Also signals long-running tool executions (e.g. terminal commands)
to terminate early, so the agent can respond immediately.

Args:
    message: Optional new message that triggered the interrupt.
             If provided, the agent will include this in its response context.

Example (CLI):
    # In a separate input thread:
    if user_typed_something:
        agent.interrupt(user_input)

Example (Messaging):
    # When new message arrives for active session:
    if session_has_running_agent:
        running_agent.interrupt(new_message.text)
TNz0Failed to propagate interrupt to child agent: %su   
⚡ Interrupt requestedz: 'r  z...''r   )r  r  _set_interruptr	  r   r  	interruptr   r  r   rI  r'  rQ   )rC   r  children_copychildr  s   &&   rE   rG  AIAgent.interrupt	  s    0 %)!")t''' !6!67M ("ET( #
 -WY\]dYehjYj3ws|nD1I  ELruv}u~~  qA  RT  U  V  ('
  TOQRSSTs#   CCC	D C;;D c                   < V ^8  d   QhRR/# rp   rd   )rs   rn   s   "rE   rt   r.  
  s       rH   c                8    RV n         RV n        \        R4       R# )zIClear any pending interrupt request and the global tool interrupt signal.FN)r  r  rF  rW   s   &rE   clear_interruptAIAgent.clear_interrupt
  s    $)!"&urH   c                $   < V ^8  d   QhRS[ RR/# )rq   descrr   Nr   )rs   rn   s   "rE   rt   r.   
  s     ( (C (D (rH   c                F    \         P                   ! 4       V n        Wn        R# )zAUpdate the last-activity timestamp and description (thread-safe).N)r  r  r  )rC   rP  s   &&rE   _touch_activityAIAgent._touch_activity 
  s    !%#' rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  %
  s     
 
d 
rH   c                :   \         P                   ! 4       V P                  ,
          pRV P                  RV P                  R\        V^4      RV P                  RV P
                  RV P                  RV P                  P                  RV P                  P                  /# )	zReturn a snapshot of the agent's current activity for diagnostics.

Called by the gateway timeout handler to report what the agent was doing
when it was killed, and by the periodic "still working" notifications.
last_activity_tslast_activity_descseconds_since_activitycurrent_toolapi_call_countrC  budget_used
budget_max)
r  r  r  roundr  r  rC  re  r   r   )rC   elapseds   & rE   get_activity_summaryAIAgent.get_activity_summary%
  s     ))+ 6 66 6 6 $":":$eGQ&7D..d22d1140055$//99	
 		
rH   c                $   < V ^8  d   QhRS[ RR/# r   r   )rs   rn   s   "rE   rt   r.  7
  s        rH   c                    V P                   '       dD    V P                   P                  T;'       g    . 4        V P                   P                  4        R# R#   \         d     L,i ; i  \         d     R# i ; i)u   Shut down the memory provider — call at actual session boundaries.

This calls on_session_end() then shutdown_all() on the memory
manager. NOT called per-turn — only at CLI exit, /reset, gateway
session expiry, etc.
N)rS  on_session_endr   shutdown_all)rC   r   s   &&rE   shutdown_memory_provider AIAgent.shutdown_memory_provider7
  sr     $$33HNNC$$113      s'   A A A) A&%A&)A87A8c                J   < V ^8  d   QhRS[ S[S[S[3,          ,          RR/# )rq   historyrr   Nr9  )rs   rn   s   "rE   rt   r.  H
  s(      4S#X+? D rH   c                B   Rp\        V4       F~  pVP                  R4      R8w  d   K  VP                  RR4      pRV9  d   K6   \        P                  ! V4      pRV9   d+   \	        VR,          \
        4      '       d   VR,          p MK~  K  	  V'       dZ   V P                  P                  VRR	7       V P                  '       g+   V P                  V P                   R
\        V4       R24       \        R4       R#   \        P                  \        3 d     EK  i ; i)z
Recover todo state from conversation history.

The gateway creates a fresh AIAgent per message, so the in-memory
TodoStore is empty. We scan the history for the most recent todo
tool response and replay it to reconstruct the state.
Nr   r   r   r   z"todos"todosF)mergeu   📋 Restored z todo item(s) from history)reversedr   r   r   rO   r   r   r   rH  rL   rI  r  rL  rQ   rF  )rC   ri  last_todo_responser   r   rR   s   &&    rE   _hydrate_todo_storeAIAgent._hydrate_todo_storeH
  s     "G$Cwwv&(ggi,G'zz'*d?z$w-'F'F)-g& (G? % ""#5U"C???0sCU?V>WWqrsu (()4 s   AC>>DDc                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  i
  s     ) ) )rH   c                    V P                   # )z)Check if an interrupt has been requested.)r  rW   s   &rE   is_interruptedAIAgent.is_interruptedh
  s     (((rH   c                &   < V ^8  d   QhRS[ RS[ /# )rq   system_messagerr   r   )rs   rn   s   "rE   rt   r.  v
  s     l) l)3 l)# l)rH   c                z  a a RpS P                   '       g   \        4       pV'       d   V.pRpV'       g1    RpT'       d   \        P                  ! RRT 2^4      pM\        pT.p. pRS P                  9   d   VP                  \        4       RS P                  9   d   VP                  \        4       RS P                  9   d   VP                  \        4       V'       d!   XP                  R	P                  V4      4       \        S P                  4      pV'       d   XP                  V4       S P                  '       Ed   S P                  p	Rp
V	RJ g,   \        V	\        4      '       d   V	P                  4       R#9   d   Rp
EMV	RJ g,   \        V	\        4      '       d   V	P                  4       R$9   d   Rp
M\        V	\        4      '       d`   S P                   ;'       g    R
P                  4       o\"        ;QJ d    V3R lV	 4       F  '       g   K   RM	  RM! V3R lV	 4       4      p
MfS P                   ;'       g    R
P                  4       o\"        ;QJ d#    V3R l\$         4       F  '       g   K   RM	  RM! V3R l\$         4       4      p
V
'       d   XP                  \&        4       S P                   ;'       g    R
P                  4       pRV9   g   RV9   d   VP                  \(        4       RV9   g   RV9   d   VP                  \*        4       Ve   XP                  V4       S P,                  '       d   S P.                  '       d5   S P,                  P1                  R4      pV'       d   XP                  V4       S P2                  '       d5   S P,                  P1                  R4      pV'       d   XP                  V4       S P4                  '       d5    S P4                  P7                  4       pV'       d   XP                  V4       \"        ;QJ d    V 3R lR% 4       F  '       g   K   RM	  RM! V 3R lR% 4       4      pV'       dE   R S P                   4        Uu0 uF  pV'       g   K  VkK  	  pp\;        S P                  VR7      pMR
pV'       d   XP                  V4       S P                   '       gG   \<        P>                  ! R4      ;'       g    Rp\A        VVR7      pV'       d   XP                  V4       ^ RI!H"p V! 4       pRVPG                  R4       2pS PH                  '       d)   S PJ                  '       d   VRS PJ                   2,          pS P                   '       d   VRS P                    2,          pS PL                  '       d   VRS PL                   2,          pXP                  V4       S PL                  R8X  db   RS P                   9   d#   S P                   PO                  R4      R&,          MS P                   pVP                  RV R S P                    R!24       S PP                  ;'       g    R
P                  4       PS                  4       pV\T        9   d   VP                  \T        V,          4       R"P                  V4      #   \8         d     ELi ; iu upi )'a  
Assemble the full system prompt from all layers.

Called once per session (cached on self._cached_system_prompt) and only
rebuilt after context compression events. This ensures the system prompt
is stable across all turns in a session, maximizing prefix cache hits.
FTNzYou are Hermes AgentzYou are r  session_searchskill_managern  r   c              3   z   <"   T F0  p\        V\        4      '       g   K  VP                  4       S9   x  K2  	  R # 5irU   )rO   rP   r7  r   pmodel_lowers   & rE   r   /AIAgent._build_system_prompt.<locals>.<genexpr>
  s*     _1JWXZ]L^6aggi;6s   ;;c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   r{  s   & rE   r   r~  
  s     T8S1;.8Sr  geminigemmar  codexrm  c              3   @   <"   T F  qSP                   9   x  K  	  R # 5irU   )r4  )r   ra   rC   s   & rE   r   r~  
  s     wIvt'<'<<Ivs   c              3   8   "   T F  p\        V4      x  K  	  R # 5irU   )r   )r   r   s   & rE   r   r~  
  s       EZ	(33EZ   )available_toolsavailable_toolsetsr  )r   	skip_soul)r  zConversation started: z%A, %B %d, %Y %I:%M %pz
Session ID: z
Model: z
Provider: alibabaru  z#You are powered by the model named z. The exact model ID is zt. When asked what model you are, always answer based on this information, not on any model name returned by the API.r9  )r  alwaysr  on)falsenevernooff)skills_list
skill_viewry  r  )+rb  r+   r   replacer4  r   r   r   r   r  r   rb  rO   rP   r7  r   rB  r   r-   r,   r/   r0   rJ  rK  format_for_system_promptrL  rS  build_system_promptr   r)   r   r-  r*   hermes_timer  r  ri  rS  r<  r  ra  r   r   )rC   rv  _soul_loaded_soul_contentprompt_parts_ai_peer_name	_identitytool_guidancenous_subscription_prompt_enforce_inject_model_lower	mem_block
user_block_ext_mem_blockhas_skills_toolstoolsetavail_toolsetsskills_prompt_context_cwdcontext_files_prompt_hermes_nowr  timestamp_line_model_shortplatform_keyr}  s   f&                        @rE   _build_system_promptAIAgent._build_system_promptv
  sc   $ &&&(NM -#  
 2::*}o.	 3	%;L t,,,  1t444  !89T222  1 78#A$BWBW#X # 89    11HG4Jx$=$=(..BRVuBuU"z(C'@'@X^^EUYxExHd++#zz//R668#__###___  $zz//R668#T8ST###T8STT##$AB $

 0 0b779 |+w,/F ''(IJ L(G|,C ''(GH %/### ..GGQ	 ''	2)))!//HHP
 ''
3 !%!5!5!I!I!K! ''7 3wIvw333wIvww EIEZEZ  G 	     7 $ 5 5#1M
 M.&&&
 99^4<<L#= L$: ###$892m1#,,?W2X1YZDOOOt.?@@N:::	$**66N===T]]O<<NN+
 ==I%8;tzz8I4::++C04tzzL5l^ D))- 5=> ++224::<>)| <={{<((w  
s$   "!Z& Z& ,
Z8;Z8&Z54Z5c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  )  s     + + +rH   c                    \        V \        4      '       d   V P                  RR4      ;'       g    R# \        V RR4      ;'       g    R# )z8Extract call ID from a tool_call entry (dict or object).idr   )rO   r   r   r`   )r   s   &rE   _get_tool_call_id_static AIAgent._get_tool_call_id_static(  sA     b$66$#))r)r4$***rH   c                r   < V ^8  d   QhRS[ S[S[S[3,          ,          RS[ S[S[S[3,          ,          /# r   r9  )rs   rn   s   "rE   rt   r.  2  s:     C Cd38n)= C$tCQTH~BV CrH   c           
        . pV  FR  pVP                  R4      pV\        P                  9  d   \        P	                  RV4       KA  VP                  V4       KT  	  Tp \        4       pV  Fm  pVP                  R4      R8X  g   K  VP                  R4      ;'       g    .  F3  p\        P                  V4      pV'       g   K"  VP                  V4       K5  	  Ko  	  \        4       pV  FG  pVP                  R4      R8X  g   K  VP                  R4      pV'       g   K6  VP                  V4       KI  	  Wt,
          pV'       d_   V  U	u. uF3  p	V	P                  R4      R8X  d   V	P                  R4      V9   d   K1  V	NK5  	  p p	\        P	                  R\        V4      4       WG,
          p
V
'       d   . pV  F  pVP                  V4       VP                  R4      R8X  g   K,  VP                  R4      ;'       g    .  F7  p\        P                  V4      pWj9   g   K   VP                  RRRR	RV/4       K9  	  K  	  Tp \        P	                  R
\        V
4      4       V # u up	i )u   Fix orphaned tool_call / tool_result pairs before every LLM call.

Runs unconditionally — not gated on whether the context compressor
is present — so orphans from session loading or manual message
manipulation are always caught.
r   z9Pre-call sanitizer: dropping message with invalid role %rr  r   r   r  z6Pre-call sanitizer: removed %d orphaned tool result(s)r   u2   [Result unavailable — see context summary above]z0Pre-call sanitizer: added %d stub tool result(s))
r   r,  _VALID_API_ROLESr  r   r   r3  r  r`  rQ   )r   filteredr   r   surviving_call_idsr   cidresult_call_idsorphaned_resultsr  missing_resultspatcheds   &           rE   _sanitize_api_messagesAIAgent._sanitize_api_messages1  s     C776?D7333O OOC   "%%Cwwv+-'',/5525B!::2>Cs*..s3 6   #uCwwv&(ggn-3#'',	  +?##af/AEE.4IM]4] 8   LLH$% ->,.Gs#776?k1!ggl399r9%>>rB1#NN & )+_ .,  :   HLLBO$ ;s   .I8Ic                &   < V ^8  d   QhRS[ RS[ /# rq   r   rr   r   )rs   rn   s   "rE   rt   r.  x  s      T d rH   c                :   ^ RI Hp \        R V  4       4      pW!8:  d   V # ^ p. pV  FS  pVP                  P                  R8X  d%   W18  d   VP                  V4       V^,          pK@  KB  VP                  V4       KU  	  \        P                  RW!,
          V4       V# )aB  Truncate excess delegate_task calls to MAX_CONCURRENT_CHILDREN.

The delegate_tool caps the task list inside a single call, but the
model can emit multiple separate delegate_task tool_calls in one
turn.  This truncates the excess, preserving all non-delegate calls.

Returns the original list if no truncation was needed.
)MAX_CONCURRENT_CHILDRENc              3   ^   "   T F#  qP                   P                  R 8X  g   K  ^x  K%  	  R# 5i)delegate_taskNr   ra   )r   r   s   & rE   r   3AIAgent._cap_delegate_task_calls.<locals>.<genexpr>  s!     [2{{7G7G?7ZQQs   -
-r  zUTruncated %d excess delegate_task call(s) to enforce MAX_CONCURRENT_CHILDREN=%d limit)tools.delegate_toolr  sumr   ra   r   r  r   )r   r  delegate_countkept_delegates	truncatedr   s   &     rE   _cap_delegate_task_calls AIAgent._cap_delegate_task_callsw  s     	@[[[4	B{{?2!;$$R("a'N <   $  	/46M	

 rH   c                &   < V ^8  d   QhRS[ RS[ /# r  r   )rs   rn   s   "rE   rt   r.    s     G GD GT GrH   c                f   \        4       p. pV  F  pVP                  P                  VP                  P                  3pWA9  d%   VP	                  V4       VP                  V4       KY  \        P                  RVP                  P                  4       K  	  \        V4      \        V 4      8  d   V# T # )zRemove duplicate (tool_name, arguments) pairs within a single turn.

Only the first occurrence of each unique pair is kept.
Returns the original list if no duplicates were found.
zRemoved duplicate tool call: %s)	r3  r   ra   r   r`  r   r  r   rQ   )r   seenuniquer   r  s   &    rE   _deduplicate_tool_callsAIAgent._deduplicate_tool_calls  s     EB;;##R[[%:%:;Cb!@"++BRBRS  Vs:6vFJFrH   c                4   < V ^8  d   QhRS[ RS[ R,          /# rq   r   rr   Nr   )rs   rn   s   "rE   rt   r.    s      3 3: rH   c                
   ^ RI Hp VP                  4       pW0P                  9   d   V# VP	                  RR4      P	                  RR4      pW@P                  9   d   V# V! W0P                  ^RR7      pV'       d
   V^ ,          # R# )zAttempt to repair a mismatched tool name before aborting.

1. Try lowercase
2. Try normalized (lowercase + hyphens/spaces -> underscores)
3. Try fuzzy match (difflib, cutoff=0.7)

Returns the repaired name if found in valid_tool_names, else None.
)get_close_matches-r  rn  r  )ncutoffN)difflibr  r7  r4  r  )rC   r   r  lowered
normalizedmatchess   &&    rE   _repair_tool_callAIAgent._repair_tool_call  s~     	. //#+++N __S#.66sC@
... $G-B-BaPST1:rH   c                p    RV n         V P                  '       d   V P                  P                  4        R# R# )z
Invalidate the cached system prompt, forcing a rebuild on the next turn.

Called after context compression events. Also reloads memory from disk
so the rebuilt prompt captures any writes from this session.
N)r?  rJ  rR  rW   s   &rE   _invalidate_system_prompt!AIAgent._invalidate_system_prompt  s/     &*"--/ rH   c                   < V ^8  d   QhRS[ S[S[S[S[3,          ,          ,          RS[ S[S[S[S[3,          ,          ,          /# )rq   r  rr   )r   r   r   rP   r   )rs   rn   s   "rE   rt   r.    sF     ! !htDcN/C&D !PXY]^bcfhkck^lYmPn !rH   c                   Ve   TMV P                   pV'       g   R# . pV F  p\        V\        4      '       d   VP                  R/ 4      M/ pVP                  R4      p\        V\        4      '       d   VP                  4       '       g   Kl  VP                  RRRVRVP                  RR4      RRR	VP                  R	RR
R/ /4      /4       K  	  T;'       g    R# )zIConvert chat-completions tool schemas to Responses function-tool schemas.Nr   ra   r   r  r   strictFr  rA   
properties)r  rO   r   r   rP   r   r   )rC   r  source_tools	converteditemr  ra   s   &&     rE   _responses_toolsAIAgent._responses_tools  s     % 1utzz*,	 D-7d-C-C*b)B66&>DdC((


rvvmR8%bff\FHlTV3WX  !   D rH   c                2   < V ^8  d   QhRS[ RS[ RS[RS[ /# )rq   fn_namer   indexrr   )rP   r   )rs   rn   s   "rE   rt   r.    s*     
  
  
  
 C 
 PS 
 rH   c                    ^ RI pV  RV RV 2pVP                  ! VP                  RRR7      4      P                  4       R,          pRV 2# )u   Generate a deterministic call_id from tool call content.

Used as a fallback when the API doesn't provide a call_id.
Deterministic IDs prevent cache invalidation — random UUIDs would
make every API call's prefix unique, breaking OpenAI's prompt cache.
N:r  r  )errorsN   Ncall_)hashlibsha256encode	hexdigest)r  r   r  r  seeddigests   &&&   rE   _deterministic_call_idAIAgent._deterministic_call_id  sT     	!I;aw/GI FGQQSTWXvhrH   c                \   < V ^8  d   QhRS[ RS[S[S[,          S[S[,          3,          /# )rq   raw_idrr   )r   tupler   rP   )rs   rn   s   "rE   rt   r.    s-       x}hsm7S1T rH   c                H   \        V \        4      '       g   R# V P                  4       pV'       g   R# RV9   dL   VP                  R^4      w  r#VP                  4       ;'       g    RpVP                  4       ;'       g    RpW#3# VP	                  R4      '       d   RV3# VR3# )z8Split a stored tool id into (call_id, response_item_id).N|fc_NN)rO   rP   r   r  r  )r   r4  call_idresponse_item_ids   &   rE   _split_responses_tool_id AIAgent._split_responses_tool_id  s     &#&&%<(-C(;%Gmmo--G/557??4,,E"";d{rH   c                <   < V ^8  d   QhRS[ RS[S[ ,          RS[ /# )rq   r  r  rr   )rP   r   )rs   rn   s   "rE   rt   r.    s-       #3- 
	rH   c                ~   \        V\        4      '       d*   VP                  4       pVP                  R4      '       d   V# T;'       g    RP                  4       pVP                  R4      '       d   V# VP                  R4      '       d+   \	        V4      \	        R4      8  d   RV\	        R4      R  2# \
        P                  ! RRV4      pVP                  R4      '       d   V# VP                  R4      '       d+   \	        V4      \	        R4      8  d   RV\	        R4      R  2# V'       d   RVR,           2# T;'       g=    \        T;'       g    R4      ;'       g     \        P                  ! 4       P                  p\        P                  ! VP                  R4      4      P                  4       R,          pRV 2# )	zCBuild a valid Responses `function_call.id` (must start with `fc_`).r  r   r  Nz[^A-Za-z0-9_-]:N0   Nr  :N   N)rO   rP   r   r  rQ   r  r   r8  r9  r:  r  sha1r  r  )rC   r  r  	candidater  	sanitizedr  r  s   &&&     rE   "_derive_responses_function_call_id*AIAgent._derive_responses_function_call_id  sr    &,,(..0I##E**  --R&&(U##MW%%#f+G*DG./00FF,b&9	&&((S^c'l-J3w<=12333())HH-334HH

8H8Hdkk'23==?DVH~rH   c                r   < V ^8  d   QhRS[ S[S[S[3,          ,          RS[ S[S[S[3,          ,          /# r   r9  )rs   rn   s   "rE   rt   r.    s?     w w$tCH~:N wSWX\]`be]eXfSg wrH   c                |   . pV EF  p\        V\        4      '       g   K  VP                  R4      pVR8X  d   K6  VR!9   Edu   VP                  RR4      pVR8X  Ed
   \        V\        4      '       d   . pV F  p\        V\        4      '       g   K  VP                  R4      R8X  d(   VP	                  RR	RVP                  RR4      /4       KX  VP                  R4      R
8X  g   Kp  VP                  R
/ 4      p\        V\        4      '       d   VP                  RR4      MRp	V	'       g   K  VP	                  RRR
V	/4       K  	  V'       d   VP	                  RRRV/4       EKa  Ve   \        V4      MRp
VR8X  Ed!   VP                  R4      pRp\        V\        4      '       dN   V FG  p\        V\        4      '       g   K  VP                  R4      '       g   K4  VP	                  V4       RpKI  	  V
P                  4       '       d   VP	                  RRRV
/4       MV'       d   VP	                  RRRR/4       VP                  R4      p\        V\        4      '       Ed7   V EF/  p\        V\        4      '       g   K  VP                  R/ 4      pVP                  R4      p\        V\
        4      '       d   VP                  4       '       g   Km  V P                  VP                  R4      4      w  ppVP                  R4      p\        V\
        4      '       d   VP                  4       '       g   Tp\        V\
        4      '       d   VP                  4       '       g   \        V\
        4      '       dC   VP                  R4      '       d,   \        V4      \        R4      8  d   RV\        R4      R  2pM7\        VP                  RR4      4      pV P                  VV\        V4      4      pVP                  4       pVP                  RR4      p\        V\        4      '       d   \        P                  ! VRR7      pM!\        V\
        4      '       g   \        V4      pVP                  4       ;'       g    RpVP	                  RRRVRVRV/4       EK2  	  EK  VP	                  RVRV
/4       EK  VR8X  g   EK  VP                  R4      pV P                  V4      w  pp\        V\
        4      '       d   VP                  4       '       g=   \        V\
        4      '       d'   VP                  4       '       d   VP                  4       p\        V\
        4      '       d   VP                  4       '       g   EKx  TP	                  RRRTR \        VP                  RR4      ;'       g    R4      /4       EK  	  V# )"z>Convert internal chat-style messages to Responses input items.r   r  rm  r  r   r   r   r   
input_text	image_urlr  input_imageNr  Fencrypted_contentTr   r   ra   r  r  r  r  r   rg  r   function_callr   r  function_call_outputoutput>   rm  r  )rO   r   r   r   r   rP   r   r  r  rQ   r  r   r   )rC   r   r6  r   r   r   responses_contentr   r  r  content_textcodex_reasoninghas_codex_reasoningrir   r   r  r  embedded_call_idembedded_response_item_idr  	_raw_argsr   raw_tool_call_idr  s   &&                       rE   !_chat_messages_to_responses_input)AIAgent._chat_messages_to_responses_input  s   &(Cc4((776?Dx,,'')R06>j$&?&?>@% ')$55$88F+v5-44 & &(<6  "XXf-<(,b(AI>HTX>Y>Y)--r":_aC"s 1 8 8$*M$/:" !# !(  )ffiAR%ST /6/Bs7|;& '*gg.E&FO*/'!/488"1B)"d33?R8S8S %R 06: 3 #2
 $))++fk9l%ST, fk9b%IJ!$!6J!*d33",B#-b$#7#7 (!#
B!7B&(ffVnG#-gs#;#;7==?? (JNJgJg "tKG,.G ')ffY&7G#-gs#;#;7==??*:#-gs#;#;7==??$./H#$N$N(A(L(LU(S(S(+,E(FU(S056OPSTYPZP[6\5].^G03BFF;4M0NI.2.I.I'S\^abg^h.iG&-mmoG(*{D(AI))T::,0JJyu,U	%/	3%?%?,/	N	(1(9(A(ATI!LL & )7 & +Y	* C #-N fdI|DEv~#&77>#: !::;KL
!'3//w}}!"2C88=M=S=S=U=U"2"8"8":!'3//w}}2wc#'')R"8">">B? [ f rH   c                L   < V ^8  d   QhRS[ RS[S[S[S[ 3,          ,          /# )rq   	raw_itemsrr   )r   r   r   rP   )rs   rn   s   "rE   rt   r.    s,     W Wc Wd4S>>R WrH   c                   \        V\        4      '       g   \        R 4      h. p\        V4       EF  w  r4\        V\        4      '       g   \        RV R24      hVP                  R4      pVR8X  EdM   VP                  R4      pVP                  R4      p\        V\        4      '       d   VP                  4       '       g   \        RV R24      h\        V\        4      '       d   VP                  4       '       g   \        RV R24      hVP                  R	R
4      p\        V\        4      '       d   \        P                  ! VRR7      pM!\        V\        4      '       g   \        V4      pVP                  4       ;'       g    R
pVP                  RRRVP                  4       RVP                  4       R	V/4       EK  VR8X  d   VP                  R4      p\        V\        4      '       d   VP                  4       '       g   \        RV R24      hVP                  RR4      p	V	f   Rp	\        V	\        4      '       g   \        V	4      p	VP                  RRRVP                  4       RV	/4       EKD  VR8X  d   VP                  R4      p
\        V
\        4      '       d   V
'       d|   RRRV
/pVP                  R4      p\        V\        4      '       d   V'       d   WR&   VP                  R4      p\        V\        4      '       d   WR&   M. VR&   VP                  V4       EK  VP                  R4      pVR9   d~   VP                  RR4      pVf   Rp\        V\        4      '       d   VP                  RVRV/4       M6\        V\        4      '       g   \        V4      pVP                  RVRV/4       EK  \        RV RV: RV: R24      h	  V# )z4Codex Responses input must be a list of input items.zCodex Responses input[] must be an object.r   r  r  ra   z#] function_call is missing call_id.z ] function_call is missing name.r   rg  Fr   r  z*] function_call_output is missing call_id.r  r   r4  r  r  r7  r   r   z#] has unsupported item shape (type=z, role=).>   rm  r  )rO   r   rN   	enumerater   r   rP   r   r   r   r   )rC   r(  r  r  r  	item_typer  ra   r   r  	encryptedreasoning_itemitem_idr7  r   r   s   &&              rE   _preflight_codex_input_items$AIAgent._preflight_codex_input_items  sd   )T**STT+-
"9-ICdD)) #9#>R!STT(IO+((9-xx'!'3//w}}$'=cUBe%fgg!$,,DJJLL$'=cUBb%cdd HH[$7	i.. $

95 II#Is33 #II%OO-55	!!!7==?

#Y	 22((9-!'3//w}}$'=cUBl%mnn(B/>F!&#.. [F!! 6!7==? & K' HH%89	i--)&,k;NPY%ZN"hhtnG!'3//G/6t,"hhy1G!'4004;y146y1%%n588F#D,,((9b1? Ggt,,%%vtY&HI%gs33"%g,%%vtY&HI(-PQZP]]deidllno ] .d rH   allow_streamc                B   < V ^8  d   QhRS[ RS[RS[S[S[ 3,          /# )rq   r  r3  rr   )r   r   r   rP   )rs   rn   s   "rE   rt   r.    s6     { {{ 	{
 
c3h{rH   c               	  a \        V\        4      '       g   \        R 4      h0 R$mpV Uu. uF  qDV9  g   K  VNK  	  ppV'       d(   \        RRP                  \	        V4      4       R24      hVP                  R4      p\        V\        4      '       d   VP                  4       '       g   \        R4      hVP                  4       pVP                  R4      pVf   R	p\        V\        4      '       g   \        V4      pVP                  4       ;'       g    \        pV P                  VP                  R4      4      pVP                  R
4      p	Rp
V	Ee   \        V	\        4      '       g   \        R4      h. p
\        V	4       EFz  w  r\        V\        4      '       g   \        RV R24      hVP                  R4      R8w  d#   \        RV RVP                  R4      : R24      hVP                  R4      pVP                  R4      p\        V\        4      '       d   VP                  4       '       g   \        RV R24      h\        V\        4      '       g   \        RV R24      hVP                  RR	4      pVf   R	p\        V\        4      '       g   \        V4      pVP                  RR4      p\        V\        4      '       g   \        V4      pV
P                  RRRVP                  4       RVRVRV/4       EK}  	  VP                  RR4      pVRJd   \        R4      h0 R%moRVRVRVRR/pV
e   V
VR
&   VP                  R4      p\        V\        4      '       d   VVR&   VP                  R4      p\        V\        4      '       d   VVR&   VP                  R4      p\        V\        \        34      '       d   V^ 8  d   \        V4      VR&   VP                  R4      p\        V\        \        34      '       d   \        V4      VR&   R& F  pVP                  V4      pVf   K  VVV&   K!  	  V'       dD   VP                  R4      pVe   VRJd   \        R 4      hVRJ d   RVR&   SP!                  R4       MRV9   d   \        R!4      h\	        V3R" lVP#                  4        4       4      pV'       d   \        R#RP                  V4       R24      hV# u upi )'z'Codex Responses request must be a dict.rB  instructionsinputz3Codex Responses request missing required field(s): r  .z;Codex Responses request 'model' must be a non-empty string.Nr   r  z=Codex Responses request 'tools' must be a list when provided.zCodex Responses tools[r*  r   r   z] has unsupported type ra   r  z] is missing a valid name.z] is missing valid parameters.r  r  Fstorez6Codex Responses contract requires 'store' to be false.r4  includemax_output_tokenstemperaturer{   Tz/Codex Responses 'stream' must be true when set.zKCodex Responses stream flag is only allowed in fallback streaming requests.c              3   8   <"   T F  qS9  g   K  Vx  K  	  R # 5irU   rd   )r   r  allowed_keyss   & rE   r   6AIAgent._preflight_codex_api_kwargs.<locals>.<genexpr>e  s     X+<C<@WCC+<s   
z2Codex Responses request has unsupported field(s): >   r7  rB  r6  >   r7  rB  r9  r  r:  r4  r<  tool_choicer6  prompt_cache_keyr;  parallel_tool_calls)r@  rB  rA  )rO   r   rN   r  r5  r   rP   r   r   r1  r   r,  r   r   r   rk  r`  keys)rC   r  r3  r  r  missingrB  r6  normalized_inputr  normalized_toolsr  r   ra   r  r  r  r9  r  r4  r:  r;  r<  passthrough_keyvalr{   
unexpectedr>  s   &&$                        @rE   _preflight_codex_api_kwargs#AIAgent._preflight_codex_api_kwargs  s    *d++FGG5"*D(3.C33(DRSWS\S\]cdk]lSmRnnopqqw'%%%U[[]]Z[[!~~n5L,,,|,L#))+EE/E<<Z^^G=TUw'eT** !`aa!&u-	!$--$'=cUBV%WXX88F#z1$'=cUBYZ^ZbZbciZjYmmn%oppxx'!XXl3
!$,,DJJLL$'=cUB\%]^^!*d33$'=cUB`%abb"hh}b9&"$K!+s33"%k"2K(E2!&$//!&\F ''


%{ &$j/ .B w.UVV
 UL%U	&

 '"2Jw NN;/	i&&&/J{#..+gt$$$+Jy! 'NN+>?'#u66;Lq;P.12C.DJ*+ nn]3kC<00(-k(:J}%  ZO..1C.1
?+  Z
 ^^H-F!fD&8 !RSS~'+
8$X&#jkkX:??+<XX
DTYYzEZD[[\]  c Es
   SSc                &   < V ^8  d   QhRS[ RS[/# rq   r  rr   r   rP   )rs   rn   s   "rE   rt   r.  m  s     ' 'C 'C 'rH   c                L   \        VRR4      p\        V\        4      '       g   R# . pV FY  p\        VRR4      pVR9  d   K  \        VRR4      p\        V\        4      '       g   K>  V'       g   KH  VP	                  V4       K[  	  RP                  V4      P                  4       # )z<Extract assistant text from a Responses message output item.r   Nr   r   r   >   r   output_textr`   rO   r   rP   r   r  r   )rC   r  r   chunksr   ptyper   s   &&     rE   _extract_responses_message_text'AIAgent._extract_responses_message_textm  s    $	40'4((DD&$/E334.D$$$d#  wwv$$&&rH   c                &   < V ^8  d   QhRS[ RS[/# rM  rN  )rs   rn   s   "rE   rt   r.  }  s      c c rH   c                   \        VRR4      p\        V\        4      '       ds   . pV FC  p\        VRR4      p\        V\        4      '       g   K(  V'       g   K2  VP	                  V4       KE  	  V'       d    RP                  V4      P                  4       # \        VRR4      p\        V\        4      '       d   V'       d   VP                  4       # R# )zAExtract a compact reasoning text from a Responses reasoning item.r7  Nr   r  r   rQ  )rC   r  r7  rR  r   r   s   &&    rE   !_extract_responses_reasoning_text)AIAgent._extract_responses_reasoning_text}  s    $	40gt$$ "FtVT2dC((TTMM$'   yy(..00tVT*dC  T::<rH   c                <   < V ^8  d   QhRS[ RS[S[ S[3,          /# r  )r   r  rP   )rs   rn   s   "rE   rt   r.    s'     b0 b0# b0%S/ b0rH   c                   \        VRR4      p\        V\        4      '       d	   V'       g   \        VRR4      p\        V\        4      '       du   VP	                  4       '       d_   \
        P                  R\        VP	                  4       4      4       \        RRR\        RVP	                  4       R7      .R	7      .pW!n	        M\        R
4      h\        VRR4      p\        V\        4      '       d    VP	                  4       P                  4       pMRpVR+9   dm   \        VRR4      p\        V\        4      '       d&   VP                  R4      ;'       g    \        V4      pMV'       d   \        V4      MRV R2p\        V4      h. p. p. p	. p
VR,9   pRpRpV EF  p\        VRR4      p\        VRR4      p\        V\        4      '       d    VP	                  4       P                  4       pMRpVR,9   d   RpVR8X  d   \        VRR4      p\        V\        4      '       d2   VP	                  4       P                  4       pVR-9   d   RpM	VR.9   d   RpV P                  V4      pV'       d   VP                  V4       K  K  VR8X  Ed   V P!                  V4      pV'       d   VP                  V4       \        VRR4      p\        V\        4      '       d   V'       d   RRRV/p\        VRR4      p\        V\        4      '       d   V'       d   VVR&   \        VRR4      p\        V\        4      '       dK   . pV F=  p\        VRR4      p\        V\        4      '       g   K(  VP                  RRRV/4       K?  	  VVR&   V	P                  V4       EK  EK  EK  VR8X  Edl   VR,9   d   EK  \        VRR4      ;'       g    Rp\        VRR4      p\        V\        4      '       g   \"        P$                  ! VRR7      p\        VR R4      p\        VRR4      pV P'                  V4      w  p p!\        V\        4      '       d   VP	                  4       '       d   TMT p"\        V"\        4      '       d   V"P	                  4       '       g   V P)                  VV\        V
4      4      p"V"P	                  4       p"\        V\        4      '       d   TMRp#V P+                  V"V#4      p#V
P                  \        V"V"V#R!\        VVR"7      R#7      4       EKt  VR$8X  g   EK~  \        VRR4      ;'       g    Rp\        VR%R4      p\        V\        4      '       g   \"        P$                  ! VRR7      p\        VR R4      p\        VRR4      pV P'                  V4      w  p p!\        V\        4      '       d   VP	                  4       '       d   TMT p"\        V"\        4      '       d   V"P	                  4       '       g   V P)                  VV\        V
4      4      p"V"P	                  4       p"\        V\        4      '       d   TMRp#V P+                  V"V#4      p#V
P                  \        V"V"V#R!\        VVR"7      R#7      4       EK  	  R&P-                  V U$u. uF  p$V$'       g   K  V$NK  	  up$4      P	                  4       p%V%'       gF   \/        VR4      '       d4   \        VRR4      p\        V\        4      '       d   VP	                  4       p%\        T%T
V'       d    R'P-                  V4      P	                  4       MRRRT	;'       g    RR(7      p&V
'       d   R)p'V&V'3# V'       g   V'       d   V'       g   Rp'V&V'3# V	'       d   V%'       g   Rp'V&V'3# R*p'V&V'3# u up$i )/zENormalize a Responses API object to an assistant_message-like object.r  NrP  z`Codex response has empty output but output_text is present (%d chars); synthesizing output item.r  r  r  r   r   r   r   statusr   z&Responses API returned no output itemsr^  r  zResponses API returned status 'rE  
incompleteFr   Tphaser4  r  r  r7  r   summary_textr  ra   r   r   rg  r   r  r   ra   r   )r  r  r  r   r   custom_tool_callr7  r  r9  )r   r   r4  r5  r6  r  r   stop>   failed	cancelled>   queuedr_  in_progress>   analysis
commentary>   finalfinal_answer)r`   rO   r   rP   r   r  r   rQ   r   r  r+  r7  r   r   rT  r   rX  r   r   r  r  r  r  r*  )(rC   r  r  out_textr  	error_objr  content_partsr=  reasoning_items_rawr   has_incomplete_itemssaw_commentary_phasesaw_final_answer_phaser  r-  item_status
item_phasenormalized_phasemessage_textrM  r.  raw_itemr0  r7  raw_summaryr   r   r  r   raw_call_idraw_item_idr!  r  r  r  r|  
final_textr<  rE  s(   &&                                      rE   _normalize_codex_response!AIAgent._normalize_codex_response  s   8T2&$''v x=H(C((X^^-=-=014X^^5E1F *"[,-hnnFVWX  #)"#KLL!(Hd;os++-335;;=O"O55'48I)T**%MM)4FFI	.7C	N?^_n^oop=q	y))#%%'46 "
.2YY$!&Dfd3I!$$7K+s++)//1779"EE'+$I%$T7D9
j#..'1'7'7'9'?'?'A$'+EE/3,)-FF15.#CCDI!((6  k)!%!G!G!M!#**>: $D*=tD	i--) &5H)TH%dD$7G!'3//G)0%dIt<G!'400&($+D#*4#>D)$44 + 2 2FNFTX3Y Z %, /:+'..x8 3<- o-"II!$399r#D+t<	!)S11 $

95 II%dIt<%dD$7&*&C&CK&P# !)3K)E)E+J[J[J]J]+cs!'3//w}}"99'9cR\o^G!--/2<[#2N2N;TX #'#J#J7Td#e !!/#%5#,'YO#  00!$399r#D'48	!)S11 $

95 II%dIt<%dD$7&*&C&CK&P# !)3K)E)E+J[J[J]J]+cs!'3//w}}"99'9cR\o^G!--/2<[#2N2N;TX #'#J#J7Td#e !!/#%5#,'YO# e t YY=>=aA=>?EEG
gh>>x;H(C((%^^-
+!>Mfkk/288:SW"""5"="=
 (M !-// "&:CY(M !-// ! )M !-// #M -//;  ?s   
^	^	c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  1  s     / /# /rH   c                b    \         P                  ! 4       pVP                   R VP                   2# )r  )r   current_threadra   ident)rC   threads   & rE   _thread_identityAIAgent._thread_identity1  s)    ))+++a~..rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  5  s     
 
S 
rH   c                    \        V R R4      p\        V RR4      p\        V RR4      pRV P                  4        RV RV RV 2# )r<  r  r1  rB  zthread=
 provider=z
 base_url=z model=)r`   r  )rC   r<  r1  rB  s   &   rE   _client_log_contextAIAgent._client_log_context5  s^    4Y74Y7gy1d++-.j
 C z1	
rH   c                4   < V ^8  d   QhRS[ P                  /# r   )r   r  )rs   rn   s   "rE   rt   r.  >  s      Y__ rH   c                ^    \        V R R4      pVf   \        P                  ! 4       pWn        V# )r  N)r`   r   r  r  )rC   locks   & rE   _openai_client_lockAIAgent._openai_client_lock>  s,    t^T2<??$D $rH   c                &   < V ^8  d   QhRS[ RS[/# rq   r%  rr   r   r   )rs   rn   s   "rE   rt   r.  F  s        rH   c                   ^ RI Hp \        W4      '       d   R# \        V RR4      pVe5   \	        V4      '       d   V! 4       '       d   R# M\        V4      '       d   R# \        V RR4      pVe   \        \        VRR4      4      # R# )aT  Check if an OpenAI client is closed.

Handles both property and method forms of is_closed:
- httpx.Client.is_closed is a bool property
- openai.OpenAI.is_closed is a method returning bool

Prior bug: getattr(client, "is_closed", False) returned the bound method,
which is always truthy, causing unnecessary client recreation on every call.
MockF	is_closedNT_client)unittest.mockr  rO   r`   rl  r   )r%  r  is_closed_attrhttp_clients   &   rE   _is_openai_client_closed AIAgent._is_openai_client_closedE  s~     	'f## d;%''!## $n%%fi6"[%@AArH   c                2   < V ^8  d   QhRS[ RS[RS[RS[/# )rq   r  r  r  rr   )r   rP   r   r   )rs   rn   s   "rE   rt   r.  c  s+      4 C QU Z] rH   c               V   V P                   R 8X  g1   \        VP                  RR4      4      P                  R4      '       d7   ^ RIHp V! R/ VB p\        P                  RVVV P                  4       4       V# \        R/ VB p\        P                  RVVV P                  4       4       V# )r  r1  r   zacp://copilot)CopilotACPClientz-Copilot ACP client created (%s, shared=%s) %sz(OpenAI client created (%s, shared=%s) %srd   )
r<  rP   r   r  agent.copilot_acp_clientr  r  r  r  r   )rC   r  r  r  r  r%  s   &&$$  rE   r.  AIAgent._create_openai_clientc  s    ==M)S1B1B:r1R-S-^-^_n-o-oA%66FKK?((*	 M(-(6$$&		
 rH   c                &   < V ^8  d   QhRS[ RS[/# r  )r   r   )rs   rn   s   "rE   rt   r.  y  s     8 8 8 8rH   c                   ^ RI p^ p \        V RR4      pVf   ^ # \        VRR4      pVf   ^ # \        VRR4      pVf   ^ # \        VRR4      ;'       g    \        VRR4      ;'       g    . p\        V4       F  p\        VRR4      ;'       g    \        VRR4      pVf   K+  \        VRR4      p	V	f   \        VR	R4      p	V	e   \        V	RR4      p	V	f   K`   V	P                  VP                  4        V	P                  4        V^,          pK  	  V#   \
         d     L-i ; i  \
         d     L-i ; i  \         d"   p
\        P                  R
T
4        Rp
?
T# Rp
?
ii ; i)a  Force-close underlying TCP sockets to prevent CLOSE-WAIT accumulation.

When a provider drops a connection mid-stream, httpx's ``client.close()``
performs a graceful shutdown which leaves sockets in CLOSE-WAIT until the
OS times them out (often minutes).  This method walks the httpx transport
pool and issues ``socket.shutdown(SHUT_RDWR)`` + ``socket.close()`` to
force an immediate TCP RST, freeing the file descriptors.

Returns the number of sockets force-closed.
Nr  
_transport_pool_connections_network_stream_stream_sockr{   z'Force-close TCP sockets sweep error: %s)
socketr`   r   shutdown	SHUT_RDWRrM   closer   r  r   )r%  _socketclosedr  	transportpoolconnectionsconnr{   sockr)  s   &          rE   _force_close_tcp_sockets AIAgent._force_close_tcp_socketsx  s    	!)	I!&)T:K"\4@I 9gt4D| nd3  4$/  
 [)D"3T: 6 6tY5  >vw5<"68T:D'&tWd;<MM'"3"34JJL !- *2       	ILLBCHH	Is|   D6 D6 D6 D6 D6 *$D6 A	D6 D5D%D6 D"D6 !D""D6 %D30D6 2D33D6 6E"EE"c                0   < V ^8  d   QhRS[ RS[RS[RR/# )rq   r%  r  r  rr   N)r   rP   r   )rs   rn   s   "rE   rt   r.    s*      3 3  QU rH   c               $   Vf   R # V P                  V4      p VP                  4        \        P                  RVVVV P	                  4       4       R #   \
         d3   p\        P                  RTTT P	                  4       T4        R p?R # R p?ii ; i)Nz<OpenAI client closed (%s, shared=%s, tcp_force_closed=%d) %sz6OpenAI client close failed (%s, shared=%s) %s error=%s)r  r  r  r  r  r   r   )rC   r%  r  r  force_closedr)  s   &&$$  rE   rw  AIAgent._close_openai_client  s    > 44V<	LLNKKN((*  	LLH((* 	s   7A B'B

Bc                &   < V ^8  d   QhRS[ RS[/# rq   r  rr   r   )rs   rn   s   "rE   rt   r.    s        rH   c          	        V P                  4       ;_uu_ 4        \        V R R4      p V P                  V P                  VRR7      pY0n        RRR4       T P                  XRT 2RR7       R#   \         d:   p\
        P                  RTT P                  4       T4        Rp?RRR4       R# Rp?ii ; i  + '       g   i     Lp; i)r%  NTr  z7Failed to rebuild shared OpenAI client (%s) %s error=%sFzreplace:)
r  r`   r.  r&  r   r  r   r  r%  rw  )rC   r  
old_client
new_clientr)  s   &$   rE   _replace_primary_openai_client&AIAgent._replace_primary_openai_client  s    %%'' x6J	!778K8KTZcg7h
 %K ( 	!!*xx5HQU!V  M,,.	  ('	 ('s4   B4A-B4-B18&B,B4,B11B44C	c                &   < V ^8  d   QhRS[ RS[/# r  rP   r   )rs   rn   s   "rE   rt   r.    s      s s rH   c                  V P                  4       ;_uu_ 4        \        V R R4      pVe$   V P                  V4      '       g   VuuRRR4       # RRR4       \        P	                  RVV P                  4       4       V P                  RV 2R7      '       g   \        R4      hV P                  4       ;_uu_ 4        V P                  uuRRR4       #   + '       g   i     L; i  + '       g   i     R# ; i)r%  NzCDetected closed shared OpenAI client; recreating before use (%s) %szrecreate_closed:r  z'Failed to recreate closed OpenAI client)	r  r`   r  r  r   r  r  r+  r%  )rC   r  r%  s   &$ rE   _ensure_primary_openai_client%AIAgent._ensure_primary_openai_client  s    %%''T8T2F!$*G*G*O*O (''
 	Q$$&	

 22<LVH:U2VVHII%%'';; (' (' (''s   (CC9C#C 	#C4	c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     D D4 DrH   c                (   \        V RR4      pVf   R#  \        VRR4      pVf   R# \        VRR4      pVf   R# \        VRR4      pVf   R# \        VRR4      ;'       g    \        VRR4      ;'       g    . p^ p\        V4       F  p\        VRR4      ;'       g    \        VR	R4      pVf   K+  \        VR
R4      p	V	f   \        VRR4      p	V	e   \        V	R
R4      p	V	f   K`  ^ RIp
 V	P                  R4       V	P	                  ^V
P
                  V
P                  ,          4      pVR8X  d
   V^,          p T	P                  R4       K  	  V^ 8  d+   \        P                  RV4       V P                  RR7       R#  R#   \         d     LW\         d    T^,          p Lli ; i  \         d     EK2  i ; i   T	P                  R4       i   \         d     i i ; i; i  \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)a1  Detect and clean up dead TCP connections on the primary client.

Inspects the httpx connection pool for sockets in unhealthy states
(CLOSE-WAIT, errors).  If any are found, force-closes all sockets
and rebuilds the primary client from scratch.

Returns True if dead connections were found and cleaned up.
r%  NFr  r  r  r  r  r  r  r{   rH   Tu@   Found %d dead connection(s) in client pool — rebuilding clientdead_connection_cleanupr  zDead connection check error: %s)r`   r   r  setblockingrecvMSG_PEEKMSG_DONTWAITBlockingIOErrorrM   r  r   r  r   r   )rC   r%  r  r  r  r  
dead_countr  r{   r  r  rR   r)  s   &            rE   _cleanup_dead_connections!AIAgent._cleanup_dead_connections  s:    x.>7	A!&)T:K"\4@I 9gt4D|nd3  4$/  
 J[) D"3T: 6 6tY5  >vw5<"68T:D'&tWd;<($$U+99Q(8(87;O;O(OPDs{"a
((.9 *> A~V 33;T3U  % '  $!OJ$
 # ((."   	ALL:C@@	As   G% G% G% G% "G% 7&G% AG% ,AF;F*3G% F'F=F'
F'$F=&F''F=*F:5G% 9F::G% =G"?GG"G	G"G	G""G% %H0HHc                &   < V ^8  d   QhRS[ RS[/# r  r  )rs   rn   s   "rE   rt   r.  2  s     W Ws Ws WrH   c                  ^ RI Hp V P                  VR7      p\        W24      '       d   V# V P	                  4       ;_uu_ 4        \        V P                  4      pRRR4       V P                  XVRR7      #   + '       g   i     L$; i)rK   r  r  NFr  )r  r  r  rO   r  r   r&  r.  )rC   r  r  primary_clientrequest_kwargss   &$   rE   _create_request_openai_client%AIAgent._create_request_openai_client2  so    &;;6;Jn++!!%%''!$"5"56N ()).PU)VV ('s   A66B	c                *   < V ^8  d   QhRS[ RS[RR/# )rq   r%  r  rr   NrN  )rs   rn   s   "rE   rt   r.  <  s'     G G3 G3 G4 GrH   c               ,    V P                  WR R7       R# )Fr  N)rw  )rC   r%  r  s   &&$rE   _close_request_openai_client$AIAgent._close_request_openai_client<  s    !!&!FrH   c                ,   < V ^8  d   QhRS[ RS[RS[/# )rq   r  r%  on_first_delta)r   r   rl  )rs   rn   s   "rE   rt   r.  ?  s(     y yD y# yV^ yrH   c                ^	   ^ RI pT;'       g    V P                  RR7      p^pRpRpRV n        . V n        \	        V^,           4       EF  p	. p
 VP
                  P                  ! R#/ VB ;_uu_ 4       pV EF  pV P                  '       d    EM\        VRR4      pRV9   g   VR8X  dr   \        VR	R4      pV'       d   V P                  P                  V4       V'       d8   V'       g.   V'       g   R
pV'       d	    V! 4        V P                  V4       K  K  K  RV9   d   R
pK  RV9   d2   R	V9   d+   \        VR	R4      pV'       d   V P                  V4       K  K  VR8X  d)   \        VRR4      pVe   V
P                  V4       EK  EK  VR$9   g   EK!  \        VRR4      pV'       d   \        VRR4      MRpV'       d   \        VRR4      MRp\        P                  RVVV\        R V P                   4       4      V P!                  4       4       EK  	  VP#                  4       p\        VRR4      p\%        V\&        4      '       d   V'       g   V
'       d1   \'        V
4      Vn        \        P+                  R\-        V
4      4       MV P                  '       dx   V'       gp   RP/                  V P                  4      p\1        RRR\1        RVR7      .R7      .Vn        \        P+                  R\-        V P                  4      \-        V4      4       VuuRRR4       u # 	  R#   \         d     EL1i ; i  + '       g   i     EK  ; i  TP2                  TP4                  TP6                  \8        3 d   pY8  d=   \        P+                  RT	^,           T^,           T P!                  4       T4        Rp?EKu  \        P+                  RT P!                  4       T4       T P;                  YR7      u Rp?u # Rp?i\<         d   p\?        T4      pR T9   pT'       dB   Y8  d<   \        P+                  R!T	^,           T^,           T P!                  4       4        Rp?EK  T'       d>   \        P+                  R"T P!                  4       4       T P;                  YR7      u Rp?u # h Rp?ii ; i)%zJExecute one streaming Responses API request and return the final response.Ncodex_stream_directr  Fr   r   zoutput_text.deltaresponse.output_text.deltadeltaTr  r4  response.output_item.doner  r  r^  incomplete_detailszkCodex Responses stream received terminal event %s (status=%s, incomplete_details=%s, streamed_chars=%d). %sc              3   8   "   T F  p\        V4      x  K  	  R # 5irU   r  )r   r|  s   & rE   r   ,AIAgent._run_codex_stream.<locals>.<genexpr>{  s     #T4SqCFF4Sr  r  z;Codex stream: backfilled %d output items from stream eventsr  r  r  rP  r\  r]  z?Codex stream: synthesized output from %d text deltas (%d chars)zNCodex Responses stream transport failed (attempt %s/%s); retrying. %s error=%szYCodex Responses stream transport failed; falling back to create(stream=True). %s error=%s)r%  response.completedzGResponses stream closed before completion (attempt %s/%s); retrying. %szYResponses stream did not emit response.completed; falling back to create(stream=True). %srd   )response.incompleteresponse.failed) httpxr  r   _codex_streamed_text_partsr  	responsesr{   r  r`   r   r   _fire_stream_delta_fire_reasoning_deltar  r   r  r  get_final_responserO   r   r  r   rQ   r  r   RemoteProtocolErrorReadTimeoutConnectErrorConnectionError!_run_codex_create_stream_fallbackr+  rP   )rC   r  r%  r  _httpxactive_clientmax_stream_retrieshas_tool_callsfirst_delta_firedattemptcollected_output_itemsr{   event
event_type
delta_textrM  	done_itemresp_objr^  r  final_response_out	assembledr)  err_textmissing_completeds   &&&&                      rE   _run_codex_streamAIAgent._run_codex_stream?  s#   bb$"D"DLa"D"b!',$ 13'/!34G+-"j",,33AjAAV!'444!%,UFB%?
.*<
Nj@j)0)DJ) $ ? ? F Fz R).'88<$5'5)1,:,< !% 7 7
 C 3Az -
:-1N(J67j;P-4UGR-HN- $ : :> J  . (+FF(/vt(DI(4 6 = =i H  5 (+UU'.uj$'GHJRWXx%FX\FbjCWY]1^pt."NN!\ *F4F ##TD4S4S#T T $ 8 8 :O "(\ &,%>%>%@N #>8TBD!$--d1489O4PN1"LL ] #$: ; "<<<^(*0O0O(PI5D%.%0'2)8mR[)\(]	6 5N1 #LL a #D$C$C Dc)n *O BA 5& 09 )1,0)1! BAAP ..0B0BFDWDWYhi `/LLh!*Q.002 o,,.
 ==j=__ s8$8H$D!$)ELLa!*Q.002	 $LLs002  AA*Acc#s   $M2A.L8!L8)L81	L8<L&BL8+L8BL8L8AL8L8%A0L8
M&L51L84L55L88M
M
M-R,:;O:<6O:2R,:R,R,AR'!R')5R'R,&R''R,c                &   < V ^8  d   QhRS[ RS[/# )rq   r  r%  )r   r   )rs   rn   s   "rE   rt   r.    s#     Kg KgD Kg# KgrH   c                   T;'       g    V P                  RR7      p\        V4      pRVR&   V P                  VRR7      pVP                  P                  ! R/ VB p\        VR4      '       d   V# \        VR4      '       g   V# Rp. p. p V EF(  p	\        V	R	R4      p
V
'       g(   \        V	\        4      '       d   V	P                  R	4      p
V
R
8X  dO   \        V	RR4      pVf(   \        V	\        4      '       d   V	P                  R4      pVe   VP                  V4       M]V
R9   dW   \        V	RR4      pV'       g)   \        V	\        4      '       d   V	P                  RR4      pV'       d   VP                  V4       V
R9  d   K  \        V	RR4      pVf(   \        V	\        4      '       d   V	P                  R4      pVf   EK:  \        VRR4      p\        V\        4      '       d   V'       g   V'       d1   \        V4      Vn        \        P                  R\        V4      4       McV'       d\   RP                  V4      p\!        RRR\!        RVR7      .R7      .Vn        \        P                  R\        V4      \        V4      4       Tu \        VRR4      p\#        V4      '       d
    V! 4        # # 	  \        VRR4      p\#        V4      '       d
    V! 4        M Ve   V# \'        R4      h  \$         d     # i ; i  \$         d     L/i ; i  \        TRR4      p\#        T4      '       d    T! 4        i   \$         d     i i ; ii ; i)zQFallback path for stream completion edge cases on Codex-style Responses backends.codex_create_stream_fallbackr  Tr{   r3  r  __iter__Nr   r  r  r  r   r  z1Codex fallback stream: backfilled %d output itemsr  r  r  rP  r\  r]  z<Codex fallback stream: synthesized from %d deltas (%d chars)r  zHResponses create(stream=True) fallback did not emit a terminal response.rd   )r  >   r  r  r  )r  r   rJ  r  creater*  r`   rO   r   r   r   r  r  r   rQ   r  r   rl  r   r+  )rC   r  r%  r  fallback_kwargsstream_or_responseterminal_responser  collected_text_deltasr  r  r  r  r  r  close_fns   &&&             rE   r  )AIAgent._run_codex_create_stream_fallback  s.   kk$"D"DLj"D"kz*$(!::?Y]:^*44;;NoN %x00%%):66%% ')&(6	+$UFD9
!j&=&=!&6!2J !<< 'vt <I (Zt-D-D$)IIf$5	 ,.55i@#BB#E7B7E Zt%<%< %		'2 6-44U;%ee$+E:t$D!$,E41H1H(-		*(=%$0"#4hED!$--d17;<R7S-4"LL S #$: ; 3(*0E(FI8G%.['2)8mR[)\(]9 8-4
 #LL ^ #$9 :C	N -,17DAH!!J "c ,` 17DAH!!J " ($$eff ! y 	 17DAH!!J   "s{   C"L .AL *L 2L :7L 2AL /K38L L 3L LLLM5L=<M=MM
MMc                &   < V ^8  d   QhRS[ RS[ /# rq   r  rr   r   )rs   rn   s   "rE   rt   r.    s      d d rH   c                  V P                   R 8w  g   V P                  R8w  d   R#  ^ RIHp V! VR7      pTP                  R4      pTP                  R4      p\        T\        4      '       d   TP                  4       '       g   R# \        T\        4      '       d   TP                  4       '       g   R# TP                  4       T n        TP                  4       P                  R	4      T n        T P                  T P                  R&   T P                  T P                  R&   T P                  R
R7      '       g   R# R#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)rp  rr  F)!resolve_codex_runtime_credentials)force_refreshz#Codex credential refresh failed: %sNr;  r1  ru  codex_credential_refreshr  T)r=  r<  hermes_cli.authr  r   r  r   r   rO   rP   r   r;  r  r1  r&  r  )rC   r  r  credsr)  r;  r1  s   &$     rE   %_try_refresh_codex_client_credentials-AIAgent._try_refresh_codex_client_credentials  s   ==--.1P	I5EJE
 ))I&99Z('3''w}}(C((0@0@}} (//4)-I&*.--J'22:T2UU'  	LL>D	s   D: :E&E!!E&c                &   < V ^8  d   QhRS[ RS[ /# r  r   )rs   rn   s   "rE   rt   r.  $  s     ! !T !T !rH   c                  V P                   R 8w  g   V P                  R8w  d   R#  ^ RIHp V! \	        ^<\        \        P                  ! RR4      4      4      \        \        P                  ! RR4      4      VR7      pTP                  R4      pTP                  R4      p\        T\        4      '       d   TP                  4       '       g   R# \        T\        4      '       d   TP                  4       '       g   R# TP                  4       T n        TP                  4       P#                  R4      T n        T P                   T P&                  R&   T P$                  T P&                  R&   T P&                  P)                  RR
4       T P+                  RR7      '       g   R# R#   \         d"   p\        P                  R	T4        R
p?R# R
p?ii ; i)ro  nousF) resolve_nous_runtime_credentialsHERMES_NOUS_MIN_KEY_TTL_SECONDS1800HERMES_NOUS_TIMEOUT_SECONDS15)min_key_ttl_secondstimeout_seconds
force_mintz"Nous credential refresh failed: %sNr;  r1  ru  r  nous_credential_refreshr  T)r=  r<  r  r!  r   r   r   r-  rk  r   r  r   r   rO   rP   r   r;  r  r1  r&  r  r  )rC   r  r!  r  r)  r;  r1  s   &$     rE   $_try_refresh_nous_client_credentials,AIAgent._try_refresh_nous_client_credentials$  sZ   ==..$--62I
	H4$'C		:[]c0d,e$f %bii0Mt&T U E ))I&99Z('3''w}}(C((0@0@}} (//4)-I&*.--J' 14822:S2TT+  	LL=sC	s   AF G
)GG
c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  G  s     % %4 %rH   c                   V P                   R 8w  g   \        V R4      '       g   R# V P                  R8w  d   R#  ^ RIHpHp V! 4       p\        T\        4      '       d   TP                  4       '       g   R# TP                  4       pY0P                  8X  d   R#  T P                  P                  4         T! T\        T RR4      4      T n        Y0n        ^ R	IHp T! T4      T n        R
#   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i  \         d     Lqi ; i  \         d"   p\        P!                  RT4        Rp?R# Rp?ii ; i)rq  r#  Frs  )r  r  z'Anthropic credential refresh failed: %sNr$  z?Failed to rebuild Anthropic client after credential refresh: %sr  T)r=  r*  r<  r"  r  r  r   r  r   rO   rP   r   r#  r   r  r`   r   r  r!  )rC   r  r  	new_tokenr)  r  s   &     rE   )_try_refresh_anthropic_client_credentials1AIAgent._try_refresh_anthropic_client_credentialsG  s%   ==00FZ8[8[ ==K'	_/1I
 )S))1B1BOO%	///	""((*	%;IwtUjlpGq%rD"
 #,;#29#= 3  	LLBCH	  		
  	NN\^ab	sA   C) D 5D) )D4DDD&%D&)E4EEc                $   < V ^8  d   QhRS[ RR/# )rq   r1  rr   Nr   )rs   rn   s   "rE   rt   r.  n  s     = =3 =4 =rH   c                :   ^ RI Hp T;'       g    RP                  4       pRV9   d   \        V4      V P                  R&   R
# RV9   d   ^ RIHp V! 4       V P                  R&   R
# RV9   d   RR	/V P                  R&   R
# V P                  P                  RR
4       R
# )rK   )_OR_HEADERSr   rw  r  r  r  r  r  r  N)r)  r3  r7  r   r&  r(  r  r  )rC   r1  r3  r  r  s   &&   rE   "_apply_client_headers_for_base_url*AIAgent._apply_client_headers_for_base_urln  s    6nn"++-
:%59+5FD 12$
2A5L5ND 12z)6BM5RD 12##$5t<rH   c                   < V ^8  d   QhRR/# rp   rd   )rs   rn   s   "rE   rt   r.  }  s     J J JrH   c                   \        VR R4      ;'       g    \        VRR4      p\        VRR4      ;'       g"    \        VRR4      ;'       g    V P                  pV P                  R8X  dk   ^ RIHpHp  V P                  P                  4        W n	        W0n
        V! W#4      V n        V P                  R8X  d	   V! V4      MR	V n        W n        W0n        R# W n        \        V\        4      '       d   VP!                  R
4      MTV n        V P                  V P"                  R&   V P                  V P"                  R&   V P%                  V P                  4       V P'                  RR7       R#   \         d     Li ; i)runtime_api_keyNaccess_tokenr   runtime_base_urlr1  rq  )r  r  rs  Fru  r;  credential_rotationr  )r`   r1  r=  r"  r  r  r   r  r   r#  r$  r<  r!  r;  rO   rP   r  r&  r4  r  )rC   rA  runtime_keyruntime_baser  r  s   &&    rE   _swap_credentialAIAgent._swap_credential}  sF   e%6=ccP^`bAcu&8$?tt75R\^bCcttgkgtgt==00W&&,,. '2#'3$%;K%VD"GK}}XcGc{'CinD$&L(M"4>|S4Q4Q++C0Wc)-I&*.--J'//>++3H+I!  s   3E) )E76E7error_contextc          
      ~   < V ^8  d   QhRS[ S[,          RS[RS[ S[S[S[3,          ,          RS[S[S[3,          /# )rq   r  has_retried_429r@  rr   )r   r   r   r   rP   r   r  )rs   rn   s   "rE   rt   r.    sO     3& 3& c]3& 	3&
  S#X/3& 
tTz	3&rH   c                  V P                   pVe   Vf   RV3# VR8X  dR   VP                  RVR7      pVe7   \        P                  R\	        VRR4       24       V P                  V4       R# RV3# VR8X  dZ   V'       g   R# VP                  RVR7      pVe7   \        P                  R	\	        VRR4       24       V P                  V4       R# R# VR
8X  d   VP                  4       pVe9   \        P                  R\	        VRR4       24       V P                  V4       RV3# VP                  R
VR7      pVe7   \        P                  R\	        VRR4       24       V P                  V4       R# RV3# )a]  Attempt credential recovery via pool rotation.

Returns (recovered, has_retried_429).
On 429: first occurrence retries same credential (sets flag True).
        second consecutive 429 rotates to next credential (resets flag).
On 402: immediately rotates (billing exhaustion won't resolve with retry).
On 401: attempts token refresh before rotating.
Fi  )r  r@  u3   Credential 402 (billing) — rotated to pool entry r  ?T  u6   Credential 429 (rate limit) — rotated to pool entry   u(   Credential 401 — refreshed pool entry u:   Credential 401 (refresh failed) — rotated to pool entry )TF)FT)r  mark_exhausted_and_rotater  r  r`   r>  try_refresh_current)rC   r  rB  r@  r  
next_entry	refresheds   &$$$   rE   _recover_with_credential_pool%AIAgent._recover_with_credential_pool  s    $$<;./))#77CWd7eJ%QRYZdfjloRpQqrs%%j1""/))#"""77CWd7eJ%TU\]gimorUsTtuv%%j1""#002I$FwyZ^`cGdFefg%%i0_,, 77CWd7eJ%XY`akmqsvYwXxyz%%j1""o%%rH   c                    < V ^8  d   QhRS[ /# rq   r  rU  )rs   rn   s   "rE   rt   r.    s     D DT DrH   c                    V P                   R 8X  d   V P                  4        V P                  P                  P                  ! R/ VB # )rq  rd   )r=  r/  r   r   r  )rC   r  s   &&rE   _anthropic_messages_create"AIAgent._anthropic_messages_create  s;    ==00::<%%..55C
CCrH   c                    < V ^8  d   QhRS[ /# rN  rU  )rs   rn   s   "rE   rt   r.    s     ;" ;"$ ;"rH   c                f  a aaa RRRR/oRR/oVVVV 3R lp\         P                  ! VRR7      pVP                  4        VP                  4       '       d   VP	                  RR	7       S P
                  '       g   K<   S P                  R
8X  dE   ^ RIHp S P                  P                  4        V! S P                  \        S RR4      4      S n	        M(SP                  R4      pVe   S P                  VRR7       \!        R4      hSR,          e
   SR,          hSR,          #   \         d     L5i ; i)a4  
Run the API call in a background thread so the main conversation loop
can detect interrupts without waiting for the full HTTP round-trip.

Each worker thread gets its own OpenAI client instance. Interrupts only
close that worker-local client, so retries and other requests never
inherit a closed transport.
r  Nr  r%  c            	      l  <  SP                   R 8X  d@   SP                  RR7      SR&   SP                  SSR,          \        SRR4      R7      SR&   MlSP                   R8X  d   SP	                  S4      SR&   MFSP                  R	R7      SR&   SR,          P
                  P                  P                  ! R/ SB SR&    SP                  R4      pVe   SP                  VRR7       R# R#   \         d   p T SR
&    Rp ? LARp ? ii ; i  SP                  R4      pTe   SP                  TRR7       i i ; i)rp  codex_stream_requestr  r%  _codex_on_first_deltaN)r%  r  r  rq  chat_completion_requestr  request_completerd   )r=  r  r  r`   rP  chatcompletionsr  r   r   r  )r  request_clientr  request_client_holderresultrC   s     rE   _call.AIAgent._interruptible_api_call.<locals>._call  sI   a==$556:6X6X`v6X6w)(3)-)?)?"4X>'.t5Ld'S *@ *F:&
 ]]&::)-)H)H)TF:&6:6X6X`y6X6z)(3)>x)H)M)M)Y)Y)`)`)ncm)nF:& "7!:!:8!D!-55nM_5` .	  $"#w$ "7!:!:8!D!-55nM_5` .sI   AC+ D %C+ 8D 9AC+ >D +D6D ;D  DD +D3Tr{  333333?r  rq  r  r$  interrupt_abortr  z!Agent interrupted during API call)r   r  r  is_aliver  r  r=  r"  r  r   r  r#  r`   r   r  r   InterruptedError)rC   r  r^  r  r  r[  r\  r]  s   ff    @@rE   _interruptible_api_callAIAgent._interruptible_api_call  s#    dGT2!)4 0	a 	a* E$7		jjllFF3F(((}}(<<R..4461G 33#D*?F2.
 *?)B)B8)L)5 ==nUf=g ''JKK'?&/!j!! ! s   =AD" (D" "D0/D0c                $   < V ^8  d   QhRS[ RR/# rq   r   rr   Nr   )rs   rn   s   "rE   rt   r.    s      s t rH   c                   \        V RR4      '       d/   V'       d'   VP                  4       '       d   RV n        RV,           pV P                  V P                  3 F  pVf   K	   V! V4       K  	  R#   \
         d     K&  i ; i)z;Fire all registered stream delta callbacks (display + TTS).r  Fr9  N)r`   r   r  r[  r  r   rC   r   cbs   && rE   r  AIAgent._fire_stream_delta  sr     4.664DJJLL',D$D=D--t/D/DEB~tH F ! s   $A22B Bc                $   < V ^8  d   QhRS[ RR/# ri  r   )rs   rn   s   "rE   rt   r.  !  s      # $ rH   c                n    RV n         V P                  pVe    V! V4       R# R#   \         d     R# i ; i)z&Fire reasoning callback if registered.TN)r   rX  r   rk  s   && rE   r  AIAgent._fire_reasoning_delta!  s?    '+$$$>4   s   % 44c                $   < V ^8  d   QhRS[ RR/# r  r   )rs   rn   s   "rE   rt   r.  +  s        rH   c                `    V P                   pVe    V! V4       R# R#   \         d     R# i ; i)aZ  Notify display layer that the model is generating tool call arguments.

Fires once per tool name when the streaming response begins producing
tool_call / tool_use tokens.  Gives the TUI a chance to show a spinner
or status line so the user isn't staring at a frozen screen while a
large tool payload (e.g. a 45 KB write_file) is being generated.
N)r\  r   )rC   r   rl  s   && rE   _fire_tool_gen_startedAIAgent._fire_tool_gen_started+  s9     ##>9   s    --c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  :  s     
 
t 
rH   c                L    V P                   RJ;'       g    \        V RR4      RJ# )z4Return True if any streaming consumer is registered.Nr  )r[  r`   rW   s   &rE   r  AIAgent._has_stream_consumers:  s5     &&d2 C Ct/6dB	
rH   r  c                &   < V ^8  d   QhRS[ RS[/# )rq   r  r  )r   rl  )rs   rn   s   "rE   rt   r.  A  s!     F" F"F"3;F"rH   c          
     j  a aaaaaaaaaa S P                   R8X  d!   SS n         S P                  S4      RS n        # RRRR/oRR/oRR/oRR/oR	\        P                  ! 4       /oVV3R
 loVVVVVV 3R loVVVV 3R loVVVVVVVV 3R lp\	        \
        P                  ! RR4      4      p\        R SP                  R. 4       4       4      ^,          pVR8  d   \        VR4      pMVR8  d   \        VR4      pMTp\        P                  ! VRR7      pVP                  4        VP                  4       '       Ed   VP                  RR7       \        P                  ! 4       SR	,          ,
          pW8  d   \        R SP                  R. 4       4       4      ^,          p	\        P!                  RWSP                  RR4      V	R 4       S P#                  R\%        V4       R SP                  RR4       R!V	R R"24        SP                  R4      p
V
e   S P'                  V
R#R$7        S P+                  R%R$7       \        P                  ! 4       SR	&   S P,                  '       g   EKC   S P                   R&8X  dE   ^ R'IHp S P2                  P5                  4        V! S P6                  \9        S R(R4      4      S n        M(SP                  R4      pVe   S P'                  VR)R$7       \;        R*4      hSR,          el   SR,          '       dT   \        P!                  R+SR,          4       \=        R,RRRR-7      p\=        R.\9        S RR4      \=        ^ VR/R07      .RR17      # SR,          hSR,          #   RS n        i ; i  \(         d     ELbi ; i  \(         d     ELai ; i  \(         d     Li ; i)2u  Streaming variant of _interruptible_api_call for real-time token delivery.

Handles all three api_modes:
- chat_completions: stream=True on OpenAI-compatible endpoints
- anthropic_messages: client.messages.stream() via Anthropic SDK
- codex_responses: delegates to _run_codex_stream (already streaming)

Fires stream_delta_callback and _stream_callback for each text token.
Tool-call turns suppress the callback — only text-only final responses
stream to the consumer.  Returns a SimpleNamespace that mimics the
non-streaming response shape so the rest of the agent loop is unchanged.

Falls back to _interruptible_api_call on provider errors indicating
streaming is not supported.
rp  Nr  r  r%  doneFr  r  c                  |   < S R ,          '       g   S'       d   RS R &    S! 4        R# R# R#   \          d     R# i ; i)rz  TN)r   )r  r  s   rE   _fire_first_deltaDAIAgent._interruptible_streaming_api_call.<locals>._fire_first_deltag  sC    $V,,,0!&)"$ 2@, ! s   , ;;c                   < ^ RI p \        \        P                  ! RR4      4      p\        \        P                  ! RR4      4      p/ S"CRRRR	R/R
V P	                  RVVRR7      /CpS&P                  RR7      S%R&   \        P                  ! 4       S$R&   S&P                  R4       S%R,          P                  P                  P                  ! R+/ VB p. p/ p\        4       p/ p/ p	Rp
RpRp. pRpRS&n        RpV EF  p\        P                  ! 4       S$R&   V'       g   RpS&P                  R4       S&P                  '       d    EMVP                  '       gc   \        VR4      '       d   VP                   '       d   VP                   p\        VR4      '       d   VP"                  '       d   VP"                  pK  VP                  ^ ,          P$                  p\        VR4      '       d   VP                   '       d   VP                   p\'        VRR4      ;'       g    \'        VRR4      pV'       d*   VP)                  V4       S!! 4        S&P+                  V4       V'       d   VP,                  '       dz   VP)                  VP,                  4       V'       g)   S!! 4        S&P/                  VP,                  4       RS#R&   M.S&P0                  '       d    S&P1                  VP,                  4       V'       Edt   VP4                  '       Eda   VP4                   EFO  pVP6                  e   VP6                  M^ pVP8                  ;'       g    RpVV	9  d   VV	V&   V'       d/   VV9   d(   VVV,          8w  d   \;        VR,R7      ^,           pVV	V&   V'       d   VVV&   V	V,          pVV9  d&   RVP8                  ;'       g    RRRRRRR R/R!R/VV&   VV,          pVP8                  '       d   VP8                  VR&   VP<                  '       d   VP<                  P>                  '       d1   VR,          R;;,          VP<                  P>                  ,          uu&   VP<                  P@                  '       d1   VR,          R ;;,          VP<                  P@                  ,          uu&   \'        VR!R4      pVf8   \        VR"4      '       d&   VPB                  ;'       g    / PE                  R!4      pVe(   \        VR#4      '       d   VPG                  4       pVVR!&   VR,          R,          pV'       g   EK  VV9  g   EK&  VPI                  V4       S!! 4        S&PK                  V4       EKR  	  VP                  ^ ,          PL                  '       d   VP                  ^ ,          PL                  p
\        VR4      '       g   EK  VP"                  '       g   EK  VP"                  pEK  	  RPO                  V4      ;'       g    RpRpV'       d   . p\Q        V4       Fn  pVV,          pVP)                  \S        VR,          VR,          VPE                  R!4      \S        VR,          R,          VR,          R ,          R$7      R%7      4       Kp  	  RPO                  V4      ;'       g    Rp\S        VVVVR&7      p\S        ^ TT
;'       g    R'R(7      p \S        R)\U        \V        PX                  ! 4       4      ,           VV .VR*7      #   \2         d     ELi ; i)-z#Stream a chat completions response.NHERMES_API_TIMEOUT      @HERMES_STREAM_READ_TIMEOUTg      N@r{   Tstream_optionsinclude_usager        >@)connectr  rL   r  chat_completion_stream_requestr  r%  r  z)waiting for provider response (streaming)r  Fzreceiving stream responserB  r
  r5  r4  r  r   )r!  r  r   r   ra   r   extra_contentmodel_extra
model_dumprb  )r  r   r  r   r   r   r   r5  rd  r  r  rE  zstream-r  rB  choicesr
  rd   r  )-r  rk  r   r-  Timeoutr  r  rR  rY  rZ  r  r3  r   r  r  r*  rB  r
  r  r`   r   r  r   r  r[  r   r   r  r  r   r   ra   r   r  r   r  r`  rs  rE  r  r5  r   rP   r8  r9  )'r  _base_timeout_stream_read_timeoutstream_kwargsr{   ro  tool_calls_acctool_gen_notified_last_id_at_idx_active_slot_by_idxrE  
model_namer   r=  	usage_obj_first_chunk_seenchunkr  rM  tc_deltaraw_idxdelta_idnew_slotr  rA  extrara   full_contentmock_tool_callsr   full_reasoningmock_messagemock_choicer|  r  deltas_were_sentlast_chunk_timer\  rC   s'                                    rE   _call_chat_completionsIAIAgent._interruptible_streaming_api_call.<locals>._call_chat_completionso  s   "!")),@&"IJM#(3OQU)V#W 

$ ?D"96>> -'	 * 	
M /3.P.P7 /Q /!(+
 $(99;OC   !LM*8499EELL]}]F"$M#%N%(U
 %'O(* MJD$&OI ,1D( %'+yy{$((,%(()DE,,,}}}ug..5;;;%*[[
ug..5;;;$)KK	a(..5'**u{{{!&J ")0CT!J!o!ogV[]hjnNo!#**>:%'..~> U]]]!((7))+//>26(/  555% $ : :5== I
 5U---$)$4$44<NN4N(..TU#+;;#4#4" #*==;B/8$ '? : (OG,D D'*>2'F'JH;C/8#7?OG41':n4 $hkk&7&7R &
 *VRb,I /	3N3/ !/s 3#;;;*2++E$K#,,,'00555 %j 1& 9X=N=N=S=S S 9'00::: %j 1+ >(BSBSB]B] ] > '/4 H =WX}-M-M%-%9%9%?%?R$D$D_$UE ,&ul;;(-(8(8(:5:E/2$Z084C/@$@-11#6-/ 77=] %5` ==#111$)MM!$4$B$BM 5'**u{{{ %IY  ^ 77=199TL"O"$!.1C',B#**?d8Z&(ff_&=!0!#J!7&(n[&A"	,  2  WW_5==N*$*"0	L *$+55vK
 #s4::<00 $	 s $- % $%s   [<<\
\c                 v  < Rp RSn         \        P                  ! 4       SR&   SP                  P                  P                  ! R/ SB ;_uu_ 4       pV EF4  pSP
                  '       d    EM \        VRR4      pVR8X  d_   \        VRR4      pV'       dH   \        VRR4      R8X  d4   Rp \        VR	R4      pV'       d   S
! 4        SP                  V4       K  K  K  K  VR
8X  g   K  \        VRR4      pV'       g   K  \        VRR4      pVR8X  d<   \        VRR4      pV'       d%   V '       g   S
! 4        SP                  V4       K  K  K  VR8X  g   EK  \        VRR4      p	V	'       g   EK  S
! 4        SP                  V	4       EK7  	  VP                  4       uuRRR4       #   + '       g   i     R# ; i)zStream an Anthropic Messages API response.

Fires delta callbacks for real-time token delivery, but returns
the native Anthropic Message object from get_final_message() so
the rest of the agent loop (validation, tool extraction, etc.)
works unchanged.
Fr  r   Ncontent_block_startcontent_blocktool_useTra   content_block_deltar  
text_deltar   r   thinking_deltar8  rd   )r   r  r   r   r{   r  r`   rs  r  r  get_final_message)has_tool_user{   r  r  rA  r   r  
delta_typer   thinking_textr|  r  r  rC   s             rE   _call_anthropicBAIAgent._interruptible_streaming_api_call.<locals>._call_anthropic-  s    !L+0D( $(99;OC ''0077E*EE#E000!(!=J!%:: ' E WUFD%AZ%O+/L(/vt(DI( 1 3 $ ; ;I F  ) &P5 $'<< 'w = 5)0)EJ)\9'.ufb'A#'$5$7$($;$;D$A 1=4 ",/?!?07z20N#0=$5$7$($>$>}$M9 $> //1A FEEEs+   BF'(F'?0F'0"F'F'0,F''F8	c                    <a ^ RI p \        \        P                  ! R^4      4      p \	        V^,           4       Fe  p SP
                  R8X  d   SP                  4        S! 4       SR&   M
S! 4       SR&    SP                  R4      pVe   SP                  VRR7       R# R# 	  SP                  R4      pVe   SP                  VRR7       R# R#   \         EdC   pSR,          '       dM   \        P                  R	T4       TSR
&    Rp? SP                  R4      pTe   SP                  TRR7       R# R# \        Y@P                  T P                  T P                  34      p\        Y@P                   T P"                  \$        34      pRpT'       g   T'       g   ^ RIHp \        YH4      '       di   \+        TRR4      '       gV   \-        T4      P/                  4       oRp	\0        ;QJ d    T3R lT	 4       F  '       g   K   RM	  RM! T3R lT	 4       4      pT'       g   T'       g
   T'       Ed   Y!8  d   \        P3                  RT^,           T^,           \5        T4      P6                  T4       SP9                  R\5        T4      P6                   RT^,            RT^,            R24       SP                  R4      p
T
e   SP                  T
RR7       RSR&    SP;                  RR7       M  \         d     Mi ; i Rp?EK  SP9                  RT^,            R24       \        P                  RT^,           T4       MZ\-        T4      P/                  4       pRT9   ;'       d    RT9   pT'       d   SP=                  R4       \        P3                  RT4        \>        P>                  ! 4       SR&   SPA                  S4      SR&   M  \         d   pTSR
&    Rp?MRp?ii ; i Rp? SP                  R4      pTe   SP                  TRR7       R# R# Rp?ii ; i  SP                  R4      pTe   SP                  TRR7       i i ; i) rK   NHERMES_STREAM_RETRIESrq  r  r%  stream_request_completer  r  z9Streaming failed after partial delivery, not retrying: %sr  F)APIErrorr  c              3   .   <"   T F
  pVS9   x  K  	  R # 5irU   rd   )r   phrase_err_lower_sses   & rE   r   KAIAgent._interruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>  s      7"2C %+n$<2Cs   TzJStreaming attempt %s/%s failed (%s: %s), retrying with fresh connection...u'   ⚠️ Connection to provider dropped (u   ). Reconnecting… (attempt ru  r  stream_retry_cleanupstream_retry_pool_cleanupu(   ❌ Connection to provider failed after uM    attempts. The provider may be experiencing issues — try again in a moment.zTStreaming exhausted %s retries on transient error, falling back to non-streaming: %sr{   znot supportedu   
⚠  Streaming is not supported for this model/provider. Falling back to non-streaming.
   To avoid this delay, set display.streaming: false in config.yaml
zCStreaming failed before delivery, falling back to non-streaming: %sr  )
connection lostconnection resetconnection closedzconnection terminatednetwork errornetwork connection
terminatedzpeer closedzbroken pipezupstream connect error)!r  r   r   r-  r  r=  r/  r   r  r   r  r   rO   r  ConnectTimeoutPoolTimeoutr  r  r  openair  r`   rP   r7  r   r  r   re   r  r  r  r  rf  )r  _max_stream_retries_stream_attemptr[  r  _is_timeout_is_conn_err_is_sse_conn_err	_APIError_SSE_CONN_PHRASESstale
_err_lower_is_stream_unsupportedfallback_errr  r  r  r  r  r  r\  r]  rC   s                 @rE   r^  8AIAgent._interruptible_streaming_api_call.<locals>._call]  s`   ""%bii0G&K"LDh',-@1-D'EO~==,@@ JJL1@1BF:.1G1IF:.t "7!:!:8!D!-55nMf5g .E (FB "7!:!:8!D!-55nMf5g .u % w+E22 #NN []^ /0F7O"` "7!:!:8!D!-55nMf5g ._ '1 2 2F4I4I6K]K]^' (2 3 3V5O5OQ`a( ,1(*<D)!77=Z^@_@_14Q5" 1 473 7"2C7"333 7"2C7" 4" 0
 ',:J:J  /D &%H$3a$7$7!$;$(G$4$4$%!" !% 1 1'((,Q(8(8'9 :00?!0C/DAFY\]F]E^^_%a!" )>(A(A((K#(#4$($E$E(-6L %F %& GK$9($C!)$($G$G/J %H %& (1 !)$(!) ( -- J#6#:"; <9!9 #NN!D 3a 7 !	 *-QJ (J 6 !B !B$3z$A 3  6 $ 0 0%7!" #KK e !
; 4899;OC0151M1Mj1YF:.( ;.:F7O;!6!:!:8!D!-55nMf5g .uwr "7!:!:8!D!-55nMf5g .s   P  6C4P  !P  P*PP  6A#PA$PP!P)P2B)PK/.P/K=:P<K==P P  AP'P5'P,O
	P
O$OPO$$P'P  PP   +QHERMES_STREAM_STALE_TIMEOUTg     f@c              3   J   "   T F  p\        \        V4      4      x  K  	  R # 5irU   rQ   rP   r   r)  s   & rE   r   <AIAgent._interruptible_streaming_api_call.<locals>.<genexpr>  s     N/M!#c!f++/M   !#r   r  g     r@P  g      n@Tr{  r`  ra  c              3   J   "   T F  p\        \        V4      4      x  K  	  R # 5irU   r  r  s   & rE   r   r     s     S4Rqs3q6{{4Rr  uq   Stream stale for %.0fs (threshold %.0fs) — no chunks received. model=%s context=~%s tokens. Killing connection.rB  r  r  u%   ⚠️ No response from provider for z
s (model: z, context: ~z tokens). Reconnecting...stale_stream_killr  stale_stream_pool_cleanuprq  rb  r$  stream_interrupt_abortz+Agent interrupted during streaming API callz`Partial stream delivered before error; returning stub response to prevent duplicate messages: %sr  r  zpartial-stream-stubrd  r  r  )r=  rV  rf  r  rk  r   r-  r  r   r   r   r  r  rd  r  r  r   r  r   r  r   r  r  r"  r  r   r  r#  r`   re  r   )rC   r  r  r^  _stream_stale_timeout_base_est_tokens_stream_stale_timeoutr  _stale_elapsed_est_ctxrcr  r[  	_stub_msgr  r  r|  r  r  r  r\  r]  s   ffd           @@@@@@@@rE   !_interruptible_streaming_api_call)AIAgent._interruptible_streaming_api_callA  s   $ ==--
 *8D&233J?-1*dGT2!)4 0#UO!5> 		,	|	 |	|.	2 .	2`I	h I	hV &+2995RTY+Z%[" Nz~~j"/MNNRSS $'(BE$J!6!$'(BE$J!$>!E$7		jjllFF3F
 "YY[?3+??N5SJNN:r4RSSWXXG"NN7I68A,	 !!;C<O;P Q)~~gyAB C!!)! -&'.228<B~99"EX9Y
77?Z7[
 (,yy{$(((}}(<<R..4461G 33#D*?F2.
 *?)B)B8)L)5 ==nUm=n ''TUU'?&&& A7O
 ,$dt&*	 ',!$;,&    /!j!!W .2*j !  ! ( ! sH   M4 (N  -N -AN$ (N$ 4	M= NNN! N!$N21N2c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.  K  s     x1 x1 x1rH   c                @
   V P                   \        V P                  4      8  d   R# V P                  V P                   ,          pV ;P                   ^,          un         VP                  R4      ;'       g    RP	                  4       P                  4       pVP                  R4      ;'       g    RP	                  4       pV'       d	   V'       g   V P                  4       #  ^ RIHp VP                  R4      ;'       g    RP	                  4       ;'       g    RpVP                  R4      ;'       g    RP	                  4       ;'       g    RpV'       d>   R	VP                  4       9   d)   V'       g!   \        P                  ! R
4      ;'       g    RpV! W#RVVR7      w  rxVf(   \        P                  ! RV4       V P                  4       # Rp	\        VP                  4      p
VR8X  d   Rp	MWVR8X  g5   V
P                  R4      P                  4       P!                  R4      '       d   Rp	MV P#                  V
4      '       d   Rp	V P$                  p\'        V\        4      '       d   TM
\        V4      V n        W n        Wn        Wn        RV n        V	R8X  d   ^ RIHpHpHp VR8X  d&   VP6                  ;'       g    V! 4       ;'       g    RMVP6                  ;'       g    RpWn        Wn        \;        VRR4      V n        V! WP<                  4      V n        V! V4      V n         RV n!        / V n"        M,VP6                  V n        Wpn!        RVP6                  RV
/V n"        V	R8H  pRV
P                  4       9   ;'       d    RVP                  4       9   ;'       g    TV n#        \I        V R4      '       d   V PJ                  '       d   ^ RI&H'p V! V P$                  V P                  V P6                  V P(                  R7      pV P$                  V PJ                  n        V P                  V PJ                  n        V P6                  V PJ                  n        V P(                  V PJ                  n        VV PJ                  n(        \S        VV PJ                  PT                  ,          4      V PJ                  n+        V PY                  RV RV 24       \        PZ                  ! RWV4       R#   \\         d3   p\        P^                  ! RTT4       T P                  4       u Rp?# Rp?ii ; i)u  Switch to the next fallback model/provider in the chain.

Called when the current model is failing after retries.  Swaps the
OpenAI client, model slug, and provider in-place so the retry loop
can continue with the new backend.  Advances through the chain on
each call; returns False when exhausted.

Uses the centralized provider router (resolve_provider_client) for
auth resolution and client construction — no duplicated provider→key
mappings.
Fr<  r   rB  r  r1  Nr;  z
ollama.comOLLAMA_API_KEYT)rB  r  explicit_base_urlexplicit_api_keyz.Fallback to %s failed: provider not configuredro  rr  rp  rs  ru  rv  rq  r  rw  r~  rc  r  r  u5   🔄 Primary model failed — switching to fallback: z via u"   Fallback activated: %s → %s (%s)z"Failed to activate fallback %s: %s)0r0  rQ   r/  r   r   r7  _try_activate_fallbackr)  r  r   r-  r   r   rP   r1  r  r  r  rB  rO   r<  r=  r1  r"  r  r  r  r;  r#  r`   r$  r   r!  r%  r&  r
  r*  rc  r  r  r  r   r  rs  r  r  r   r  )rC   r  fb_providerfb_modelr  fb_base_url_hintfb_api_key_hint	fb_clientr  fb_api_modefb_base_urlr  r  r  r  r~  r{  r  fb_context_lengthr  s   &                   rE   r  AIAgent._try_activate_fallbackK  se    3t';';#<<!!$"6"67!vvj)//R668>>@FF7O))r002(..00
_	1F !#z 2 8 8b??AIIT!vvi066B==?GG4O  L4D4J4J4L$LUd"$)),<"="E"E2t"2!02LI  D! 2244 -Ki001Kn,/+{/A/A#/F/L/L/N/W/WXd/e/e2++K88/

I%/#%>%>CMDJ'M'M'M'+D$22ttZeitZt!2!2!U!U6M6O!U!USU  |E  |M  |M  |S  |S  QS,*7'+29j$+O()?OgOg)h&+:=+I("&(#  )00'y00'# #.1E"E!2!2!44UUX^^EU9U ' '& $ t122t7N7N7NI$<JJ LL4==%! 15

''-37==''026,,''/37==''09J''6;>%(?(?(Q(QQ<''8 G*E+0 LL4[  	1MM>!L..00	1s   S  <S  S  /S  
S  S  /S  ;S  AS  $S  >A9S  8S  S  BS  <S  +S  DS   T+'TTTc                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     > >$ >rH   c                   V P                   '       g   R# V P                  p VR,          V n        VR,          V n        VR,          V n        VR,          V n        VR,          V n        \        VR,          4      V n        VR,          V n	        V P
                  R	8X  dU   ^ R
I
Hp VR,          V n        VR,          V n        V! VR,          VR,          4      V n        VR,          V n        RV n        M)V P#                  \        VR,          4      RRR7      V n        V P$                  pVR,          Vn        VR,          Vn        VR,          Vn        VR,          Vn        VR,          Vn        VR,          Vn        RV n         ^ V n        \,        P.                  ! RV P                  V P                  4       R#   \0         d#   p\,        P2                  ! RT4        Rp?R# Rp?ii ; i)a  Restore the primary runtime at the start of a new turn.

In long-lived CLI sessions a single AIAgent instance spans multiple
turns.  Without restoration, one transient failure pins the session
to the fallback provider for every subsequent turn.  Calling this at
the top of ``run_conversation()`` makes fallback turn-scoped.

The gateway creates a fresh agent per message so this is a no-op
there (``_fallback_activated`` is always False at turn start).
FrB  r<  r1  r=  r;  r  r  rq  rb  r  r  r  Nrestore_primaryTr  r  r  r  r  r  r  z.Primary runtime restored for new turn: %s (%s)z%Failed to restore primary runtime: %s)r1  rt  rB  r<  r1  r=  r;  r   r&  r
  r"  r  r#  r$  r   r!  r%  r.  rc  r  rs  r0  r   r  r   r   )rC   rtr  ccr  s   &    rE   _restore_primary_runtime AIAgent._restore_primary_runtime  s    '''""/	GDJzNDMzNDMzNDMi=DL"&r/':";D')*>'?D$ }} 44J*,-@*A'+-.B+C()?*+R0D-E*& ,..B+C(""88O,-, 9  ((B,-BH23BK01BJ23BK "#> ?B"$%B"CB (-D$#$D LL@

DMM  	OOCQG	s   FF7 7G$GG$c                2   < V ^8  d   QhRS[ RS[RS[RS[/# )rq   	api_errorretry_countmax_retriesrr   )r   r   r   )rs   rn   s   "rE   rt   r.    s3     K K"K47KFIK	KrH   c          
        V P                   '       d   R# \        V4      P                  pW@P                  9  d   R# V P	                  4       '       d   R# V P
                  ;'       g    RP                  4       P                  4       pVR9   d   R#  \        V RR4      e     V P                  V P                  RRR7       V P                  p\        VR,          4      V n        VR	,          V n        VR
,          V n        VR,          V n        VR,          V n        VR,          V n        V P"                  R8X  dU   ^ RIHp VR,          V n        VR,          V n        V! VR,          VR,          4      V n        VR,          V n        RV n
        M)V P3                  \        VR,          4      RRR7      V n
        \5        ^V,           ^4      pV P7                  V P8                   RV RV P
                   RV R2RR7       \:        P<                  ! V4       R#   \         d     ELci ; i  \         d#   p	\>        P@                  ! RT	4        Rp	?	R# Rp	?	ii ; i)uF  Attempt one extra primary-provider recovery cycle for transient transport failures.

After ``max_retries`` exhaust, rebuild the primary client (clearing
stale connection pools) and give it one more attempt before falling
back.  This is most useful for direct endpoints (custom, Z.AI,
Anthropic, OpenAI, local models) where a TCP-level hiccup does not
mean the provider is down.

Skipped for proxy/aggregator providers (OpenRouter, Nous) which
already manage connection pools and retries server-side — if our
retries through them are exhausted, one more rebuilt client won't help.
Fr   r%  Nprimary_recoveryTr  r  rB  r<  r1  r=  r;  rq  rb  r  r  r  u   🔁 Transient z on u    — rebuilt client, waiting z"s before one last primary attempt.r  z%Primary transport recovery failed: %s)r   znous-research)!r1  r   re   _TRANSIENT_TRANSPORT_ERRORSr  r<  r   r7  r`   rw  r%  r   rt  r   r&  rB  r1  r=  r;  r"  r  r#  r$  r   r!  r.  r   r  rL  r  sleepr   r   )
rC   r  r   r  
error_typeprovider_lowerr  r  	wait_timer  s
   &&$$      rE   _try_recover_primary_transport&AIAgent._try_recover_primary_transport  s-    ### )_--
=== ""$$----2446<<>66-	tXt,8--,>t .  &&B"&r/':";DGDJzNDMzNDMzNDMi=DL}} 44J*,-@*A'+-.B+C()?*+R0D-E*& ,..B+C(""88O,-- 9  AOQ/ILL??#?:,d4==/ R++4+5WY  
 JJy!G ! H  	OOCQG	s=   H%  H >EH% H"H% !H""H% %I0IIc                &   < V ^8  d   QhRS[ RS[/# r  r  )rs   rn   s   "rE   rt   r.  ^  s      # $ rH   c                    \        V \        4      '       g   R # V  F4  p\        V\        4      '       g   K  VP                  R4      R9   g   K3   R# 	  R # )Fr   T>   r  r  )rO   r   r   r   )r   r   s   & rE   _content_has_image_parts AIAgent._content_has_image_parts]  sB    '4((D$%%$((6*:>Z*Z  rH   c                L   < V ^8  d   QhRS[ RS[S[ S[S[,          3,          /# )rq   r  rr   )rP   r  r   r	   )rs   rn   s   "rE   rt   r.  g  s*      C E#xPT~BU<V rH   c           
     ^   \        T ;'       g    R 4      P                  R4      w  rpRpVP                  R4      '       dM   V\        R4      R P	                  R^4      ^ ,          P                  4       pVP                  R4      '       d   TpRRR	R
RRRRRR/P                  VR4      p\        P                  ! RVRR7      pV;_uu_ 4        VP                  \        P                  ! V4      4       RRR4       \        VP                  4      p\        V4      V3#   + '       g   i     L2; i)r   r  z
image/jpegdata:N;zimage/z	image/pngz.pngz	image/gifz.gifz
image/webpz.webpz.jpgz	image/jpganthropic_image_F)r  suffixdelete)rP   	partitionr  rQ   r  r   r   tempfileNamedTemporaryFilerL   base64	b64decoder	   ra   )	r  headerr  rR   mime	mime_partr  tmpr   s	   &        rE    _materialize_data_url_for_vision(AIAgent._materialize_data_url_for_visionf  s   ioo2.88=4W%%s7|}-33C;A>DDFI##H-- '&
 #dF
 	 ))1CF[`aSIIf&&t,- CHH~4y$ Ss   &DD,	c                ,   < V ^8  d   QhRS[ RS[ RS[ /# )rq   r  r   rr   r   )rs   rn   s   "rE   rt   r.  {  s#     1 1 13 1SV 1rH   c                   \         P                  ! \        T;'       g    R 4      P                  R4      4      P	                  4       pV P
                  P                  V4      pV'       d   V# RRRR/P                  VR4      pRp\        T;'       g    R 4      pRpVP                  R4      '       d   V P                  V4      w  rxR p	 ^ R	I	H
p
 \        P                  ! V
! WvR
7      4      p\        V\        4      '       d   \        P                  ! V4      M/ pVP                  R4      ;'       g    R P!                  4       p	V'       d(   VP%                  4       '       d    VP'                  4        T	'       g   Rp	RT RT	 R2pT'       d8   \        T;'       g    R 4      P                  R4      '       g   TRT R2,          pYP
                  T&   T#   \"         d   pRT 2p	 Rp?LRp?ii ; i  \(         d     Li ; i  T'       d;   TP%                  4       '       d$    TP'                  4        i   \(         d     i i ; ii i ; i)r   r  r  r   ztool resultrm  zDescribe everything visible in this image in thorough detail. Include any text, code, UI, data, objects, people, layout, colors, and any other notable visual information.Nr  )vision_analyze_tool)r  user_promptri  zImage analysis failed: zImage analysis failed.z[The z- attached an image. Here's what it contains:
r  z@
[If you need a closer look, use vision_analyze with image_url: )r  r  rP   r  r  r  r   r  r  tools.vision_toolsr#  asyncior  rO   r   r   r   r   r>  unlinkrM   )rC   r  r   	cache_keycached
role_labelanalysis_promptvision_sourcecleanup_pathr  r#  result_jsonr]  r  notes   &&&            rE   &_describe_image_for_anthropic_fallback.AIAgent._describe_image_for_anthropic_fallback{  s   NN3yB#7#>#>w#GHRRT	5599)DM M
 #dF
 	
8 	 IOO,'+##G,,*.*O*OP]*^'M	>!++#mYK 1;;0L0LTZZ,RTF!::j177R>>@K  3 3 5 5 '') 2Kzl"PQ\P]]^_Y__"!5!@!@!I!ISTaSbbcdD ;?,,Y7'  	83A37K	8    3 3 5 5 '')  !6|sg   A(G 1G !G0 G-G(#H (G--H 0G>=G>I!H21I2I =I?I  Ic                ,   < V ^8  d   QhRS[ RS[RS[ /# )rq   r   r   rr   rN  )rs   rn   s   "rE   rt   r.    s'     *[ *[S *[ *[ *[rH   c                   V P                  V4      '       g   V# . p. pV EF  p\        V\        4      '       d8   VP                  4       '       d    VP	                  VP                  4       4       KQ  \        V\
        4      '       g   Ki  VP                  R 4      pVR9   dO   \        VP                  RR4      ;'       g    R4      P                  4       pV'       d   VP	                  V4       K  VR9   d   VP                  R/ 4      p\        V\
        4      '       d   VP                  RR4      M\        T;'       g    R4      p	V	'       d"   VP	                  V P                  W4      4       MVP	                  R4       EKb  \        VP                  RR4      ;'       g    R4      P                  4       pV'       g   EK  VP	                  V4       EK  	  RP                  R V 4       4      P                  4       p
RP                  R	 V 4       4      P                  4       pV
'       d   V'       d   V
 RV 2# V
'       d   V
# V'       d   V# R
# )r   r   r   r  r  z:[An image was attached but no image source was available.]r9  c              3   8   "   T F  q'       g   K  Vx  K  	  R # 5irU   rd   )r   r/  s   & rE   r   8AIAgent._preprocess_anthropic_content.<locals>.<genexpr>  s     BkdTTTk   	
r  c              3   8   "   T F  q'       g   K  Vx  K  	  R # 5irU   rd   )r   r   s   & rE   r   r5    s     ?JD$44Jr6  zI[A multimodal message was converted to text for Anthropic compatibility.]>   r   r  >   r  r  )	r  rO   rP   r   r   r   r   r0  r  )rC   r   r   
text_partsimage_notesr   rS  r   
image_datar  r  r  s   &&&         rE   _preprocess_anthropic_content%AIAgent._preprocess_anthropic_content  s   ,,W55N "
!#D$$$::<<%%djjl3dD))HHV$E..488FB/5526<<>%%d+44!XXk26
9CJPT9U9UJNN5"5[^_i_o_omo[p	&&t'R'RS\'cd&&'cdtxx+11r288:Dt!!$'5 8 BkBBHHJ?J??EEGfXT&**MMZrH   c                &   < V ^8  d   QhRS[ RS[ /# rq   rG  rr   r   )rs   rn   s   "rE   rt   r.    s        rH   c           
       a  \         ;QJ d    V 3R  lV 4       F  '       g   K   RM	  RM! V 3R  lV 4       4      '       g   V# \        P                  ! V4      pV Fb  p\        V\        4      '       g   K  S P                  VP                  R4      \        VP                  RR4      ;'       g    R4      4      VR&   Kd  	  V# )c              3      <"   T F=  p\        V\        4      ;'       d!    SP                  VP                  R 4      4      x  K?  	  R# 5i)r   N)rO   r   r  r   )r   r   rC   s   & rE   r   >AIAgent._prepare_anthropic_messages_for_api.<locals>.<genexpr>  s>      
# sD!WWd&C&CCGGIDV&WW#s
   A)ATFr   r   rm  )r   r  r%  rO   r   r;  r   rP   )rC   rG  transformedr   s   f&  rE   #_prepare_anthropic_messages_for_api+AIAgent._prepare_anthropic_messages_for_api  s    s 
#
sss 
#
 
 
  mmL1Cc4((!??	"CGGFF+55v6C	N  rH   c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     Y Y$ YrH   c                    \        V RR4      ;'       g    RP                  4       R9   d   R# \        V RR4      ;'       g    RP                  4       pRV9   ;'       g    RV9   ;'       g    RV9   # )	zTrue when using an anthropic-compatible endpoint that preserves dots in model names.
Alibaba/DashScope keeps dots (e.g. qwen3.5-plus).
OpenCode Go keeps dots (e.g. minimax-m2.7).r<  r   Tr1  	dashscopealiyuncszopencode.ai/zen/go>   r  opencode-go)r`   r7  )rC   bases   & rE   _anthropic_preserve_dots AIAgent._anthropic_preserve_dots  sp     D*b)//R668<VVj"-33::<d"XXjD&8XX<PTX<XXrH   c                &   < V ^8  d   QhRS[ RS[/# r>  )r   r   )rs   rn   s   "rE   rt   r.    s     T Td Tt TrH   c                T  a V P                   R8X  d   ^ RIHp V P                  V4      p\	        V RR4      pV'       d   VP
                  MRpV! V P                  VV P                  V P                  V P                  V P                  V P                  4       VR7      # V P                   R8X  Ed   RpTpV'       d`   V^ ,          P                  R4      R	8X  dC   \        V^ ,          P                  R
4      ;'       g    R4      P                  4       pVR,          pV'       g   \        pRV P                   P#                  4       9   ;'       g    RV P                   P#                  4       9   pRpRp	V P                  '       dw   \%        V P                  \&        4      '       dW   V P                  P                  R4      RJ d   Rp	M4V P                  P                  R4      '       d   V P                  R,          pRV P                  RVRV P)                  V4      RV P+                  4       RRRRRR/p
V'       g   V P,                  V
R&   V	'       d2   V'       d   V P/                  4       pVe   WR&   MRVRR/V
R&   R.V
R&   MV'       g   . V
R&   V P                  e   V P                  V
R &   V
# TpRpV F  p\%        V\&        4      '       g   K  R!V9   d   Rp MjVP                  R"4      p\%        V\0        4      '       g   KO  V F-  p\%        V\&        4      '       g   K  R#V9   g
   R$V9   g   K+  Rp M	  V'       g   K   M	  V'       d   \2        P4                  ! V4      pV F  p\%        V\&        4      '       g   K  VP7                  R!R4       VP                  R"4      p\%        V\0        4      '       g   KV  V F?  p\%        V\&        4      '       g   K  VP7                  R#R4       VP7                  R$R4       KA  	  K  	  V P                  ;'       g    RP#                  4       oV'       d   V^ ,          P                  R4      R	8X  df   \8        ;QJ d#    V3R% l\:         4       F  '       g   K   RM	  RM! V3R% l\:         4       4      '       d   \1        V4      p/ V^ ,          CRR&/CV^ &   / pV P<                  '       d   V P<                  VR'&   V P>                  '       d   V P>                  VR(&   V P@                  '       d   V P@                  VR)&   V PB                  '       d   V PB                  VR*&   V PD                  '       d   RVR+&   V PF                  '       d   V PF                  VR,&   RV P                  R-VR.\I        \J        PL                  ! R/R04      4      /pV P                  '       d   V P                  VR&   V P                  e,   VPO                  V PQ                  V P                  4      4       M]V PS                  4       '       dH   R1V P                  ;'       g    RP#                  4       9   d    ^ R2IH*p V! V P                  4      pVVR3&   / pV PS                  4       pRV PX                  9   ;'       g    RV PX                  9   pV'       d   V'       d   VVR4&   R5V PX                  9   pV P[                  4       '       ds   V'       d   V P/                  4       pVe   VVR&   MPV P                  e:   \'        V P                  4      pV'       d   VP                  R4      RJ d   MVVR&   M	RRRR/VR&   V'       d   R6.VR7&   V'       d   VVR8&   R9V PX                  9   d6   \]        V R:4      '       d$   V P,                  '       d   R;V P,                  /VR<&   V#   \V         d     ELUi ; i)=z9Build the keyword arguments dict for the active API mode.rq  build_anthropic_kwargsrc  N)rB  r   r  r^  r_  is_oauthpreserve_dotsr  rp  r   r   r  r   :   NNmodels.github.air  mediumTr  FeffortrB  r6  r7  r  r@  r  rB  r9  rA  r4  r7  zreasoning.encrypted_contentr:  r;  r  r   r  r  c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   )r   r|  r  s   & rE   r   ,AIAgent._build_api_kwargs.<locals>.<genexpr>j  s     E/D!%/Dr  	developeronlyignoreordersortrequire_parametersdata_collectionr   r  r  r  r~  )_get_anthropic_max_outputr^  r<  nousresearchproduct=hermes-agenttags
extra_bodyzx.airS  zx-grok-conv-idextra_headers)/r=  r"  rP  rC  r`   r  rB  r  r^  r_  r!  rK  r   rP   r   r   r1  r7  rO   r   r%  r  rS  #_github_models_reasoning_extra_bodyr   r  r%  r  r   r.   rM  rN  rO  rP  rQ  rR  rk  r   r-  ru  r  r  r`  r   r8  _supports_reasoning_extra_bodyr*  )rC   rG  rP  rq  rW  r6  payload_messagesis_github_responsesreasoning_effortreasoning_enabledr  github_reasoningsanitized_messagesneeds_sanitizationr   r   r   provider_preferencesr  r`  _model_output_limitrd  _is_openrouter_is_github_models_is_nousr  r  s   &&                        @rE   _build_api_kwargsAIAgent._build_api_kwargs  s   ==00F!%!I!I,!W d$8$?G07g,,TG)jj+jj??!%!6!611";;=&	 	 ==--L+Q 3 3F ;x G"<?#6#6y#A#G#GRHNNP#/#3 5 #dmm&9&9&;; D D*dmm.A.A.CC    ( $$$$D4I4I4)P)P((,,Y75@(-%**..x88'+'<'<X'F$ ??@PQ..0v%tF '-1__)* & (,'O'O'Q$'3.>{++35EyRX*YF;')F(GF9%($&y!*.2oo*+M)"Cc4((&#-%)".J*d++!+I%i66  I-1Cy1P-1* ", &%!  $ !%|!<)!#t,, /6 WW\2
j$//%/	%i66%MM)T:%MM*<dC &0 *" 

((b//1"1%))&1X=E/DEE/DEEE "&&8!9$R'9!'<$Rfk$Rq!!!!!+/+A+A (!!!-1-C-C *,0,@,@ )+/+=+= (+++9= !56(((6:6S6S !23 TZZ*uRYY';VDE


 :::"&**Jw??&d44T__EF$$&&8

8H8Hb7O7O7Q+QM&?

&K#+>
<( 
002$"6"66 ? ?&$*>*>> 	  N%9Jz"!T%9%99..00 #'#K#K#M #/.>J{+((4d334B  BFF9$5$>24
;/ "4 (/J{+ "8!9Jv'1J|$
 T)))gdL.I.Idooo+;T__*MJ'i  s   4^ ^'&^'c                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s      T  T  TrH   c                  a RV P                   9   d   R# RV P                   9   d   R# RV P                   9   g   RV P                   9   d#    ^ RIHp \        V! V P                  4      4      # RV P                   9  d   R# R	V P                   9   d   R# V P                  ;'       g    R
P                  4       oRp\        ;QJ d    V3R lV 4       F  '       g   K   R# 	  R# ! V3R lV 4       4      #   \
         d     R# i ; i)a  Return True when reasoning extra_body is safe to send for this route/model.

OpenRouter forwards unknown extra_body fields to upstream providers.
Some providers/routes reject `reasoning` with 400s, so gate it to
known reasoning-capable model families and direct Nous Portal.
ra  Tzai-gateway.vercel.shrT  r  github_model_reasoning_effortsFrw  zapi.mistral.air   c              3   F   <"   T F  pSP                  V4      x  K  	  R # 5irU   )r  )r   r  rB  s   & rE   r   9AIAgent._supports_reasoning_extra_body.<locals>.<genexpr>  s!     S:R5##F++:Rs   !)z	deepseek/z
anthropic/zopenai/zx-ai/zgoogle/gemini-2z
qwen/qwen3)r8  r(  ry  r   rB  r   r7  r   )rC   ry  reasoning_model_prefixesrB  s   &  @rE   rg  &AIAgent._supports_reasoning_extra_body  s     T111!T%9%99!5!559PTXThTh9hL:4::FGG t333t333!!r((*$
  sS:RSssSsSsS:RSSS!  s    C2 2D Dc                .   < V ^8  d   QhRS[ R,          /# rp   rU  )rs   rn   s   "rE   rt   r.    s     , ,TD[ ,rH   c                *    ^ RI Hp T! T P                  4      pT'       g   R# T P                  '       d   \        T P                  \        4      '       dd   T P                  P                  R4      RJ d   R# \        T P                  P                  RR4      4      P                  4       P                  4       pMRpTR8X  d   RT9   d   RpRT/# Y29  d+   TR	8X  d   R
T9   d   R
pRT/# RT9   d   RpRT/# T^ ,          pRT/#   \         d     R# i ; i)zDFormat reasoning payload for GitHub Models/OpenAI-compatible routes.rx  Nr  FrV  rU  xhighhighminimallow)r(  ry  r   rB  r_  rO   r   r   rP   r   r7  )rC   ry  supported_effortsrequested_efforts   &   rE   rf  +AIAgent._github_models_reasoning_extra_body  s/   	H ;4::F    Z0E0Et%L%L$$((3u<"%%))(H= egeeg   (w&65F+F% *++ 69,:K1K#(  *++ ..#+  *++ $5Q#7 *++5  		s   D DDc                &   < V ^8  d   QhRS[ RS[/# )rq   rE  rr   )rP   r   )rs   rn   s   "rE   rt   r.    s      t t tQU trH   c                	   V P                  V4      p\        V4      pV'       gj   VP                  ;'       g    Rp\        P                  ! RV\        P
                  R7      pV'       d%   RP                  R V 4       4      pT;'       g    RpV'       d8   V P                  '       d&   \        P                  ! R\        V4       RV 24       V'       d7   V P                  '       d%   V P                  '       g    V P                  V4       R	R
RVP                  ;'       g    RRVRV/p\        VR4      '       d   VP                  '       d   VP                  p	. p
V	 F  p\!        V\"        4      '       d   V
P%                  V4       K,  \        VR4      '       d   V
P%                  VP&                  4       K[  \        VR4      '       g   Ko  V
P%                  VP)                  4       4       K  	  V
'       d   WR&   \+        VRR4      pV'       d   WR&   VP,                  '       EdL   . pVP,                   EF4  p\+        VRR4      p\+        VRR4      p\!        V\.        4      '       d   VP1                  4       '       g   V P3                  V4      w  ppTp\!        V\.        4      '       d   VP1                  4       '       g   \!        V\.        4      '       d(   VP1                  4       '       d   VP1                  4       pMW\+        VRR4      pV'       d   \+        VRR4      MRpV'       d   \+        VRR4      MRpV P5                  VV\        V4      4      pVP1                  4       p\+        VRR4      p\!        V\.        4      '       d   VP1                  4       '       g   V P3                  V4      w  ppTpT P7                  T\!        V\.        4      '       d   TMR4      pRVRVRVRVP8                  RRVP:                  P<                  RVP:                  P>                  //p\+        VRR4      pVe(   \        VR4      '       d   VP)                  4       pVVR&   VP%                  V4       EK7  	  WR&   V#   \         d     ELwi ; i)zBuild a normalized assistant message dict from an API response message.

Handles reasoning extraction, reasoning_details, and optional tool_calls
so both the tool-call path and the final-response path share one builder.
r   r:  r   r9  c              3   p   "   T F,  qP                  4       '       g   K  VP                  4       x  K.  	  R # 5irU   )r   )r   bs   & rE   r   3AIAgent._build_assistant_message.<locals>.<genexpr>  s      &T,Q'')yqwwyy,s   66NzCaptured reasoning (	 chars): r   r  r   r4  rE  r6  __dict__r  r  r  r  r   ra   r   rg  r  r   r  r   ) rB  r   r   r  r;  r  r  rH  r   r   rQ   rX  r[  r   r*  r6  rO   r   r   r  r  r`   r   rP   r   r  r  r  r   r   ra   r   )rC   r<  rE  rM  _from_structuredr   think_blockscombinedr   raw_details	preserveddcodex_itemsr   r   r   r  r!  r  _fn_fn_name_fn_argsr  r"  tc_dictr  s   &&&                       rE   _build_assistant_message AIAgent._build_assistant_message  s    001BC/
 '//552G::&=wbiiXL!;;&T,&TT!)!1!1Td222MM0^1D0EY~N^_`d555 ---++N;
 K(0066B]	
 $&9::?P?b?b?b
 ,==KI a&&$$Q'Q
++$$QZZ0Q--$$Q\\^4 ! +4'( /1H$O+6'('''J.99	 D$7!)Y=!'3//w}}*.*G*G*O'$a.G!'3//w}}!&#..6<<>>"(,,.%iTB?B73#;FI73T#Bt"&"="=hRUV`Ra"b!--/#*96H$#O !"2C88@P@V@V@X@X373P3PQW3X0A0'@$#'#J#J(23CS(I(I$t$  'w&(8INN	 2 2 7 7#Y%7%7%A%A!	  	?DA$ul33 % 0 0 2/4GO,!!'*Y :Z !+
e ! s   :Q4 4RRc                &   < V ^8  d   QhRS[ RS[ /# )rq   api_msgrr   rU  )rs   rn   s   "rE   rt   r.    s      T d rH   c                0   V P                  R4      p\        V\        4      '       g   V # RR0pV UUUu. uFG  p\        V\        4      '       d-   VP	                  4        UUu/ uF  w  rEWB9  g   K  WEbK  	  uppMTNKI  	  upppV R&   V # u uppi u upppi )u  Strip Codex Responses API fields from tool_calls for strict providers.

Providers like Mistral, Fireworks, and other strict OpenAI-compatible APIs
validate the Chat Completions schema and reject unknown fields (call_id,
response_item_id) with 400 or 422 errors. These fields are preserved in
the internal message history — this method only modifies the outgoing
API copy.

Creates new tool_call dicts rather than mutating in-place, so the
original messages list retains call_id/response_item_id for Codex
Responses API compatibility (e.g. if the session falls back to a
Codex provider later).

Fields stripped: call_id, response_item_id
r   r  r  )r   rO   r   r   r6  )r  r   _STRIP_KEYSr   r(  r)  s   &     rE   #_sanitize_tool_calls_for_strict_api+AIAgent._sanitize_tool_calls_for_strict_api  s    " [[.
*d++N "45 !!
 ! "d## !hhjAjdaA,@TQTjA)+, !

 	 B!
s   .B"
B1B7
BBc                    < V ^8  d   QhRS[ /# r   r   )rs   rn   s   "rE   rt   r.    s     2 2T 2rH   c                     V P                   R8g  # )au  Determine if tool_calls need sanitization for strict APIs.

Codex Responses API uses fields like call_id and response_item_id
that are not part of the standard Chat Completions schema. These
fields must be stripped when calling any other API to avoid
validation errors (400 Bad Request).

Returns:
    bool: True if sanitization is needed (non-Codex API), False otherwise.
rp  )r=  rW   s   &rE   _should_sanitize_tool_calls#AIAgent._should_sanitize_tool_calls  s     }} 111rH   c                &   < V ^8  d   QhRS[ RS[/# )rq   r   	min_turns)r   r   )rs   rn   s   "rE   rt   r.    s     [ [t [s [rH   c           	     P   V P                   ^ 8X  d   Vf   R# RV P                  9  g   V P                  '       g   R# Ve   TMV P                   pV P                  V8  d   R# Vf   \	        V RR4      pV'       d   \        V4      ^8  d   R# RpR\        V 4       R\        P                  ! 4        2pRRR	VR
V/pVP                  V4        V P                  4       p. pV F  p	V	P                  4       p
V	P                  R4      R8X  d   V	P                  R4      pV'       d   WR&   V
P                  RR4       V
P                  RR4       V
P                  R
R4       V'       d   V P                  V
4       VP                  V
4       K  	  V P                  '       d   RRR	V P                  /.V,           pRpV P                   ;'       g    .  F-  pVP                  R/ 4      P                  R4      R8X  g   K+  Tp M	  V'       g   VP                  4         V'       d9   VR0,          P                  R
4      V8w  d   VP                  4        V'       d   K?   V'       d2   VR0,          P                  R
4      V8X  d   VP                  4        R# R# R# ^ RIHp Rp V! RVV.RRRR7      pV'       g[   V P(                  R8X  dJ   V P+                  V4      pV P-                  V.4      VR&   RVR&   RV9   d   RVR&   V P/                  V4      pMV'       gQ   V P(                  R8X  d@   ^ RIHp V! V P4                  VV.RRV P7                  4       R 7      pV P9                  V4      pMhV'       ga   R!V P4                  R"VRV.RR/V P;                  R4      CpV P=                  RR#7      P>                  P@                  PB                  ! R1/ VBR$R/B p. pV P(                  R8X  dD   V'       g<   V PE                  V4      w  ppV'       d   VPF                  '       d   VPF                  pMV P(                  R8X  dM   V'       gE   ^ R%IH$p V! VV PJ                  R&7      w  ppV'       d   VPF                  '       d   VPF                  pM_\M        VR'4      '       dN   VPN                  '       d<   VPN                  ^ ,          PP                  pVPF                  '       d   VPF                  pV F  pVPR                  PT                  R8X  g   K    \V        PX                  ! VPR                  PZ                  4      pVP                  R(R4      p^ R)I.H/p V! VP                  R*4      VVP                  R	4      VP                  R+4      V P                  R,7      pV P`                  '       g!   \c        R-VP                  R(R4       24       K  K  	  T'       d9   TR0,          P                  R
4      T8w  d   TP                  4        T'       d   K?   T'       d2   TR0,          P                  R
4      T8X  d   TP                  4        R# R# R#   \&         d	    RpRp ELi ; i  \d         d#   p \f        Pi                  R.T 4        Rp ? EK  Rp ? ii ; i  \d         d!   p \f        Pi                  R/T 4        Rp ? LRp ? ii ; i  T'       d9   TR0,          P                  R
4      T8w  d   TP                  4        T'       d   K?   T'       d0   TR0,          P                  R
4      T8X  d   TP                  4        i i i ; i)2a=  Give the model one turn to persist memories before context is lost.

Called before compression, session reset, or CLI exit. Injects a flush
message, makes one API call, executes any memory tool calls, then
strips all flush artifacts from the message list.

Args:
    messages: The current conversation messages. If None, uses
              self._session_messages (last run_conversation state).
    min_turns: Minimum user turns required to trigger the flush.
               None = use config value (flush_min_turns).
               0 = always flush (used for compression).
Nr  r>  u   [System: The session is being compressed. Save anything worth remembering — prioritize user preferences, corrections, and recurring patterns over task-specific details.]__flush_r  r   rm  r   _flush_sentinelr  r4  r5  rE  r  r   ra   )call_llmTflush_memoriesr`  i   r  )taskr   r  r<  r^  r  Frp  r  r<  r;  rq  rO  )rB  r   r  r^  r_  rR  rB  r   r  r  normalize_anthropic_responsestrip_tool_prefixr  r|  memory_toolactionold_textr  r|  r   r  r9  u     🧠 Memory flush: saved to z!Memory flush tool call failed: %sz Memory flush API call failed: %sr  rd   )5rN  r4  rJ  rf  r`   rQ   r  r  	monotonicr   r  r  r   r  r  r?  r  r)  r  r+  r=  rt  r  r  r"  rP  rB  rK  rP  r  r  rY  rZ  r  r}  r   r  r!  r*  r  r  r   ra   r   r   r   rQ  r  rI  r'  r   r  r   )!rC   r   r  effective_minflush_content	_sentinel	flush_msg_needs_sanitizerG  r   r  r4  memory_tool_defr  	_call_llm_aux_availabler  codex_kwargs_build_ant_kwargs
ant_kwargsr  r   assistant_msgr  
_nar_flush
_flush_msgr<  r   rA  flush_target_memory_toolr]  r  s!   &&&                              rE   r  AIAgent.flush_memories  s@    ''1,1B40008J8J8J%.%:	@\@\  =0t%8$?H3x=1,O 	
 r$xj$..*:);<	VY?PR[\		"w	">>@OL((*776?k1 # 4I 7@ 34K.OT2-t4"<<WE##G,   )))!'9d>X>X YZ]ii #Ojj&&B&55R(,,V4@&'O '
 #j x|//0ABiOxHRL,,->?9L Mxk E!N $))*+ ##  "dmm7H&H#55lC(,(=(=>O(PW%.1]+&,68<L!4511,?#9M(M_.**|*+%)"&"?"?"A	
  :::F#TZZo.!3	
 ,,T2
  ==EU=V[[ggnn  Kq{  K  FJ  K J}} 11.#'#A#A(#K q ]%=%=%=!.!9!9J"66~^ *8tG_G_ `
A*"7"7"7!+!6!6J9--(2B2B2B$,$4$4Q$7$?$?!$///!2!=!=J ;;##x/M#zz"++*?*?@'+xx('CQ!-#'88H#5#/$(HHY$7%)XXj%9"&"4"4"  $!$B488HV^C_B`"ab  / !, x|//0ABiOxHRL,,->?9L MxU    !& ~ % M%H!LLM 	@LL;Q??	@
 x|//0ABiOxHRL,,->?9L Mxs  AY> #AY> %7Y> ,Y> 
)Y> 8Y> Y> Y> X8 *Y> 2A!Y> AY> ,A:Y> 'Y> Y> %Y> ;$Y>  Y> 20Y> #.Y> )Y> BYY7Y> 8YY> 
YY> Y;Y6/Y> 6Y;;Y> >Z)	Z$Z, $Z))Z, ,\%52\%,\%50\%rF  r\  r!  c          
      8   < V ^8  d   QhRS[ RS[RS[RS[RS[/# )rq   r   rv  rF  r\  rr   )r   rP   r   r  )rs   rn   s   "rE   rt   r.  H  s>     ]- ]-$ ]- ]-WZ ]-lo ]-  AF ]-rH   c               6   \        V4      p\        P                  RV P                  ;'       g    RTV'       d   VR MRV P                  4       V P                  V^ R7       V P                  '       d    V P                  P                  V4       V P                  P                  WR7      pV P                  P                  4       pV'       d   VP                  RRR	V/4       V P                  4        V P                  V4      pWn        V P"                  '       Ed    V P"                  P%                  V P                  4      p	V P"                  P'                  V P                  R
4       V P                  p
\(        P*                  ! 4       P-                  R4       R\.        P0                  ! 4       P2                  R,           2V n        V P4                  RV P                   R2,          V n        V P"                  P9                  V P                  V P:                  ;'       g!    \<        P>                  PA                  RR4      V P                  V
R7       V	'       dC    V P"                  PC                  V	4      pV P"                  PE                  V P                  V4       V P"                  PK                  V P                  V4       ^ V n&        \Q        V4      \S        V4      ,           pWP                  n*        ^ V P                  n+        V P                  PX                  ^ 8  d+   WP                  PX                  ,          pVR8  d   RV n-         ^ RI.H/p V! V4       \        P                  RV P                  ;'       g    RV\        V4      VR 4       Wh3#   \         d     ELi ; i  \F        \        3 d"   p\        PI                  RT4        Rp?EL7Rp?ii ; i  \         d"   p\        PO                  RT4        Rp?EL9Rp?ii ; i  \         d     Li ; i)z|Compress conversation context and split the session in SQLite.

Returns:
    (compressed_messages, new_system_prompt) tuple
zGcontext compression started: session=%s messages=%d tokens=~%s model=%sr  r  r  )r  )current_tokensr   rm  r   r  r  r  r  r  r  r  r  )rS  r  rB  rd  z,Could not propagate title on compression: %sNuK   Session DB compression split failed — new session will NOT be indexed: %s333333?F)reset_file_dedupz?context compression done: session=%s messages=%d->%d tokens=~%s)0rQ   r  r  rS  rB  r  rS  on_pre_compressr   rc  compressrH  format_for_injectionr   r  r  r?  rB  get_session_titleend_sessionr   r  r  r8  r9  r:  r;  r=  rE  ra  r   rF  r   get_next_title_in_lineageset_session_titlerN   r   update_system_promptrD  r   r   r    r  r  rs  r  tools.file_toolsr  )rC   r   rv  rF  r\  _pre_msg_count
compressedtodo_snapshotnew_system_prompt	old_titleold_session_id	new_titler  _compressed_est_post_progressr  s   &&&$$           rE   _compress_contextAIAgent._compress_contextH  st    XUOO%%v~$1}Qy$**	
 	H2 $$44X> ,,55h5]
((==?vvy-HI&&( 55nE%6"q ,,>>tO	  ,,T__mL!%%-\\^%<%<_%M$NaPTPZPZP\P`P`acPdOe"f(,(4??BSSX8Y(Y%  //#==ZZBJJNN;RTY,Z**&4	 0  X$($4$4$N$Ny$Y	((::4??IV   55dooGXY,-) ""34,Z89 	 6E29:6 ""33a7,/F/F/W/WWN$05-
	9W% 	MOO%%v~s:q!	

 ,,U  B '	2 X%SUVWWX
  qlnoppq8  		sn   5N DO  9O AN& -O P
 N#"N#&O7OO OO P&PP
PPc                0   < V ^8  d   QhRS[ RS[RS[RR/# rq   r   effective_task_idr[  rr   Nr   rP   r   )rs   rn   s   "rE   rt   r.    s,     * *t *X[ *mp *y} *rH   c                    VP                   pRV n         \        V4      '       g   V P                  WW44      RV n        # V P	                  WW44      RV n        #   RT n        i ; i)a  Execute tool calls from the assistant message and append results to messages.

Dispatches to concurrent execution only for batches that look
independent: read-only tools may always share the parallel path, while
file reads/writes may do so only when their target paths do not overlap.
TF)r   r  r   _execute_tool_calls_sequential_execute_tool_calls_concurrent)rC   r<  r   r  r[  r   s   &&&&& rE   _execute_tool_callsAIAgent._execute_tool_calls  sp     '11
 !%
	*1*==::%1B %*D!	 66!-> %*D!ED!s   "A A 	A!c          
      H   < V ^8  d   QhRS[ RS[RS[ RS[S[ ,          RS[ /# )rq   r  r   r  r  rr   )rP   r   r   )rs   rn   s   "rE   rt   r.    s>     H H# Hd HWZ H#+C=H<?HrH   c           
        VR8X  d;   ^ RI Hp V! VP                  R4      VP                  RR4      V P                  R7      # VR8X  d   V P                  '       g   \
        P                  ! RRR	R
/4      # ^ RIHp V! VP                  RR4      VP                  R4      VP                  R^4      V P                  V P                  R7      # VR8X  d   TP                  RR4      p^ RI
Hp V! VP                  R4      VVP                  R4      VP                  R4      V P                  R7      p	V P                  '       dW   VP                  R4      R'9   dA    V P                  P                  VP                  RR4      VVP                  RR4      4       V	# V	# V P                  '       d=   V P                  P!                  V4      '       d   V P                  P#                  W4      # VR8X  d;   ^ RIHp
 V
! VP                  RR4      VP                  R4      V P(                  R7      # VR8X  d`   ^ RIHp V! VP                  R4      VP                  R 4      VP                  R!4      VP                  R"4      VP                  R#4      V R$7      # \/        YTTV P                  ;'       g    RV P0                  '       d   \3        V P0                  4      R&7      # R%R&7      #   \         d     T	# i ; i)(a   Invoke a single tool and return the result string. No display logic.

Handles both agent-level tools (todo, memory, etc.) and registry-dispatched
tools. Used by the concurrent execution path; the sequential path retains
its own inline invocation for backward-compatible display handling.
todo	todo_toolrk  rl  Frk  rl  r9  rx  rh  r  Session database not available.rx  queryr   role_filterlimitr  r  r  dbcurrent_session_idr  r|  r  r  r   r  r  r   clarify_toolquestionr  r  r  callbackr  r  goalr  toolsetstasksrC  r  r  r  r   rC  parent_agentNr  rS  enabled_tools)r`  r  )rG  r  r   rH  rB  r   r   tools.session_search_toolrx  rS  rQ  r  rJ  rS  on_memory_writer   has_toolhandle_tool_calltools.clarify_toolr  rY  r  r  r   r4  r   )rC   r  r   r  r  
_todo_tool_session_searchr|  r  r]  _clarify_tool_delegate_tasks   &&&&&       rE   _invoke_toolAIAgent._invoke_tool  s    F"?#''0#''7&& 
 ..###zz9eW>_"`aaS"#''4)--m<#''3###'??  h&"&&x:FE!$((2%)))4&**:6((F ###(9(9((CGY(Y((88%))(B7%)))R8 M6M!!!d&:&:&C&CM&R&R''88VVi'H &**:r:%)))4.. 
 o-K!"&&v.%)))4&**:6#''0,001AB!  (.?)??00b=A=R=R=Rd4#8#89	  Y]	 / ! Ms   =K K,+K,c                0   < V ^8  d   QhRS[ RS[RS[RR/# r  r  )rs   rn   s   "rE   rt   r.    s<     VT VT$ VTcf VTx{ VT  EI VTrH   c                R  a aa/ VP                   p\        V4      pS P                  '       d`   \        S P                   RV R24       V F<  pVP                  RRRRVP                  P                   R2RVP                  /4       K>  	  R	# . pV EF  p	V	P                  P                  p
V
R
8X  d	   ^ S n	        MV
R8X  d   ^ S n
         \        P                  ! V	P                  P                  4      p\        V\         4      '       g   / pV
RN9   dr   S P"                  P$                  '       dV    VP'                  RR4      pV'       d;   S P"                  P)                  V4      pS P"                  P+                  VRV
 24       V
R8X  d   S P"                  P$                  '       d    VP'                  RR4      p\/        V4      '       dj   VP'                  R4      ;'       g+    \0        P2                  ! R\0        P4                  ! 4       4      pS P"                  P+                  VRVR,           24       VP                  WV34       EK  	  RP7                  R V 4       4      pS P8                  '       g   \        RV RV 24       \;        V^4       F  w  pw  ppp\        P<                  ! VRR7      pS P>                  '       d=   \        RV RV R\A        VPC                  4       4       R24       \        RV 24       Kp  \        V4      S PD                  8  d   VR	S PD                   R ,           MTp\        RV RV R\A        VPC                  4       4       R!V 24       K  	  V F<  w  pppS PF                  '       g   K   \I        VV4      pS PG                  R"VVV4       K>  	  V F9  w  pppS PN                  '       g   K   S PO                  VP                  VV4       K;  	  R	.V,          o/VV/V 3R% lpR	pS P8                  '       d{   S PF                  '       gi   S PQ                  4       '       dS   \R        PT                  ! \V        PX                  4      p\W        V R&V R'2R(S PZ                  R)7      pVP]                  4         \_        V\`        4      p\b        Pd                  Pg                  VR*7      ;_uu_ 4       p. p\;        V4       F0  w  pw  pppVPi                  VVVVV4      pVP                  V4       K2  	  \b        Pd                  Pk                  V4       R	R	R	4       V'       dA   \m        R+ S/ 4       4      p\m        R, S/ 4       4      p VPo                  R-V R.V R/V R0 R124       \;        T4       EF`  w  pw  pppS/T,          p!T!f
   R2T R32p"R4p#MT!w  rp"p#p$T$'       d4   \        T"4      ^8  d
   T"R5,          MT"p%\p        Ps                  R6T
T#T%4       S PF                  '       d    S PG                  R7T
R	R	T#T$R87       S P>                  '       dD   \J        PL                  ! R9T
 R:T#R; R<24       \J        PL                  ! R=\        T"4       R>T" 24       S P8                  '       d%   \u        TTT#T"R?7      p&S Pw                  R@T& 24       MS P8                  '       g   S P>                  '       d*   \        RAT^,            R:T#R; R<24       \        RBT" 24       MN\        T"4      S PD                  8  d   T"R	S PD                   R ,           MT"p'\        RAT^,            R:T#R; RCT' 24       R	S n<        S P{                  RDT RET#R0 RF24       S P|                  '       d     S P}                  TP                  TTT"4       \        TT"4      p"S P                  P                  TT4      p(T('       d
   T"T(,          p"RRRT"RTP                  /p)TP                  T)4       EKc  	  S P                  T4      p*T*'       Ed   T'       d   TRO,          P'                  R4      R8X  d   TRO,          R,          p+ \        P                  ! T+4      p,\        T,\         4      '       d)   T*T,RH&   \        P<                  ! T,RR7      TRO,          R&   MT+RIT* 2,           TRO,          R&    S P8                  '       gO   S P                  T,
          p-T-S P                  RJ,          8:  d   RKMRLp.\        S P                   T. RT- RM24       R	# R	# R	# R	# R	#   \        P                   d    / p EL+i ; i  \,         d     ELi ; i  \,         d     ELi ; i  \,         d&   p\J        PL                  ! R#T 24        R	p?EK	  R	p?ii ; i  \,         d&   p\J        PL                  ! R$T 24        R	p?EK  R	p?ii ; i  + '       g   i     EL; i  T'       dB   \m        R+ S/ 4       4      p\m        R, S/ 4       4      p TPo                  R-T R.T R/T R0 R124       i i ; i  \,         d%   p\J        PL                  ! R#T 24        R	p?EL/R	p?ii ; i  \,         d%   p\J        PL                  ! RGT 24        R	p?ELR	p?ii ; i  \        P                  \        3 d    T+RIT* 2,           TRO,          R&    EL
i ; i)PzExecute multiple tool calls concurrently using a thread pool.

Results are collected in the original tool-call order and appended to
messages so the API sees them in the expected sequence.
   ⚡ Interrupt: skipping  tool call(s)r   r   r      [Tool execution cancelled — # was skipped due to user interrupt]r  Nr  ry  r   r   before terminalr@  workdirr  before terminal: r  r  c              3   *   "   T F	  w  rqx  K  	  R # 5irU   rd   )r   r  ra   s   &  rE   r   9AIAgent._execute_tool_calls_concurrent.<locals>.<genexpr>G  s     "G,JAQ4,s   u     ⚡ Concurrent: u    tool calls — Fr        📞 Tool r^  (r       Args: r  ) - tool.startedTool progress callback error: Tool start callback error: c                  < \         P                   ! 4       p SP                  W#S
VP                  4      p\         P                   ! 4       V,
          p\        W%4      w  rV'       d    \        P                  RW'VR,          4       M \        P                  R	W'\        V4      4       W#WWV3SV &   R#   \         d+   pRT RT 2p\        P                  RY&RR7        Rp?LRp?ii ; i)
z%Worker function executed in a thread.Error executing tool '': z_invoke_tool raised for %s: %sTr  Nztool %s failed (%.2fs): %sr   #tool %s completed (%.2fs, %d chars))	r  r  r  r   r  r  r6   r  rQ   )r  r   r  r   r  r]  
tool_errordurationis_errorr  r  resultsrC   s   &&&&      rE   	_run_tool9AIAgent._execute_tool_calls_concurrent.<locals>._run_toolf  s    IIKEi**=IZ\e\h\hi yy{U*H.}EKH8-SYZ^S_`A=\_`f\gh+FhWGEN  i1-J<P=}cghhis   B/ /C$: CC$u    ⚡ running z tools concurrentlydotsspinner_typeprint_fn)max_workersc              3   0   "   T F  qf   K  ^x  K  	  R # 5irU   rd   r   rs   & rE   r   r    s     D7a7s   
c              3   >   "   T F  qf   K  V^,          x  K  	  R # 5irU   rd   r3  s   & rE   r   r    s     Gg!gs   u   ⚡ ru  z tools completed in .1fzs totalr$  z!': thread did not return a resultr  r   "Tool %s returned error (%.2fs): %stool.completedr(  r)  Tool  completed in .2fsTool result (r  r]         ✅ Tool      Result: s - tool completed: r  s)Tool complete callback error: r   r9  皙?   ⚠️  WARNING   💡 CAUTION iterations remaining
write_filepatchr  )Er   rQ   r  r'  rL  r   r   ra   r  rO  rP  r   r   r   r   rO   r   rA  r  r   get_working_dir_for_pathensure_checkpointr   r   r   r-  getcwdr  rI  r,  r   rH  r   rC  rK  rT  _build_tool_previewr   r   rU  r  randomchoicer3   KAWAII_WAITINGr  r  r   _MAX_TOOL_WORKERS
concurrentfuturesThreadPoolExecutorsubmitwaitr  rd  r  r   _get_cute_tool_message_implr  r  rR  rV  r*  re  check_tool_call_get_budget_warningr   rC  )0rC   r<  r   r  r[  r   	num_toolsr   parsed_callsr   r  r   	file_pathwork_dirr   r   tool_names_strr  ra   rA  args_strargs_previewr(  cb_errr+  spinnerfacer1  executorrW  r'  r  	total_durr4  r  tool_durationr)  result_previewcute_msgresponse_previewsubdir_hintsr  budget_warninglast_contentr  r   tierr*  s0   f&&f&                                          @rE   r  &AIAgent._execute_tool_calls_concurrent  s
    '11

O	 $$$T__%%=i[VW F!?@P@P?QQtu"BEE!  !  #I%..33M (+,(.0*+'# $

9+=+=+G+G H mT22 "  77D<P<P<X<X<X - 1 1&" =I #'#7#7#P#PQZ#[,,>>x7S`RaIbc
 
*t/C/C/K/K/K'++Ir:C.s33+//	:ddbiiXZXaXaXc>d,,>>#4SXJ!? = IJM $R "G,"GG&yk1A.AQRS'0q'A##Bd::d?'''L2dV1T$))+5F4GqIJKz23ORS[}_c_t_tOt8,BT-B-B#Ce#K  {CLL2dV1T$))+5F4GtL>Z[ (B +NBd***M1$=G//gtT	 + +NBd'''J,,RUUD$? + &9$	X" ???4#>#>#>4CcCcCeCe==!=!=>D#tfM)DW$Xgmx|  yG  yG  HGMMO	gi):;K##66;6OOS[+4\+B'A'D$ 	1b$EANN1% ,C
 ""''0 P D7DD	GgGG	tI;a	{:NyY\o]def $-\#:AD$
Ay$:4&@a"b #YZVo}h>A/>RUX>X_T%:^mNNN#GXeguv...Q33,mT4%2X 4  '''MME-}UXFYYZ"[\MMM#o2F1GyQ`Pa"bc 6tT=Yhi  2hZ1___'''K!uN=:MQOPM/):;<Z]^mZnqu  rG  rG  [G7M8M8M'NQV'V  M\$K!uN=:MTRbQcde!%D  #3D6M#;Nb!QR***M//tT?S
 :$PO  33CCD$OL</ ?H
 OOH%{ $;@ 11.A>h8B<+;+;F+Cv+M#B<	2LQL1fd++0>F,-.2jje.THRL+.:tNCS=T.THRL+ ??? //.@	,59L9Ls9R,R(Xf)$r)<QRS # ,Nh>O '' # "# !  ! . ! MMM$B6("KLLM ! JMM$?x"HIIJ@ POO D7DD	GgGG	tI;a	{:NyY\o]def	 4 % Q(Fvh&OPPQ2 ! MMM$B6("KLLM< (()4 Q*64?O9P*PY'Qs   *d.d!:d!&:d3!Ad3 ee88f? ?A!f+ f? 1h!h?0Ai1 i1 dd!d0/d03eee5e00e58f(f##f(+f<	6	f? ?Ah
h<h77h<?i.
i))i.11j&%j&c                0   < V ^8  d   QhRS[ RS[RS[RR/# r  r  )rs   rn   s   "rE   rt   r.    s<     DT DT$ DTcf DTx{ DT  EI DTrH   c                &   \        VP                  ^4       EF  w  rVV P                  '       d   VP                  V^,
          R pV'       d-   V P                  V P                   R\        V4       R2RR7       V F@  pVP                  P                  p	RRRR	V	 R
2RVP                  /p
VP                  V
4       KB  	   EMVP                  P                  pVR8X  d	   ^ V n
        MVR8X  d   ^ V n         \        P                  ! VP                  P                  4      p\%        V\&        4      '       g   / pV P(                  '       g   \        P*                  ! VRR7      pV P,                  '       d<   \/        RV RV R\1        VP3                  4       4       R24       \/        RV 24       M`\        V4      V P4                  8  d   VRV P4                   R,           MTp\/        RV RV R\1        VP3                  4       4       RV 24       Wn        V P9                  RV 24       V P:                  '       d!    \=        W4      pV P;                  RVVV4       V PB                  '       d    V PC                  VP                  W4       VRs9   dr   V PD                  PF                  '       dV    VPI                  RR4      pV'       d;   V PD                  PK                  V4      pV PD                  PM                  VRV 24       VR8X  d   V PD                  PF                  '       d    VPI                  R R4      p\O        V4      '       dj   VPI                  R!4      ;'       g+    \P        PR                  ! R"\P        PT                  ! 4       4      pV PD                  PM                  VR#VR$,           24       \V        PV                  ! 4       pVR%8X  d   ^ R&I,H-p V! VPI                  R'4      VPI                  R(R4      V P\                  R)7      p\V        PV                  ! 4       V,
          pV P(                  '       d"   V P                  R*\_        R%VVVR+7       24       EMVR,8X  d   V P`                  '       g   \        P*                  ! R-RR.R//4      pMV^ R0I1H2p V! VPI                  R1R4      VPI                  R24      VPI                  R3^4      V P`                  V Pf                  R47      p\V        PV                  ! 4       V,
          pV P(                  '       d"   V P                  R*\_        R,VVVR+7       24       EM8VR8X  d   TPI                  R5R4      p^ R6I4H5p V! VPI                  R74      VVPI                  R4      VPI                  R84      V Pl                  R97      p\V        PV                  ! 4       V,
          pV P(                  '       d"   V P                  R*\_        RVVVR+7       24       EMVR:8X  d   ^ R;I7H8p V! VPI                  R<R4      VPI                  R=4      V Pr                  R>7      p\V        PV                  ! 4       V,
          pV P(                  '       d"   V P                  R*\_        R:VVVR+7       24       EMVR?8X  Ed   ^ R@I:H;p VPI                  RA4      pV'       d'   \%        V\0        4      '       d   RB\        V4       RC2p M1VPI                  RD4      ;'       g    RRE,          p!V!'       d   RFV! 2MRGp Rp"V P(                  '       dz   V P:                  '       gh   V Py                  4       '       dR   \z        P|                  ! \~        P                  4      p#\        V# RHV  2RIV P                  RJ7      p"V"P                  4        V"V nC        Rp$ V! VPI                  RD4      VPI                  RK4      VPI                  RL4      VVPI                  RM4      V RN7      pTp$RV nC        \V        PV                  ! 4       V,
          p\_        R?VVV$R+7      p%V"'       d   V"P                  V%4       EMDV P(                  '       d   V P                  R*V% 24       EMV P                  '       EdJ   V P                  P                  V4      '       Ed(   Rp"V P(                  '       d   V P:                  '       gu   \z        P|                  ! \~        P                  4      p#\        V4      p&\=        W4      ;'       g    Tp\        V# RHV& RHV 2RIV P                  RJ7      p"V"P                  4        Rp' V P                  P                  W4      pTp'\V        PV                  ! 4       V,
          p\_        WVV'R+7      p%V"'       d   V"P                  V%4       EMV P(                  '       d   V P                  R*V% 24       EMV P(                  '       Ed<   Rp"V P:                  '       gu   \z        P|                  ! \~        P                  4      p#\        V4      p&\=        W4      ;'       g    Tp\        V# RHV& RHV 2RIV P                  RJ7      p"V"P                  4        Rp) \        YTVP                  V Pf                  ;'       g    RV P                  '       d   \1        V P                  4      MRRS7      pTp)\V        PV                  ! 4       V,
          p\_        WVV)R+7      p%V"'       d   V"P                  V%4       MV P                  R*V% 24       Mr \        YTVP                  V Pf                  ;'       g    RV P                  '       d   \1        V P                  4      MRRS7      p\V        PV                  ! 4       V,
          pV P,                  '       d   TM\        V4      ^8  d
   VRW,          MTp*\        VV4      w  p+p,V+'       d   \        P#                  RXVVV*4       M!\        P                  RYVV\        V4      4       V P:                  '       d    V P;                  RZVRRVV+R[7       RV n        V P9                  R\V R]VR^ R_24       V P,                  '       dD   \         P@                  ! R`V RaVRb Rc24       \         P@                  ! Rd\        V4       ReV 24       V P                  '       d    V P                  VP                  WV4       \        VV4      pV P                  P                  W4      p-V-'       d
   VV-,          pRRRVRVP                  /p.VP                  V.4       V P(                  '       g|   V P,                  '       d#   \/        RgV RaVRb Rc24       \/        RhV 24       MG\        V4      V P4                  8  d   VRV P4                   R,           MTp/\/        RgV RaVRb RiV/ 24       V P                  '       d   V\        VP                  4      8  d   \        VP                  4      V,
          p0V P                  V P                   RV0 Rj2RR7       VP                  VR  F@  pVP                  P                  p	RRRRkV	 Rl2RVP                  /p
VP                  V
4       KB  	   MVV P                  ^ 8  g   EK`  V\        VP                  4      8  g   EK}  \V        P                  ! V P                  4       EK  	  V P                  V4      p1V1'       Ed   V'       d   VRt,          PI                  R4      R8X  d   VRt,          R,          p2 \        P                  ! V24      p3\%        V3\&        4      '       d)   V1V3Rm&   \        P*                  ! V3RR7      VRt,          R&   MV2RnV1 2,           VRt,          R&    V P(                  '       gO   V P                  V,
          p0V0V P                  Ro,          8:  d   RpMRqp4\/        V P                   V4 RV0 Rr24       R# R# R# R# R#   \        P                   d'   p\         P"                  ! RT 24       / p Rp?ELRp?ii ; i  \>         d%   p\         P@                  ! RT 24        Rp?ELRp?ii ; i  \>         d%   p\         P@                  ! RT 24        Rp?ELRp?ii ; i  \>         d     ELi ; i  \>         d     ELi ; i  RT nC        \V        PV                  ! 4       T,
          p\_        R?TTT$R+7      p%T"'       d   T"P                  T%4       i T P(                  '       d   T P                  R*T% 24       i i ; i  \>         dC   p(\        P*                  ! R.ROT RPT( 2/4      p\        P                  RQTT(RRR7        Rp(?(EL#Rp(?(ii ; i  \V        PV                  ! 4       T,
          p\_        YTT'R+7      p%T"'       d   T"P                  T%4       i T P(                  '       d   T P                  R*T% 24       i i ; i  \>         d-   p(RTT RUT( 2p\        P                  RVTT(RRR7        Rp(?(ELkRp(?(ii ; i  \V        PV                  ! 4       T,
          p\_        YTT)R+7      p%T"'       d   T"P                  T%4       i T P                  R*T% 24       i ; i  \>         d-   p(RTT RUT( 2p\        P                  RVTT(RRR7        Rp(?(ELSRp(?(ii ; i  \>         d%   p\         P@                  ! RT 24        Rp?ELRp?ii ; i  \>         d%   p\         P@                  ! RfT 24        Rp?ELLRp?ii ; i  \        P                  \        3 d    T2RnT1 2,           TRt,          R&    ELi ; i)uz`Execute tool calls sequentially (original behavior). Used for single calls or interactive tools.Nr  r  Tr  r   r   r   r  r  r  r  ry  z(Unexpected JSON error after validation: Fr   r  r^  r  r  r  r  r  zexecuting tool: r   r!  r"  r   r   r  r  r@  r  r  r  r  r  r  rk  rl  r  r@  r?  rx  rh  r  r  r  r  r  r  r  r|  r  r  r  r  r   r  r  r  r  r  r  r   u   🔀 delegating z tasksr  :N   Nu   🔀 u   🔀 delegatingrn  r-  r.  r  r  rC  r  zMemory tool 'z
' failed: z1memory_manager.handle_tool_call raised for %s: %sr  r  r$  r%  z&handle_function_call raised for %s: %sr   r7  r&  r8  r9  rD  r  r6  rE  r:  r;  r<  r=  r>  r  rF  rA  rB  rC  z remaining tool call(s)u   [Tool execution skipped — z* was not started. User sent a new message]r   r9  rG  rH  rI  rJ  rK  r  )Xr,  r   r  r  rL  rQ   r   ra   r  r   rO  rP  r   r   r   r   r   r   rO   r   rI  r   rH  r'  r   rC  rK  r  rR  rT  rQ  r   r   rU  rA  r  r   rN  rO  r   r   r-  rP  r  rG  r  rH  r[  rB  r  rx  rS  rQ  r  rJ  r	  r  rY  r  r  r  rR  rS  r3   rT  r  r  _delegate_spinnerrd  rS  r  _get_tool_emojir  r  r  r   r4  r6   r  rV  r*  re  r\  rD  r  r]  r   rC  )5rC   r<  r   r  r[  r  r   remaining_calls
skipped_tcskipped_nameskip_msgr  r   r  rc  rd  r(  re  r`  ra  r   r   tool_start_timer
  r  rj  r  r|  r  r  r  	tasks_argspinner_labelgoal_previewrf  rg  _delegate_resultrl  emoji_mem_resultr'  _spinner_resultrk  _is_error_resultr  rn  r  rm  r   ro  rp  r  rq  s5   &&&&&                                                rE   r  &AIAgent._execute_tool_calls_sequential  s.   %&7&B&BAFLA ((("3">">qst"D"LLDOO#44LSQ`MaLbbo!px|L}"1J#-#6#6#;#;L!%CL>Qt#u&
 H
 OOH- #2 %..33M (+,(.0*+'# $

9+=+=+G+G H mT22 "???::m%H'''L2m_Ad=CUCUCW>X=YYZ[\Kz23ORS[}_c_t_tOt8,BT-B-B#Ce#K  {CLL2m_Ad=CUCUCW>X=YY]^j]klm!.  #3M?!CD***M1-OG//wXef '''J,,Y\\=X
  77D<P<P<X<X<X - 1 1&" =I #'#7#7#P#PQZ#[,,>>$&? 
*t/C/C/K/K/K'++Ir:C.s33+//	:ddbiiXZXaXaXc>d,,>>#4SXJ!? #iikO&C",'++G4'++GU;**#
 !%		o =???LL2&A&-Yfo~&  &A  "B  C"22'''&*jj)UGMn1o&pO[&5+//<$1$5$5m$D+//;+++/??'O !%		o =???LL2&ABRTacp  zI  'J  &K  "L  M(*&**8X>I".(,,X6!)--i8*..z:,,# !%		o =???LL2&A(M[h  rA  'B  &C  "D  E)+L"/*..z2>)--i8!22#
 !%		o =???LL2&A)]\i  sB  'C  &D  "E  F/1O)--g6	It!<!<&6s9~6Ff$MM$1$5$5f$=$C$CS#IL>JeL>$:PaM???4+F+F+F4KkKkKmKm!==)E)EFD+tfAm_,ETZeiesestGMMO)0&#' 6&4*..v6 - 1 1) <!.!2!2:!>''4'8'89I'J%)'O (7$-1D*$(IIK/$AM:?M[h  rB   CHX.r(_5%%%$*>*>*G*G*V*V ???4+F+F+F!==)E)EFD+M:E1-O``S`G+tfAeWAgY,GV\gkguguvGMMO"6&*&:&:&K&KM&iO"1K
 %)IIK/$AM:=Yfoz{HX.r(_5222!==)E)EFD+M:E1-O``S`G+tfAeWAgY,GV\gkguguvGMMO"&6&:%6G%.\\#'??#8#8bEIEZEZEZd4+@+@&A`d	'O '6O
 %)IIK/$AM:=Yfo~HX.r(_5	u&:%6G%.\\#'??#8#8bEIEZEZEZd4+@+@&A`d	'O !%		o =040D0D0D_),_)=)C%  #7}o"VaC]TacqrA=R_adetauv***M//(-t!.9I 0  "&D  #3M?"]SVDWWY!Z[###m_N=QTBUUVWXc/.B-C9_L]^_***M//	m\kl
 :-YO  33CCMaL</ ?	H
 OOH%???'''Ks.s8K1MNM/):;<Z]^mZnqu  rG  rG  [G7M8M8M'NQV'V  M\$Ks.s8K4P`Oabc(((Q5F5Q5Q1R-R 1 < <=A	00HSjkswx"3">">qr"BJ#-#6#6#;#;L!%A,Oy#z&
 H
 OOH- #C "q3/@/K/K+L'L

4??+[	 Gf	 11.A>h8B<+;+;F+Cv+M#B<	2LQL1fd++0>F,-.2jje.THRL+.:tNCS=T.THRL+ ??? //.@	,59L9Ls9R,R(Xf)$r)<QRS # ,Nh>q '' #"J1# NO "#, ! MMM$B6("KLLM ! JMM$?x"HIIJ !  ! ^ .2D*$(IIK/$AM:?M[h  rB   CHX.r(_5 )  ! @&*jj']=/Ycdnco;p1q&rOLL!TVceoz~L@ %)IIK/$AM:=Yfoz{HX.r(_5 )& ! u(>}oSQ[P\&]OLL!I=ZdosLttu %)IIK/$AM:=Yfo~HX.r(_5 ! u(>}oSQ[P\&]OLL!I=ZdosLttu. ! MMM$B6("KLLM ! MMM$B6("KLLMp (()4 Q*64?O9P*PY'Qs  6*<A@.AA.AA>:AA>&:AB!AABAAB""AD
8AGAG;$AI1 AI14AI1?AJ+AK	AAL AL A@1A@@A@@AA	@%AAAAA	AAA;AAA6A6AA;A>ABBABBABBABB"AADDADDAE'D%7AE"EAE*E"AE'E'AE*E*AAGGAGGAHG%!AHHAHHAHHAHHAAI.I1AJ(I<!AJ#J#AJ(J+AKJ6AKKAKKALK(ALLALL1AMMAMc                6   < V ^8  d   QhRS[ RS[S[,          /# )rq   r[  rr   )r   r   rP   )rs   rn   s   "rE   rt   r.  &  s      # (3- rH   c                2   V P                   '       d   V P                  ^ 8:  d   R# WP                  ,          pV P                  V,
          pW P                  8  d   RV RV P                   RV R2# W P                  8  d   RV RV P                   RV R2# R# )	zReturn a budget pressure string, or None if not yet needed.

Two-tier system:
  - Caution (70%): nudge to consolidate work
  - Warning (90%): urgent, must respond now
Nz[BUDGET WARNING: Iteration ru  z. Only zd iteration(s) left. Provide your final response NOW. No more tool calls unless absolutely critical.]z[BUDGET: Iteration z. z1 iterations left. Start consolidating your work.])r  rC  r  r  )rC   r[  progressr   s   &&  rE   r]  AIAgent._get_budget_warning&  s     ,,,0C0Cq0H!$7$77''.8	555-n-=Qt?R?R>S T!{ #cc
 555%n%5Qt7J7J6K2+NP rH   c                $   < V ^8  d   QhRS[ RR/# )rq   compaction_progressrr   N)rk  )rs   rn   s   "rE   rt   r.  >  s      %Y %Y% %YPT %YrH   c                   ^ RI HpHp VP                  '       d   VP                  VP                  ,          MRpV P
                  R
9   d2   V! VVP                  VV P                  R7      pV P                  V4       V P                  '       d+    V! VVV P                  R7      pV P                  RV4       R# R#   \         d    \        P                  RRR	7        R# i ; i)u  Notify the user that context is approaching the compaction threshold.

Args:
    compaction_progress: How close to compaction (0.0–1.0, where 1.0 = fires).
    compressor: The ContextCompressor instance (for threshold/context info).

Purely user-facing — does NOT modify the message stream.
For CLI: prints a formatted line with a progress bar.
For gateway: fires status_callback so the platform can send a chat message.
)format_context_pressureformat_context_pressure_gatewayr  N)r  rs  r  rd  )r  r  rd  context_pressurez)status_callback error in context pressureTr  )Nr  )agent.displayr  r  r  rs  ra  rd  r  r]  r   r  r   )rC   r  rV  r  r  threshold_pctliner   s   &&&     rE   _emit_context_pressureAIAgent._emit_context_pressure>  s     	[S]SlSlSl
33j6O6OOru
 ==M)*$7!+!<!<"/$($<$<	D T" Y5(;&3(,(@(@
 $$%7=    YHSWXYs   'B: :"C C c                ,   < V ^8  d   QhRS[ RS[RS[/# )rq   r   r[  rr   )r   r   rP   )rs   rn   s   "rE   rt   r.  e  s'     U Ut US US UrH   c           
        \        RV P                   R24       RpVP                  RRRV/4        V P                  4       p. pV FX  pVP	                  4       pR- F  pVP                  VR4       K  	  V'       d   V P                  V4       VP                  V4       KZ  	  V P                  ;'       g    R	p	V P                  '       d)   V	R
,           V P                  ,           P                  4       p	V	'       d   RRRV	/.V,           pV P                  '       dQ   V	'       d   ^M^ p
\        V P                  4       F+  w  rVP                  W,           VP	                  4       4       K-  	  / pRV P                  9   pV P                  4       '       d(   V P                  e   V P                  VR&   M	RRRR/VR&   V'       d   R.VR&   V P                   R8X  dy   V P#                  V4      pVP                  RR4       V P%                  V4      pV P'                  V4      w  ppV'       d%   VP(                  ;'       g    R	P                  4       MR	pEM2RV P*                  RV/pV P,                  e+   VP/                  V P1                  V P,                  4      4       / pV P2                  '       d   V P2                  VR&   V P4                  '       d   V P4                  VR&   V P6                  '       d   V P6                  VR&   V P8                  '       d   V P8                  VR&   V'       d   VVR&   V'       d   VVR&   V P                   R8X  d   ^ RIHpHp V! V P*                  VRV P,                  V P                  V P@                  V PC                  4       R7      pV PE                  V4      pV! VV P@                  R 7      w  ppVP(                  ;'       g    R	P                  4       pMV PG                  R!R"7      PH                  PJ                  PL                  ! R./ VB pVPN                  '       dV   VPN                  ^ ,          PP                  P(                  '       d)   VPN                  ^ ,          PP                  P(                  pMR	pV'       db   R#V9   d7   \R        PT                  ! R$R	V\R        PV                  R%7      P                  4       pV'       d   VP                  RR&RV/4       V# R'p V# V P                   R8X  dy   V P#                  V4      pVP                  RR4       V P%                  V4      pV P'                  V4      w  ppV'       d%   VP(                  ;'       g    R	P                  4       MR	pEMV P                   R8X  d   ^ RIHpHp V! V P*                  VRV P@                  V P,                  V P                  V PC                  4       R(7      pV PE                  V4      pV! VV P@                  R 7      w  ppVP(                  ;'       g    R	P                  4       pMRV P*                  RV/pV P,                  e+   VP/                  V P1                  V P,                  4      4       V'       d   VVR&   V PG                  R)R"7      PH                  PJ                  PL                  ! R./ VB pVPN                  '       dV   VPN                  ^ ,          PP                  P(                  '       d)   VPN                  ^ ,          PP                  P(                  pMR	pV'       db   R#V9   d7   \R        PT                  ! R$R	V\R        PV                  R%7      P                  4       pV'       d   VP                  RR&RV/4       V# R'p V# R'p V#   \X         d@   p \Z        P\                  ! R*T  24       R+T P                   R,\_        T 4       2p Rp ? T# Rp ? ii ; i)/zSRequest a summary when max iterations are reached. Returns the final response text.u$   ⚠️  Reached maximum iterations (z). Requesting summary...zYou've reached the maximum number of tool-calling iterations allowed. Please provide a final response summarizing what you've found and accomplished so far, without calling any more tools.r   rm  r   r4  Nr   r9  r  ra  r  TrV  rU  rb  rc  rp  r  rB  r   rZ  r[  r\  r]  r<  rd  rq  )rP  r  )rB  r   r  r^  r_  rQ  rR  r  iteration_limit_summaryr  r  z<think>.*?</think>\s*r   r  z>I reached the iteration limit and couldn't generate a summary.)rB  r   r  rQ  r^  r_  rR  iteration_limit_summary_retryz Failed to get summary response: z"I reached the maximum iterations (z!) but couldn't summarize. Error: )r4  rE  rd   )0r'  rC  r   r  r  r  r  r?  rJ  r   r`  r,  insertr8  rg  r_  r=  rt  r  r}  r   rB  r^  ru  r  rM  rN  rO  rP  r"  rP  r  r!  rK  rP  r  rY  rZ  r  r  r  r  r   r  r   r   r   rP   )!rC   r   r[  summary_requestr  rG  r   r  internal_fieldeffective_system
sys_offsetr  pfmsummary_extra_bodyrs  r  summary_responser<  r  r  summary_kwargsro  _bak_nar_ant_kw_msgretry_response	retry_msg_bak2_nar2_ant_kw2
_retry_msgr  s!   &&&                              rE   _handle_max_iterationsAIAgent._handle_max_iterationse  s&   4T5H5H4IIabc. 	
 	ODEH	A #>>@OL((*&DNKK5 'E"<<WE##G,    $99??R+++$4v$=@\@\$\#c#c#e !'9>N OPS__$$$"2Q
 )$*?*? @HC ''
(8#((*E !A "$%)=)==H2244((46:6K6K&{3 "4 (7&{3 .D-E"6*}} 11#55lC  $/#'#9#9,#G '+'E'EFV'W$!1N_"3";";"A"Ar!H!H!Jeg TZZ" ??."))$*@*@*QR (*$)))373I3I(0)))595K5K(2'''484H4H(1%%%373E3E(0'5I&z2%3EN<0==$88|"lRV.2ooPTPePe,0,D,D151N1N1PRG (,'F'Fw'O$"#3tG_G_`GD!&*ll&8&8b%?%?%AN'+'I'IQj'I'k'p'p'|'|  (D  (D  (V  GU  (V$'///4D4L4LQ4O4W4W4_4_4_)9)A)A!)D)L)L)T)T)+.%'VV,Db.`b`i`i%j%p%p%rN!OOV[)^$TUf c &fNb ] ==$55#'#9#9,#GL $$Wd3%)%;%;L%IN#'#A#A.#QLIqJSi&7&7&=&=2%D%D%FY[N]]&::~$4::TX-1-E-E/3QUQfQf262O2O2Q SH &*%D%DX%NN$).DLdLd$eMJ&0&8&8&>&>B%E%E%GN  "L&N 2&--d.D.DT__.UV)7I|4'+'I'IQp'I'q'v'v  (C  (C  (J  (J  (\  M[  (\$'///4D4L4LQ4O4W4W4_4_4_)9)A)A!)D)L)L)T)T)+! N2)+0H"ndfdmdm)n)t)t)v% i(XY  *j  &fN 	  	AOO>qcBCA$BUBUAVVwx{|}x~w  AN		As   A	^  <8^  5^  
/^  :^  ^  "A.^  .^   A&^  '^  :A0^  + ^   ^  - ^  ^  %^  2B^  A^  *,^  1^  	A^  ^  %^  *A ^  ^  B-^  A!^  .A^  ;,^  (1^  A^  ^  6^  ;^   _
4__
c                   < V ^8  d   QhRS[ RS[ RS[S[S[ S[3,          ,          RS[ RS[S[,          RS[S[ ,          RS[S[ S[3,          /# )rq   r  rv  rH  r\  stream_callbackpersist_user_messagerr   )rP   r   r   r   r   rl  )rs   rn   s   "rE   rt   r.    sx     E$ E$E$ E$ #4S>2	E$
 E$ "(+E$ 'smE$ 
c3hE$rH   c           #       a a+aaa߀ \        4        S P                  4        \        V\        4      '       d   \	        V4      p\        V\        4      '       d   \	        V4      pVS n        RS n        VS n        T;'       g    \        \        P                  ! 4       4      p^ S n
        ^ S n        ^ S n        ^ S n        ^ S n        RS n        RS n        RS n        S P$                  R8w  d)    S P'                  4       '       d   S P)                  R4       \-        S P.                  4      S n        \3        V4      ^P8  d   VR,          R,           MTpVP5                  RR4      p\6        P9                  R	S P:                  ;'       g    R
S P<                  S P>                  ;'       g    RS P@                  ;'       g    R\3        T;'       g    . 4      V4       V'       d   \C        V4      M. p	V	'       d   \E        V	4       V'       d2   S PF                  PI                  4       '       g   S PK                  V4       S ;PL                  ^,          un&        Ve   TMTp
RpS PN                  ^ 8  da   RS PP                  9   dP   S PR                  '       d>   S ;PT                  ^,          un*        S PT                  S PN                  8  d
   Rp^ S n*        RRRV/pV	PW                  V4       \3        V	4      ^,
          pVS n        S PX                  '       g1   S P[                  RVR,           \3        V4      ^<8  d   RMR R24       S P\                  Ef   RpV'       d\   S P^                  '       dJ    S P^                  Pa                  S P:                  4      pV'       d   VPc                  R4      ;'       g    RpV'       d	   VS n.        MS Pe                  V4      S n.         ^ RI3H4p T! RS P:                  S P<                  \k        S RR4      ;'       g    RR7       S P^                  '       d2    S P^                  Po                  S P:                  S P\                  4       S P\                  pS Pr                  '       Ed   \3        V	4      S Pt                  Pv                  S Pt                  Px                  ,           ^,           8  Edk   \{        T	T;'       g    RS P|                  ;'       g    RR7      pVS Pt                  P~                  8  Ed#   \6        P9                  RVR S Pt                  P~                  R S P<                  S Pt                  P                  R 4       S PX                  '       g/   S P[                  RVR R S Pt                  P~                  R R!24       \        ^4       F  p\3        V	4      pS P                  WVVR"7      w  p	p\3        V	4      V8  d    MORp\{        T	T;'       g    RS P|                  ;'       g    RR7      pVS Pt                  P~                  8  g   K   M	  Rp ^ RI3H4p T! R#S P:                  T
\C        V	4      \        V4      '       * S P<                  \k        S RR4      ;'       g    RR$7      p. pV F  p\        V\        4      '       d;   VPc                  R%4      '       d$   VPW                  \        VR%,          4      4       KS  \        V\        4      '       g   Kk  VP                  4       '       g   K  VPW                  V4       K  	  V'       d   R&P                  V4      p^ pRpRp^ p^ pRp ^ p!S P                  4        Rp"S P                  '       dA    \        T
\        4      '       d   T
MRp#S P                  P                  T#4      ;'       g    Rp"TS P.                  8  E2d   S P0                  P                  ^ 8  E1d   S P                  P                  4        S P                  '       d(   RpS PX                  '       g   S P[                  R(4       E1MT^,          pTS nN        S P                  R)T 24       S P0                  P                  4       '       gU   S PX                  '       gA   S P[                  R*S P0                  P                   R+S P0                  P                   R,24       E0MS P                  Ee-    . p$\        \        T	4      4       F  w  p%p&T&Pc                  R4      R-8X  g   K  T&Pc                  R.4      '       g   K7  \3        T	4      T%,
          p'/ p(T	T'R  FK  p)T)Pc                  R4      R/8w  d    M4T)Pc                  R04      p*T*'       g   K6  T)Pc                  RR4      T(T*&   KM  	  T&R.,           U+u. uFM  p+\        T+\        4      '       g   K  R1T+R2,          R1,          R3T(Pc                  T+Pc                  R44      4      /NKO  	  p$p+ M	  S P                  TT$4       S P                  ^ 8  d+   R6S PP                  9   d   S ;P                  ^,          unW        . p-\        T	4       EFi  w  p.p/T/P                  4       p0T.T8X  d   T/Pc                  R4      R8X  d   . p1T"'       d%   \        T"4      p2T2'       d   T1PW                  T24       T'       d   T1PW                  T4       T1'       dK   T0Pc                  RR4      p3\        T3\        4      '       d#   T3R&,           R&P                  T14      ,           T0R&   T/Pc                  R4      R-8X  d   T/Pc                  R74      p4T4'       d   T4T0R8&   R7T09   d   T0P                  R74       R9T09   d   T0P                  R94       S P                  4       '       d   S P                  T04       T-PW                  T04       EKl  	  T;'       g    Rp5S P                  '       d)   T5R&,           S P                  ,           P                  4       p5T5'       d   RR:RT5/.T-,           p-S P                  '       dS   T5'       d   ^M^ p6\        S P                  4       F-  w  p.p7T-P                  T6T.,           T7P                  4       4       K/  	  S P                  '       d&   \        T-S P                  S P$                  R8H  R;7      p-S P                  T-4      p-\        R< T- 4       4      p8T8^,          p9RoS PX                  '       g   S P                  RS P                   R=T R+S P.                   R24       S P                  S P                   R>\3        T-4       R?T9R R@T8R RA24       S P                  S P                   RBS P|                  '       d   \3        S P|                  4      M^  24       M\        P                  ! \        P                  4      p:\        P                  ! \        P                  4      p;S P                  '       d   S P                  T: RT; R24       MsS P                  4       '       g^   S P                  4       '       dH   \        P                  ! . ERO4      p<\        T: RT; R2T<S P                  RC7      oSP                  4        S P                  '       d   \        Pp                  ! RDS P<                   RE\3        T	4       RFS P|                  '       d   \3        S P|                  4      M^  24       \        Pp                  ! RGT	'       d   T	ER,          R,          MR
 24       \        Pp                  ! RHT9R RI24       \        P                  ! 4       p=^ p>^p?Rp@^pARpBRpCRpDRpERpFRpGRJpHRpIT>T?8  Ed    S P                  T-4      pJS P$                  RK8X  d   S P                  XJRRL7      pJ ^ RI3H4p T! RMTS P:                  ;'       g    RS P@                  ;'       g    RS P<                  S P>                  S P                  S P$                  T\3        T-4      \3        S P|                  ;'       g    . 4      T9T8S P                  RN7       \        RO4      '       d   S P                  XJRPRQ7       T T3RR lpKRpLS P                  4       '       g&   ^ RSIzH{pM \        \k        S RTR4      TM4      '       d   RpLXL'       d   S P                  XJXKRU7      pIMS P                  XJ4      pI\        P                  ! 4       T=,
          pNS'       d   SP                  R4       RoS P                  '       d   S P                  R4       S PX                  '       g#   S P                  S P                   RVXNRW RX24       S P                  '       dS   XI'       d   \k        XIRYRZ4      MRZpO\        Pp                  ! R[TO R\\        XIR]4      '       d   XIEP                   MRZ 24       RpP. pQS P$                  RK8X  d   XIe   \k        XIR^R4      MRpRXIf   RpPXQPW                  R_4       EM\        XR\B        4      '       g   RpPXQPW                  R`4       EM\3        XR4      ^ 8X  dm   \k        XIRaR4      pS\k        TIRbR4      pT\        Pl                  ! RcTSTT\k        TIRYR4      RdS P$                   ReS P>                   24       RpPXQPW                  Rf4       EM8S P$                  R8X  dz   XIe   \k        XIRR4      MRpUXIf   RpPXQPW                  R_4       M\        XU\B        4      '       g   RpPXQPW                  Rg4       M\3        XU4      ^ 8X  d   RpPXQPW                  Rh4       MXIe=   \        XIRi4      '       d+   XIEP                  e   \3        XIEP                  4      ^ 8X  do   RpPXIf   XQPW                  R_4       MV\        XIRi4      '       g   XQPW                  Rj4       M2XIEP                  f   XQPW                  Rk4       MXQPW                  Rl4       XP'       Ed   S'       d   SP                  Rm4       RoS P                  '       d   S P                  R4       T>^,          p>S EP                  \3        S EP                  4      8  d   S P)                  Rn4       S EP	                  4       '       d   ^ p>EK'  RooRopVXI'       d   \        XIRp4      '       d   XIEP
                  '       d{   \        XIEP
                  4      o\        TIEP
                  Rq4      '       dG   XIEP
                  EP                  '       d)   XIEP
                  EP                  Pc                  RrRo4      pVMCXI'       d<   \        XIRs4      '       d*   XIEP                  '       d   \        XIEP                  4      oXVRo8X  d<   XI'       d4   \        XIRY4      '       d"   XIP<                  '       d   RtXIP<                   2pVXVRo8X  d   XI'       d   E\        XI4      EP                  4        UWUXu/ uF3  w  pWpXTWEP                  Ru4      '       d   K   XW\        XX4      Rv,          bK5  	  pYpWpXS P                  '       d   \        Pp                  ! RwXY 24       S P                  S P                   RxT> R+T? RyRzP                  XQ4       2RR{7       S P                  S P                   R|XV 2RR{7       S EP                  S4      pZS P                  S P                   R}TZ 2RR{7       S P                  S P                   R~XNRW R2RR{7       T>T?8  d   S P)                  RT? R24       S EP	                  4       '       d   ^ p>EK  S P)                  RT? R24       \        EP
                  ! S P                   RT? R24       S EP                  Y4       RT	RRRTRpRRR/# E\        ^^T>^,
          ,          ,          ^x4      p[S P                  S P                   RT[ R2RR{7       \        Pl                  ! RT> R+T? RyRzP                  XQ4       RXV 24       \        P                  ! 4       T[,           p\\        P                  ! 4       X\8  d   S P                  '       dV   S P                  S P                   R2RR{7       S EP                  Y4       S P                  4        RRT> R+T? R2RT	RTRRRR/# \        EP                  ! R4       K  E	K]  S P$                  RK8X  dg   \k        XIRaR4      p]\k        TIRbR4      p^Rp_\        T^\        4      '       d   X^Pc                  R4      p_M\k        X^RR4      p_X]R8X  d   X_ER9   d   RpHM[RJpHMXS P$                  R8X  d)   RRJRR.RRRRJ/p`T`Pc                  XIEP                  RJ4      pHMXIEP                  ^ ,          EP                   pHXHR8X  Ed   S P                  S P                   R2RR{7       RpaS P$                  R8X  d_   \        XIRi4      '       d3   XIEP                  '       d    XIEP                  ^ ,          EP                  MRpbTb'       d   \k        XbRR4      MRpaMrS P$                  R8X  db   . pc\k        XIR. 4       F3  pd\k        TdRR4      R8X  g   K  XcPW                  \k        XdRR4      4       K5  	  Xc'       d   RP                  Xc4      MRpaXaRJ;'       d     S EP#                  Xa4      '       * ;'       g    XaRJ peTe'       dW   RpfS P                  S P                   R2RR{7       RpgS EP%                  T4       S EP                  Y4       RTgRT	RTRRRRRpTf/# S P$                  R8X  Ed@   XIEP                  ^ ,          EP                  phThEP&                  '       Eg   T^,          pS EP)                  XhXH4      piT	PW                  Ti4       ThEP*                  '       d   T XhEP*                  ,          p T^8  dV   S P                  S P                   RT R24       RRRR/pjT	PW                  Tj4       T	S n        S EP/                  T	4       RpGEMDS EP1                  T 4      P                  4       pkS EP%                  T4       S EP                  Y4       RTk;'       g    RRT	RTRRRRRpR/# \3        T	4      ^8  dc   S P                  S P                   R24       S EP3                  T	4      plS EP%                  T4       S EP                  Y4       RRRTlRTRRRRRpR/# S P                  S P                   R2RR{7       S EP                  Y4       RRRT	RTRRRRRpR/# \        XIR]4      '       Ed   XIEP                   '       Ed   E\5        XIEP                   S P>                  S P$                  R7      pmTmEP6                  pnTmEP8                  poTmEP:                  ppRTnRToRTp/pqS Pt                  EP=                  Tq4       S Pt                  EP>                  '       d   S Pt                  P                  pr\k        S Pt                  RR4      '       dQ   E\A        S P<                  S P                  Xr4       S P[                  S P                   RTrR RS P<                   24       RS Pt                  n        RS Pt                  n        S ;EPD                  Xn,          un        S ;EPF                  Xo,          un        S ;EPH                  Xp,          un        S ;EPJ                  ^,          un        S ;EPL                  XmEPN                  ,          un        S ;EPP                  TmEP8                  ,          un        S ;EPR                  TmEPT                  ,          un        S ;EPV                  TmEPX                  ,          un        S ;EPZ                  TmEP\                  ,          un        RpsTmEPT                  '       d:   Xn'       d2   RXmEPT                   R+Xn R^dTmEPT                  ,          Tn,          R R2ps\6        P9                  RS EPJ                  S P<                  S P>                  ;'       g    RXnXoXpXNXs4	       E\_        S P<                  XmS P>                  S P                  \k        S RR4      R7      ptTtEP`                  e0   S ;EPb                  E\e        XtEP`                  4      ,          un        XtEPf                  S n        TtEPj                  S n        S P^                  '       d   S P:                  '       d    S P^                  EPo                  S P:                  XmEPN                  TmEP8                  TmEPT                  TmEPX                  TmEP\                  XtEP`                  e   E\e        XtEP`                  4      MRXtEPf                  TtEPj                  S P>                  S P                  TtEPf                  R8X  d   RMRS P<                  R7       S P                  '       d8   \        Pp                  ! RXqR,          R RTqR,          R RTqR,          R 24       S P                  '       Ed   S P$                  R8X  dF   \k        XIEP                   R^ 4      ;'       g    ^ pu\k        XIEP                   R^ 4      ;'       g    ^ pvMZ\k        XIEP                   RR4      pwTw'       d   \k        XwR^ 4      ;'       g    ^ M^ puXw'       d   \k        XwR^ 4      ;'       g    ^ M^ pvXqR,          pxTx^ 8  d   XuXx,          ^d,          M^ pyS PX                  '       g/   S P                  S P                   RXuR R+XxR RXyR RXvR R2
4       RpES P                  RT R24        T'       d   EMZXF'       d3   T^,          pS P0                  EP                  4        T>^,          p>RpFEK  XG'       d   EK   XIf/   E\        S P                   ERo24       S EP                  Y4       EM S P$                  RK8X  d   S EP                  XI4      w  phpHMQS P$                  R8X  d"   ^ ERpIHp T! XIS EP                  ERq7      w  phpHMXIEP                  ^ ,          EP                  phXhEP*                  Ee   \        XhEP*                  \        4      '       Egy   XhEP*                  p\        T\        4      '       dT   XPc                  RR4      ;'       g3    XPc                  RR4      ;'       g    E\        EP                  ! X4      Xhn        EM\        X\B        4      '       d   . pX F  p\        T\        4      '       d   XPW                  X4       K,  \        X\        4      '       d:   XPc                  R4      R8X  d$   XPW                  XPc                  RR4      4       K{  \        X\        4      '       g   K  RX9   g   K  XPW                  \        XR,          4      4       K  	  RP                  X4      Xhn        M\        X4      Xhn         ^ RI3H4p \k        XhR.R4      ;'       g    . pXhEP*                  ;'       g    RpT! ERERrTERsS P:                  ;'       g    RRS P@                  ;'       g    RRYS P<                  RS P>                  RS P                  ERtS P$                  ERuTERvXNR9XHERw\3        T-4      ERx\k        XIRYR4      R]S EP                  TI4      ERy\3        X4      ERz\3        X4      /  XhEP*                  '       d   S PX                  '       g   S P                  '       d.   S P                  S P                   ER{XhEP*                   24       MRS P                  S P                   ER{XhEP*                  Rv,           \3        ThEP*                  4      ^d8  d   RMR 24       XhEP*                  '       d   S EP                  '       d   XhEP*                  P                  4       pE\        EP                  ! ER|RT4      P                  4       pT'       d!   XEP                  R4      ^ ,          R,          MRpT'       d*   \k        S ER}^ 4      ^ 8  d    S EP                  ER~X4       M(X'       d!    S EP                  ERER~XER,          R4       E\        XhEP*                  ;'       g    R4      '       Ed   \        S ER4      '       g   ^ S n        S ;P                  ^,          un        S P                  S P                   ER24       S P                  ^8:  d1   S P                  S P                   ERS P                   ER24       E!K  S P                  S P                   ER2RR{7       ^ S n        S EP3                  T	4      plS EP%                  T4       S EP                  Y4       RRRTlRTRRRRRpER/# \        S ER4      '       d   ^ S n        S P$                  RK8X  Ed   XHR8X  Ed   \        S ER4      '       g   ^ S n        S ;P                  ^,          un        S EP)                  XhXH4      pi\        TiPc                  R4      ;'       g    RP                  4       4      p\        XiPc                  R74      \        4      '       d*   \        XiPc                  R7R4      P                  4       4      MRp\        XiPc                  ER4      4      pX'       g   X'       g
   X'       Ed=   T	'       d   T	ER,          MRp\        T\        4      '       d   XPc                  ER4      MRpXiPc                  ER4      p\        X\        4      ;'       d    XPc                  R4      R-8H  ;'       d    XPc                  R94      R8H  ;'       d    XPc                  R4      ;'       g    RXiPc                  R4      ;'       g    R8H  ;'       dE    XPc                  R74      ;'       g    RXiPc                  R74      ;'       g    R8H  ;'       d    XX8H  pT'       g   T	PW                  Xi4       S P                  ^8  d\   S PX                  '       g.   S P                  S P                   ERS P                   ER24       T	S n        S EP/                  T	4       E$K  ^ S n        S EP                  Y4       RRRT	RTRRRRRpER/# \        S ER4      '       d   ^ S n        XhEP&                  '       E	d]   S PX                  '       g8   S P                  S P                   ER\3        XhEP&                  4       ER24       S P                  '       dh   XhEP&                   FV  o+\        Pp                  ! ERS+EP                  EP                   ERS+EP                  EP                  ER,           R24       KX  	  XhEP&                   F  o+S+EP                  EP                  S PP                  9  g   K,  S EP                  S+EP                  EP                  4      pT'       g   K^  E\        S P                   ERS+EP                  EP                   ERX R24       TS+EP                  n        K  	  XhEP&                   U+u. uFD  p+T+EP                  EP                  S PP                  9  g   K,  T+EP                  EP                  NKF  	  pp+T'       Ed   \        S ER4      '       g   ^ S n
        S ;P                  ^,          un
        RzP                  E\        S PP                  4      4      pX^ ,          p\3        T4      ^P8  d   XR,          R,           MXpS P                  S P                   ERT ERS P                   ER24       S P                  ^8  dM   S P                  S P                   ER2RR{7       ^ S n
        S EP                  Y4       RRRT	RTRRRRRpERX 2/# S EP)                  XhXH4      pT	PW                  T4       ThEP&                   Fp  o+S+EP                  EP                  S PP                  9  d"   ERS+EP                  EP                   ERX 2pMERpT	PW                  RR/R0S+EP                  RX/4       Kr  	  E(K  \        S ER4      '       d   ^ S n
        . pXhEP&                   F  o+S+EP                  EP                  p\        T\        \B        34      '       d+   E\        EP                  ! X4      S+EP                  n        Ka  XeJ   \        X\        4      '       g4   \        X4      S+EP                  n        S+EP                  EP                  pX'       d   XP                  4       '       g   ERS+EP                  n        K   E\        EP                  ! X4       K  	  X'       Edd   S ;P                  ^,          un        X^ ,          w  poS P                  S P                   ERT ERS 24       S P                  ^8  d0   S P                  S P                   ERS P                   R24       E*K  S P                  S P                   ER24       ^ S n        S EP)                  XhXH4      pT	PW                  T4       X UUu0 uF  w  ppTkK
  	  pppXhEP&                   Fe  o+S+EP                  EP                  X9   d!   E\        T+3ER lX 4       4      pERT ER2pMERpT	PW                  RR/R0S+EP                  RX/4       Kg  	  E+Ka  ^ S n        S EP                  XhEP&                  4      Thn        S EP                  ThEP&                  4      Thn        S EP)                  ThXH4      pThEP*                  ;'       g    RpT'       d   S EP#                  X4      '       d   XS n        E\        0 ERm4      oE\        ;QJ d+    T3ER lXhEP&                   4       F  '       d   K   RM 	  RM! T3ER lXhEP&                   4       4      pT'       d   S P                  4       '       d	   RS n        MOS PX                  '       d>   S EP1                  X4      P                  4       pT'       d   S P                  ERX 24       T	PW                  X4       S EP                  '       d    S EP                  R4       S EP                  XhYT4       RS n        ThEP&                   U+u0 uF  p+T+EP                  EP                  kK  	  pp+TER08X  d   S P0                  EP                  4        S Pt                  pTEP                  ^ 8  d!   XEP                  TEP                  ,           pME\        T	4      pXP~                  ^ 8  dI   XXP~                  ,          pTER8  d.   S EP                  '       g   RS n        S EP                  XX4       S Pr                  '       dG   XEP                  X4      '       d/   S P                  YS Pt                  EP                  TR"7      w  p	pRpT	S n        S EP/                  T	4       E.K  XhEP*                  ;'       g    RpS EP#                  T4      '       Eg   \k        S ERR4      pT'       EdB   \6        Pq                  ER4       RS n        ^ S n        \        \3        T	4      ^,
          ERER4       F  pT	T,          p/T/Pc                  R4      R-8X  g   K$  T/Pc                  R.4      '       g   K=  . pT/R.,           FV  o+S+'       d   \        S+\        4      '       g   K#  S+Pc                  R2/ 4      pXPW                  TPc                  R1R4      4       KX  	  ERRzP                  X4       ER\3        T4      ^8  d   RXMR R2T/R&    M	  S EP1                  X4      P                  4       pRS n        EMS EP                  Xh4      p4S EP)                  ThXH4      pERTR&   T	PW                  T4       T4'       dF   \3        T44      R8  d   T4ER,          R,           MT4pS P                  S P                   ERT 24       MS P                  S P                   ER24       ERpEMM\        S ER4      '       d   ^ S n        RS n        S P$                  RK8X  d   S PP                  '       d   T^8  d~   S EP                  TTT	ER7      '       db   T^,          pS EP)                  XhR4      piT	PW                  Ti4       RRRER/pjT	PW                  Tj4       T	S n        S EP/                  T	4       E1K  ^ pT '       d   T T,           pRp ^ pS EP1                  T4      P                  4       pS EP)                  XhXH4      pT	PW                  T4       S PX                  '       g   S P[                  ERT ER24        Tf   TS P.                  8  g   S P0                  P                  ^ 8:  d|   S P0                  P                  ^ 8:  dN   S PX                  '       g<   E\        R*S P0                  P                   R+S P0                  P                   R,24       S EP                  T	T4      pTRJ;'       d    TS P.                  8  pS EP                  YT4       S EP%                  T4       S EP                  Y4       T'       dS   T'       gK    ^ RI3H4p T! ERS P:                  T
T\C        T	4      S P<                  \k        S RR4      ;'       g    RER7       Rp\        T	4       F=  p/T/Pc                  R4      R-8X  g   K  T/Pc                  R74      '       g   K4  T/R7,          p M	  / RTbERXbRT	bRTbRXbRRbRTbER\k        S ERR4      bRYS P<                  bRS P>                  bRS P                  bERS EPL                  bERS EPP                  bERS EPR                  bRS EPV                  bERS EPZ                  bRS EPD                  bRS EPF                  RS EPH                  ER\k        S Pt                  ER^ 4      ;'       g    ^ ERS EPb                  ERS EPh                  ERS EPl                  /CpRS n        T'       d%   S EP                  '       d   S EP                  XER&   S P                  4        RS n        RpS P                  ^ 8  d6   S P                  S P                  8  d   R6S PP                  9   d
   Rp^ S nW        S P                  '       dK   T'       dC   T
'       d;    S P                  EP                  T
T4       S P                  EP                  T
4       T'       d9   T'       g1   T'       g	   X'       d!    S EP                  \C        T	4      TXER7        ^ RI3H4p T! ERS P:                  XTS P<                  \k        S RR4      ;'       g    RER7       X#   \*         d     E<Li ; i  \*         d     E:LNi ; i  \*         d"   p\6        Pm                  RT4        Rp?E:LRp?ii ; i  \*         d"   p\6        Pq                  RT4        Rp?E:LRp?ii ; i  \*         d"   p\6        Pm                  R'T4        Rp?E7LURp?ii ; i  \*         d     E6Li ; iu up+i   \*         d#   p,\6        Pq                  R5TT,4        Rp,?,E4LRp,?,ii ; i  \*         d     E.Li ; iu upXpWi   \*         d     EL-i ; i  E\p         d    S'       d   SP                  R4       RoS P                  '       d   S P                  R4       \        P                  ! 4       T=,
          pzS P                  S P                   R2RR{7       S EP                  Y4       RpRTzR R2p EKP  \*         Ed   p{S'       d   SP                  R4       RoS P                  '       d   S P                  R4       \        X{E\r        4      '       dT   \k        S RR4      '       gA   RS n        E\u        T	4      '       d(   S P                  S P                   R2RR{7        Rp{?{E1K   \k        X{RR4      p|S EPw                  T{4      p}S EPy                  T|XET}R7      w  p~pET~'       d    Rp{?{E1KF  S P$                  RK8X  da   S P>                  R8X  dP   X|R8X  dI   XB'       gA   RpBS EP{                  RR{7      '       d&   S P                  S P                   R24        Rp{?{E1K  S P$                  R8X  d\   S P>                  R8X  dK   X|R8X  dD   XD'       g<   RpDS EP}                  RR{7      '       d!   E\        S P                   R24        Rp{?{E2K#  S P$                  R8X  Ed   X|R8X  Ed   \        S R4      '       Ed   XC'       Eg   RpC^ RIHp S EP                  4       '       d!   E\        S P                   R24        Rp{?{E2K  S EP                  pX! T4      '       d   RMRpE\        S P                   R24       E\        S P                   RT 24       E\        X'       d*   \3        X4      ^8  d   S P                   RXR,           R2MS P                   R24       E\        S P                   R24       ^ RIHp T! 4       pE\        S P                   RT R24       E\        S P                   RT R24       E\        S P                   R24       E\        S P                   R24       E\        S P                   R24       E\        S P                   R24       T>^,          p>\        P                  ! 4       T=,
          pE\        X{4      EP                  p\        T{4      EP                  4       oS EP                  T{4      p\6        Pm                  RT>T?TS EP                  4       T4       \k        S RR4      p\k        S RR4      p3\k        S RYR4      pX|'       d   RX| R2MRpS P                  S P                   RT> R+T? RyX T 2RR{7       S P                  S P                   RX RX 2RR{7       S P                  S P                   RT3 2RR{7       S P                  S P                   RX 2RR{7       X|'       d[   X|R8  dT   \k        X{RR4      pT'       d   \        X4      R,          MRpT'       d#   S P                  S P                   RX 2RR{7       S P                  S P                   RXRW R\3        T-4       RT9R RI24       S P                  '       du   S P                  S P                   R2RR{7       S EP                  Y4       S P                  4        RRX ER S EP                  \        X{4      4       R2RT	RTRRRR/u Rp{?{# \k        X{RR4      p|T|ER8H  ;'       d<    ERS9   ;'       d.    ERS9   ;'       d     ERS P<                  EP                  4       9   pT'       Ed   ERpS Pt                  pTP                  pTT8  dc   XXn@        E\        TTEP                  ,          4      Tn?        RTn        RTn        S P                  S P                   ERXR ERTR RI2RR{7       T!^,          p!T!XA8:  dw   \3        T	4      pS P                  YT9TR"7      w  p	p\3        T	4      T8  g   XX8  d>   S P)                  ERXR ER	XR ER
24       \        EP                  ! ^4       RpF Rp{?{E#K  X|ER8H  ;'       g?    ERS9   ;'       g1    ERS9   ;'       g#    ERS9   ;'       g    ERS9   ;'       g    ERS9   pT'       d   S EP                  \3        S EP                  4      8  de   S EP                  pTRJ;'       d    XEP                  4       pT'       g3   S P)                  ER4       S EP	                  4       '       d
   ^ p> Rp{?{E8K  X|ER8H  ;'       g#    ERS9   ;'       g    ERS9   ;'       g    ERS9   pT'       Ed   T!^,          p!T!XA8  d   S P                  S P                   ERXA ER2RR{7       S P                  S P                   ER2RR{7       \        EP
                  ! S P                   ERTA ER24       S EP                  Y4       RT	RRRTRpERTA ER2RR/u Rp{?{# S P)                  ERT! R+XA R24       \3        T	4      pS P                  YT9TR"7      w  p	p\3        T	4      T8  dE   S P)                  ERX ER\3        T	4       ER24       \        EP                  ! ^4       RpF Rp{?{E&K&  S P                  S P                   ER2RR{7       S P                  S P                   ER2RR{7       \        EP
                  ! S P                   ER 24       S EP                  Y4       RT	RRRTRpER!RR/u Rp{?{# E\        ;QJ d!    T3ER" lER 4       F  '       g   K   RM	  RM! T3ER" lER 4       4      pT'       g   X|ER#8X  d   \k        \k        S ER$R4      ER%ER4      pT9TER&,          8  ;'       g    \3        T-4      ^P8  p\3        SP                  4       4      ^8  pT'       d>   X'       d6   RpS P                  S P                   ER'T9R ER(\3        T-4       ER)2RR{7       X'       g   X|'       g   ER*S9   ;'       g    ER+S9   ;'       g    XER9   pT'       d|   \k        \k        S ER$R4      ER%ER4      pT9TER,,          8  ;'       g    \3        T-4      ^8  pT'       d6   RpS P                  S P                   ER-T9R ER(\3        T-4       ER.2RR{7       X'       Ed	   S Pt                  pTP                  pE\        S4      pT'       d6   XX8  d/   XpS P                  S P                   ER/TR ER	XR ER02RR{7       ME\        X4      pX'       d   XX8  dz   XXn@        E\        TTEP                  ,          4      Tn?        RTn        \        X;'       d    XX8H  4      Xn        S P                  S P                   ER1XR ERXR RI2RR{7       M!S P                  S P                   ER22RR{7       T!^,          p!T!XA8  d   S P                  S P                   ERXA ER2RR{7       S P                  S P                   ER2RR{7       \        EP
                  ! S P                   ER3TA ER24       S EP                  Y4       RT	RRRTRpER4TA ER2RR/u Rp{?{# S P)                  ER5T9R ER6T! R+XA ER724       \3        T	4      pS P                  YT9TR"7      w  p	p\3        T	4      T8  g   X'       d\   XX8  dU   \3        T	4      X8  d%   S P)                  ERX ER\3        T	4       ER24       \        EP                  ! ^4       RpF Rp{?{E*K  S P                  S P                   ER82RR{7       S P                  S P                   ER92RR{7       \        EP
                  ! S P                   ER:T9R ER;24       S EP                  Y4       RT	RRRTRpER<T9R ER=2RR/u Rp{?{# 0 ERmp\        X{E\        E\        34      ;'       d    \        X{E\r        4      '       * p\k        X{RR4      ;'       g    / p\        T\        4      '       d#   XPc                  Rp/ 4      Pc                  RsR4      MRpX|ER#8H  ;'       d$    XP                  4       EP                  4       ER9   p\        X|E\        4      ;'       d4    ER#X|u;8*  ;'       d    R8  Mu ;'       d    X|X9  ;'       d    X'       * pX;'       gR    X;'       gH    E\        ;QJ d!    T3ER> lER 4       F  '       g   K   RM	  RM! T3ER> lER 4       4      ;'       d    X'       * pT'       Ed   S P)                  ERAX| ERB24       S EP	                  4       '       d
   ^ p> Rp{?{EAK  S P                  XJERCX{ERD7       S P)                  EREX| RyS EP                  T{4       24       S P                  S P                   ERFT| ERG2RR{7       S P                  S P                   RX RX 2RR{7       S P                  S P                   RT3 2RR{7       T|ER9   g   ER?S9   g   ER@S9   g
   ERHS9   Ed=   XR8X  d   X|R8X  d   S P                  S P                   ERI2RR{7       S P                  S P                   ERJ2RR{7       S P                  S P                   ERK2RR{7       S P                  S P                   ERL2RR{7       MS P                  S P                   ERM2RR{7       S P                  S P                   ERN2RR{7       S P                  S P                   EROX ERP2RR{7       ERQ\        T34      EP                  4       9   d"   S P                  S P                   ERR2RR{7       M!S P                  S P                   ERS2RR{7       \        EP
                  ! S P                   ERTX{ 24       X|ER#8X  d;   T9ERU8  g   \3        T-4      ^P8  d#   S P                  S P                   ERV2RR{7       MS EP                  Y4       RRRT	RTRRRRRp\        X{4      /u Rp{?{# T>T?8  Ed   X@'       g(   S EP                  X{T>T?ERW7      '       d   Rp@^ p> Rp{?{EDK  S P)                  RT? ERX24       S EP	                  4       '       d
   ^ p> Rp{?{EDK9  S EP                  X{4      pX'       d   S P)                  ERYT? ERZX 24       MS P)                  ER[T? ERZX 24       S P                  S P                   ER\X 2RR{7       \k        X{RR4      '       * ;'       d@    E\        ;QJ d!    T3ER] lER 4       F  '       g   K   RM	  RM! T3ER] lER 4       4      pT'       dC   S P                  S P                   ER^2RR{7       S P                  S P                   ER_2RR{7       \        EP
                  ! ER`S P                  T?XXX\3        T-4      T9R 4       S P                  XJERaX{ERD7       S EP                  Y4       ERbT? ERcT 2pX'       d   XERd,          pRXRT	RTRRRRRpX/u Rp{?{# RpX'       d   \k        \k        X{EReR4      ERfR4      pT'       dz   \        XERg4      '       dg   XPc                  ERh4      ;'       g    XPc                  ERi4      pT'       d3    E\        E\        X4      ^x4      pM  E\        E\        3 d     Mi ; iX'       d   XME\        ^T>,          ^<4      p[X'       d'   S P)                  ERjX[ ERkT>^,            R+T? ER724       MS P)                  RX[ ERlT> R+T? ER724       \6        Pm                  ERmX[T>T?S EP                  4       X{4       \        P                  ! 4       T[,           p\\        P                  ! 4       X\8  d   S P                  '       d\   S P                  S P                   R2RR{7       S EP                  Y4       S P                  4        RERnT> R+T? R2RT	RTRRRR/u Rp{?{# \        EP                  ! R4       K   Rp{?{EGK  Rp{?{ii ; i  \*         d     E0L^i ; i  \*         d     E.Li ; i  \*         d     E.Li ; iu up+i   E\        EP                   d?   pXPW                  S+EP                  EP                  \        T4      34        Rp?E'K"  Rp?ii ; iu uppi   \*         d     E#L*i ; iu up+i   \*         Ed   pERT ER \        T4       2o E\        ERS 24       M/  E\        E\        3 d    \6        EP                  S4        Mi ; iS P                  '       d   \        EP                  ! ER4       Rp\        \3        T	4      ^,
          ERER4       EF(  p.T	T.,          p/\        T/\        4      '       g    EMT/Pc                  R4      R/8X  d   K>  T/Pc                  R4      R-8X  d   T/Pc                  R.4      '       d   T	T.^,           R  Uu0 uF<  p\        T\        4      '       g   K  XPc                  R4      R/8X  g   K3  XR0,          kK>  	  Mu upi ppT/R.,           FW  o+S+'       d   \        S+\        4      '       g   K#  S+R4,          X9  g   K3  RR/R0S+R4,          RERS 2/pT	PW                  T4       KY  	  Rp M	  TS P.                  ^,
          8  d#   ERS 2pT	PW                  RR-RT/4        Rp?E K;   Rp?ERKW  Rp?ii ; i  \*         d#   p\6        Pm                  ERT4        Rp?ELRp?ii ; i  \*         d     ELi ; i  \*         d     ELi ; i  \*         d#   p\6        Pm                  ERT4        Rp?X# Rp?ii ; i(  a  
Run a complete conversation with tool calling until completion.

Args:
    user_message (str): The user's message/question
    system_message (str): Custom system message (optional, overrides ephemeral_system_prompt if provided)
    conversation_history (List[Dict]): Previous conversation messages (optional)
    task_id (str): Unique identifier for this task to isolate VMs between concurrent tasks (optional, auto-generated if not provided)
    stream_callback: Optional callback invoked with each text delta during streaming.
        Used by the TTS pipeline to start audio generation before the full response.
        When None (default), API calls use the standard non-streaming path.
    persist_user_message: Optional clean user message to store in
        transcripts/history when user_message contains API-only
        synthetic prefixes.
            or queuing follow-up prefetch work.

Returns:
    Dict: Complete conversation result with final response and message history
NFrq  u~   🔌 Detected stale connections from a previous provider issue — cleaned up automatically. Proceeding with fresh connection.:NP   Nr  r  rn  zPconversation turn: session=%s model=%s provider=%s platform=%s history=%d msg=%rr  r  r  Tr   rm  r   u   💬 Starting conversation: 'r  r   rE  r=  )invoke_hookon_session_startra  )rS  rB  ra  z on_session_start hook failed: %sz*Session DB update_system_prompt failed: %s)r=  r  zDPreflight compression: ~%s tokens >= %s threshold (model %s, ctx %s)r  u   📦 Preflight compression: ~z tokens >= z
 threshold)rF  r\  pre_llm_call)rS  r  rH  is_first_turnrB  ra  r  r9  zpre_llm_call hook failed: %su2   
⚡ Breaking out of tool loop due to interrupt...zstarting API call #u%   
⚠️  Iteration budget exhausted (ru  z iterations used)r  r   r   r  ra   r   r]  r  z&step_callback error (iteration %s): %sry  r4  r5  rE  r  )	cache_ttlnative_anthropicc              3   J   "   T F  p\        \        V4      4      x  K  	  R # 5irU   r  r
  s   & rE   r   +AIAgent.run_conversation.<locals>.<genexpr>  s     D|c#c(mm|r  u   🔄 Making API call #u      📊 Request size: z messages, ~z
 tokens (~z chars)u      🔧 Available tools: r.  zAPI Request - Model: z, Messages: z	, Tools: zLast message role: zTotal message size: ~z tokensrd  rp  r  pre_api_request)r\  rS  ra  rB  r<  r1  r=  r[  r;  
tool_countapprox_input_tokensrequest_char_countr^  HERMES_DUMP_REQUESTS	preflightr  c                     < S'       d   SP                  R 4       RoS P                  '       d   S P                  R 4       R# R# r6  )rd  rW  )rC   thinking_spinners   rE   _stop_spinner/AIAgent.run_conversation.<locals>._stop_spinner  s9    +,11"5/3,111 2226 2rH   r  r%  )r  u   ⏱️  API call completed in r<  r=  rB  zN/AzAPI Response received - Model: z	, Usage: r
  r  zresponse is Nonezresponse.output is not a listr^  r  zeCodex response.output is empty after stream backfill (status=%s, incomplete_details=%s, model=%s). %sz	api_mode=r  zresponse.output is emptyzresponse.content is not a listzresponse.content is emptyr  z#response has no 'choices' attributezresponse.choices is Nonezresponse.choices is emptyu   (´;ω;`) oops, retrying...u<   ⚠️ Empty/malformed response — switching to fallback...Unknownr  metadatarx  r  zmodel=r  r  z*Response attributes for invalid response: u&   ⚠️  Invalid API response (attempt z): r  r  u      🏢 Provider: u      📝 Provider message: u      ⏱️  Response time: z/s (fast response often indicates rate limiting)u   ⚠️ Max retries (u.   ) for invalid responses — trying fallback...u   ❌ Max retries (z,) exceeded for invalid responses. Giving up.zInvalid API response after z	 retries.r   r  	api_callszOInvalid API response shape. Likely rate limited or malformed provider response.re  u   ⏳ Retrying in z/s (extended backoff for possible rate limit)...zInvalid API response (retry z | Provider: u3   ⚡ Interrupt detected during retry wait, aborting.r  zAOperation interrupted: retrying API call after rate limit (retry r+  interruptedr  r  r_  rL  end_turnr  r^  stop_sequenceuQ   ⚠️  Response truncated (finish_reason='length') - model hit max output tokensro  r   r   zModel used all output tokens on reasoning with none left for the response. Try lowering reasoning effort or increasing max_tokens.uV   💭 Reasoning exhausted the output token budget — no visible response was produced.u  ⚠️ **Thinking Budget Exhausted**

The model used all its output tokens on reasoning and had none left for the actual response.

To fix this:
→ Lower reasoning effort: `/thinkon low` or `/thinkon minimal`
→ Increase the output token limit: set `model.max_tokens` in config.yamlpartialu   ↻ Requesting continuation (z/3)...z[System: Your previous response was truncated by the output length limit. Continue exactly where you left off. Do not restart or repeat prior text. Finish the answer directly.]z9Response remained truncated after 3 continuation attemptsu3      ⏪ Rolling back to last complete assistant turnz-Response truncated due to output length limitu-   ❌ First response truncated - cannot recoverz3First response truncated due to output length limitr  r  completion_tokensr  r  u   💾 Cached context length: z tokens for z cache=r  z.0fz%)zHAPI call #%d: model=%s provider=%s in=%d out=%d total=%d latency=%.1fs%sr;  )r<  r1  r;  includedsubscription_included)input_tokensoutput_tokenscache_read_tokenscache_write_tokensreasoning_tokensestimated_cost_usdcost_statuscost_sourcebilling_providerbilling_base_urlbilling_moderB  zToken usage: prompt=z, completion=z, total=cache_read_input_tokenscache_creation_input_tokensprompt_tokens_detailscached_tokensr  u      💾 Cache: z	 tokens (z% hit, z	 written)z
API call #z
 completedu    ⚡ Interrupted during API call.z3Operation interrupted: waiting for model response (r6  zs elapsed).u   (╥_╥) error, retrying..._surrogate_sanitizeduH   ⚠️  Stripped invalid surrogate characters from messages. Retrying...r  )r  rB  r@  rr  rF  u8   🔐 Codex auth refreshed after 401. Retrying request...r   u<   🔐 Nous agent key refreshed after 401. Retrying request...r#  r  uC   🔐 Anthropic credentials refreshed after 401. Retrying request...zBearer (OAuth/setup-token)zx-api-key (API key)u-   🔐 Anthropic 401 — authentication failed.z   Auth method: z   Token prefix: r  z   Token: (empty or short)z   Troubleshooting:)display_hermes_homeu"        • Check ANTHROPIC_TOKEN in z+/.env for Hermes-managed OAuth/setup tokensu$        • Check ANTHROPIC_API_KEY in z)/.env for API keys or legacy token valuesuL        • For API keys: verify at https://console.anthropic.com/settings/keysuD        • For Claude Code: run 'claude /login' to refresh, then retryu?        • Clear stale keys: hermes config set ANTHROPIC_TOKEN ""u?        • Legacy cleanup: hermes config set ANTHROPIC_API_KEY ""z;API call failed (attempt %s/%s) error_type=%s %s summary=%sr<  r1  z [HTTP r  u!   ⚠️  API call failed (attempt u      🔌 Provider: z	  Model: u      🌐 Endpoint: u      📝 Error: i  r  r  u      📋 Details: u      ⏱️  Elapsed: zs  Context: z msgs, ~u?   ⚡ Interrupt detected during error handling, aborting retries.z+Operation interrupted: handling API error (r^  rE  zextra usagezlong contextsonneti@ uO   ⚠️  Anthropic long-context tier requires extra usage — reducing context: r  u   🗜️ Context reduced to z tokens (was z), retrying...z
rate limitztoo many requests
rate_limitzusage limitquotau9   ⚠️ Rate limited — switching to fallback provider...  request entity too largezpayload too largezerror code: 413u   ❌ Max compression attempts (z&) reached for payload-too-large error.uR      💡 Try /new to start a fresh conversation, or /compress to retry compression.z413 compression failed after z
 attempts.z5Request payload too large: max compression attempts (z
) reached.u@   ⚠️  Request payload too large (413) — compression attempt u   🗜️ Compressed z messages, retrying...u2   ❌ Payload too large and cannot compress further.z/413 payload too large. Cannot compress further.z9Request payload too large (413). Cannot compress further.c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   r   r  r  s   & rE   r   r    s      2 U&I2E Ur  i  rc  r  rK  u)   ⚠️  Generic 400 with large session (~z	 tokens, u1    msgs) — treating as probable context overflow.zserver disconnectedzpeer closed connectiong333333?u1   ⚠️  Server disconnected with large session (~uD    msgs) — treating as context-length error, attempting compression.u)   ⚠️  Context limit detected from API: r  u3   ⚠️  Context length exceeded — stepping down: uM   ⚠️  Context length exceeded at minimum tier — attempting compression...z!Context compression failed after z3Context length exceeded: max compression attempts (u   🗜️ Context too large (~u    tokens) — compressing (z)...u8   ❌ Context length exceeded and cannot compress further.u      💡 The conversation has accumulated too much content. Try /new to start fresh, or /compress to manually trigger compression.zContext length exceeded: z! tokens. Cannot compress further.zContext length exceeded (z" tokens). Cannot compress further.c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   r  s   & rE   r   r  p   s%      b E  {Alubu Er  unauthorized	forbiddenu!   ⚠️ Non-retryable error (HTTP u   ) — trying fallback...non_retryable_client_error)r  r  u   ❌ Non-retryable error (HTTP u%   ❌ Non-retryable client error (HTTP z). Aborting.
permissionuK      💡 Codex OAuth token was rejected (HTTP 401). Your token may have beenz?      refreshed by another client (Codex CLI, VS Code). To fix:z?      1. Run `codex` in your terminal to generate fresh tokens.z3      2. Then run `hermes auth` to re-authenticate.u9      💡 Your API key was rejected by the provider. Check:u-         • Is the key valid? Run: hermes setupu+         • Does your account have access to rD  rw  u?         • Check credits: https://openrouter.ai/settings/creditsu6      💡 This type of error won't be fixed by retrying.zNon-retryable client error: r  uU   ⚠️  Skipping session persistence for large failed session to prevent growth loop.)r   r  u"   ) exhausted — trying fallback...u   ❌ Rate limited after u    retries — u   ❌ API failed after u      💀 Final error: c              3   ,   <"   T F	  qS9   x  K  	  R # 5irU   rd   )r   r|  r  s   & rE   r   r     s      $ =qN =r  u      💡 The provider's stream connection keeps dropping. This often happens when the model tries to write a very large file in a single tool call.z~      Try asking the model to use execute_code with Python's open() for large files, or to write the file in smaller sections.zP%sAPI call failed after %s retries. %s | provider=%s model=%s msgs=%s tokens=~%smax_retries_exhaustedzAPI call failed after z
 retries: u  

The provider's stream connection keeps dropping — this often happens when generating very large tool call responses (e.g. write_file with long content). Try asking me to use execute_code with Python's open() for large files, or to write in smaller sections.r  r  r   r  r  u#   ⏱️ Rate limit reached. Waiting zs before retry (attempt zs (attempt z4Retrying API call in %ss (attempt %s/%s) %s error=%sz<Operation interrupted: retrying API call after error (retry u:   ❌ All API retries exhausted with no successful response.r  r  r\  rS  r=  r[  api_durationr;  response_modelassistant_content_charsassistant_tool_call_countu   🤖 Assistant: z,</?(?:REASONING_SCRATCHPAD|think|reasoning)>r  	_thinkingzreasoning.availabler  _incomplete_scratchpad_retriesuL   ⚠️  Incomplete <REASONING_SCRATCHPAD> detected (opened but never closed)u   🔄 Retrying API call (z/2)...uA   ❌ Max retries (2) for incomplete scratchpad. Saving as partial.z/Incomplete REASONING_SCRATCHPAD after 2 retries_codex_incomplete_retriesr  u0   ↻ Codex response incomplete; continuing turn (z/3)z@Codex response remained incomplete after 3 continuation attemptsu   🔧 Processing z tool call(s)...zTool call: z with args: r   u   🔧 Auto-repaired tool name: 'z' -> '_invalid_tool_retriesu   ⚠️  Unknown tool 'u2   ' — sending error to model for self-correction (uI   ❌ Max retries (3) for invalid tool calls exceeded. Stopping as partial.z#Model generated invalid tool call: zTool 'z#' does not exist. Available tools: zZSkipped: another tool call in this turn used an invalid name. Please retry this tool call.rg  u1   ⚠️  Invalid JSON in tool call arguments for 'r%  u;   ⚠️  Injecting recovery tool results for invalid JSON...c              3   f   <"   T F&  w  rVSP                   P                  8X  g   K"  Vx  K(  	  R # 5irU   r  )r   r  r  r   s   &  rE   r   r  X"  s,     .h=NTQRSWYWbWbWgWgRgqq=Ns   1
1zError: Invalid JSON arguments. z_. For tools with no required parameters, use an empty object: {}. Please retry with valid JSON.z;Skipped: other tool call in this response had invalid JSON.c              3   V   <"   T F  pVP                   P                  S9   x  K   	  R # 5irU   r  )r   r   _HOUSEKEEPING_TOOLSs   & rE   r   r  "  s(      0&B KK,,0CC&Bs   &)u     ┊ 💬 execute_coder  _last_content_with_toolsuO   Empty follow-up after tool calls — using prior turn content as final responsezCalling the z toolz(empty)uA   ℹ️  Reasoning-only response (no visible content). Reasoning: u1   ℹ️  Empty response (no content or reasoning)._empty_content_retries)r  r  r   zr[System: Continue now. Execute the required tool calls and only send your final answer after completing the task.]u"   🎉 Conversation completed after z OpenAI-compatible API call(s)z)Error during OpenAI-compatible API call #u   ❌ zDetailed error information:zError executing tool: z0I apologize, but I encountered repeated errors: post_llm_call)rS  r  assistant_responserH  rB  ra  zpost_llm_call hook failed: %slast_reasoningresponse_previewed_response_was_previewedr  r  r  r  r  r  r  r  interrupt_message)rb  rc  rd  rd  )rS  r  r  rB  ra  zon_session_end hook failed: %s)brainsparklepulsemoonstarr  >   rL  r;  )zcontext lengthzcontext sizezmaximum contextztoken limitztoo many tokenszreduce the lengthzexceeds the limitzcontext windowr  zprompt is too longzprompt exceeds max length)	ReadErrorr  ServerDisconnectedError>     r  rE  )r  r   )zerror code: 401zerror code: 403zerror code: 404zerror code: 422zis not a valid modelzinvalid modelzmodel not foundzinvalid api keyinvalid_api_keyauthenticationr  r  z	not found)rF  i  )r  r  r  r  r  r  )post_api_request>   r  r  ry  rx  (  r|   r  rO   rP   r   r  r  r  r8  r9  r  _invalid_json_retriesr  r  r  r  r  r  r=  r  r  r   r~   rC  re  rQ   r  r  r  rS  rB  r<  ra  r   r  rH  	has_itemsro  rf  rM  r4  rJ  rO  r   rI  r  r?  rB  get_sessionr   r  hermes_cli.pluginsr  r`   r   r  r   rd  rc  r  r  r!   r  rs  r  r  r  r   r   r   r  rM  rS  prefetch_allr   rA  new_turnr  r  rR  r   r   r   rZ  r,  rm  ra  rP  r  r   r  r  r  rJ  r`  r  r
  r(   r  r  r  r  rL  rR  rS  r3   KAWAII_THINKINGTHINKING_VERBSrW  r  r  r  r  rH  r   r  rt  rJ  r1  r^  r<   r2  r  r  r  rf  rd  r*  r
  r  r0  r/  r  r  r  r  varsr6  r  r  r  r   r  stop_reasonrE  r  r_  r   r  r   r>  r  r  r  r2   r  r  r  update_from_responser  r$   r  rg  rh  ri  rj  rk  r  rl  rm  r  rn  r  ro  r  r1   
amount_usdrp  rk  r^  rq  r  rr  update_token_countsre  UnicodeEncodeErrorr   r  rK  r  r*  r'  r"  r  r/  r#  r\  r  r   re   r7  r  r  r   r  r  has_availabler   r#   r"   rN   r   r	  r   r}  r  r!  r   r   r  rT  r  r   r  r9   r   ra   r   r  r5  r  r   r   nextr  r  	frozensetallr[  r  r  r  r  r    r  r  rP  r 	  rB  rJ  r/  rM   	exceptionr  r  r  sync_allqueue_prefetch_allr  )rC   r  rv  rH  r\  r  r  r  _msg_previewr   original_user_message_should_review_memoryuser_msgcurrent_turn_user_idxstored_promptsession_row_invoke_hookr)  r  active_system_prompt_preflight_tokens_pass	_orig_len_plugin_user_context_pre_results
_ctx_partsr4  r[  r  r  codex_ack_continuationslength_continue_retriestruncated_response_prefixcompression_attempts_ext_prefetch_cache_query
prev_tools_idx_m
_fwd_start_results_by_id_tm_tcidr   	_step_errrG  r  r   r  _injections_fenced_baserM  r  r  r  total_charsrF  rg  verbr/  api_start_timer   r  primary_recovery_attemptedmax_compression_attemptscodex_auth_retry_attemptedanthropic_auth_retry_attemptednous_auth_retry_attemptedrB   restart_with_compressed_messages restart_with_length_continuationrE  r  r  r  _use_streamingr  r  
resp_modelresponse_invaliderror_detailsoutput_items_resp_status_resp_incompletecontent_blocksrx  r(  r)  
resp_attrscleaned_provider_errorr  	sleep_endr^  r  incomplete_reasonstop_reason_map_trunc_content
_trunc_msg_text_parts_blk_thinking_exhausted_exhaust_error_exhaust_responser<  interim_msgcontinue_msgpartial_responserolled_back_messagescanonical_usager  r  r  
usage_dictctx
_cache_pctcost_resultr)  writtendetailsr~  hit_pctapi_elapsedr  r  r@  recovered_with_poolr  r  auth_method_dhh_fn_dhhelapsed_timer  _error_summary	_provider_model_status_code_str	_err_body_err_body_str_is_long_context_tier_error_reduced_ctxrV  old_ctxr!  is_rate_limitedr  pool_may_recoveris_payload_too_largeis_context_length_errorrW  rR  is_generic_error_is_server_disconnect	_is_largeparsed_limitnew_ctx_RETRYABLE_STATUS_CODESis_local_validation_error_err_message_is_generic_400is_client_status_erroris_client_error_final_summary_is_stream_drop_final_response_retry_after_resp_headers_ra_rawr  r  r   r   _assistant_tool_calls_assistant_text_think_text
first_lineinterim_has_contentinterim_has_reasoninginterim_has_codex_reasoninglast_msglast_codex_itemsinterim_codex_itemsduplicate_interimrepairedinvalid_tool_callsr  invalid_nameinvalid_previewr  r   invalid_json_argsrA  r   recovery_assistantra   r  invalid_nameserrtool_resultturn_content_all_housekeepingclean	_tc_names_compressor_real_tokens_compaction_progressfallbackr  r   r  reasoning_preview	final_msgpending_handledr  answered_idserr_msgr  r  r]  _should_review_skillsr  r  r  s   f&&&&&&                                    `                                                                                                                                                                                 @@@rE   ru  AIAgent.run_conversation  siX   < 	
 	%%'
 lC((/=L*C00#78L#M  !0)-&.B+#88s4::<'8 &'"%&"&'#./+)*&(,%#( $)!
 ==001133%%& !00C0C D 7:,6G"6LS)E1R^#++D#6^OO%%vtzz4==3M3MIMM&&Y,@,F,FB(G		
 2F4,-2 /9
  (8(8(B(B(D(D$$%9: 	" 9M8X 4^j
 !&''!+ 5 55&&&$$)$''4+F+FF(,%+,( FI|<! #H 1)>&<\#=N<OY\]iYjmoYoPUuwOxxyz{ %%- M#(8(8(8"&"2"2">">t"OK"(3(H(P(PD  .;* .2-F-F~-V*
	LN *#'??"jj!(z4!@!F!FB	 ###V((==dootOiOij  $99 $$$H 7 7 G G"&"9"9"H"H!IKL!M M
 !>288bjj((D! !D$;$;$L$LLZ(+..??BJJ..==a@ $$78I!7L M"55FFqIU #1XE #HI595K5K @Q 1 6L 62H2 8}	1 ,0((E &:&@&@b"jj00D)%
 )4+B+B+S+SS+ &F  "	@F'??2%)(^#'(<#==jj z48>>BL %'J!a&&155+;+;%%c!I,&783''AGGII%%a(	 "
 '-{{:'>$
 "#"#$&!  	 !2<=RTW2X2X.^`&*&:&:&G&G&O&U&USU# t222t7L7L7V7VYZ7Z  ))+ ((("$$%Z[aN#1D   #6~6F!GH((0022$$'MdNcNcNhNhMiijko  lA  lA  lK  lK  kL  L]  &^  _ !!-f!#J$-hx.@$Ab66&>[8RVVL=Q=Q),X)=J-/N'/
'<#&776?f#<$)(+(?#(5<?GGIr<RN5$9 (= +-\*:*
 +;B#-b$#7!"$*BzN6,B$,n.@.@.N!" +; ' * "% %B& &&~zB **Q.&$*?*??''1,' L%h/S((* //CGGFOv4M"$K*"<=P"Q"'..w7+#**+?@" 'Ir :%eS1116&++kBZ1ZGI. 776?k1%(WW[%9N%7E 34 ')KK,"g-KK0
 3355<<WE ##G,Y 0d  499r+++$4v$=@\@\$\#c#c#e 
  !'9>N OPS__ $$$"2Q
 )$*?*? @HC ''
S(8#((*E !A '''<\UYUdUdx|  yF  yF  J^  y^   `  66|DL D|DDK'1,M  $???r$//!22HHXXYZ^ZmZmYnnqrs00Fs<GXFYYefstuev  wA  BM  NO  AP  PW  X  Y00I]a]g]g]g#djj/mnIopq }}]%B%BC}}]%A%AB))) **dV1TF#+>?3355$:Z:Z:\:\ $*==1^#_L'4vQtfC5HWcnrn|n|'}$$**, ### 5djj\cRZm_\ey}  zD  zD  zDfijnjtjtfu  JK  fL  M  N 3HHRL4HZ`3abc 5mA5FgNO!YY[NKK).&'($',&+0*&+%#O/4,/4,"MH+z(!%!7!7!EJ}}(99%)%E%Ej_d%E%e
R$-$5'+'<'<"%)]]%8%8b"&**%)]]%)]]%)]]+9*-l*;'*4::+;+;'<0=/:'+& ''=>>44Z4T7 &*N5577 7%gdHd&CTJJ-2N%#'#I#I&} $J $ $(#?#?
#K#'99;#?L ((--b1+/(---..r2???'88VWcdgVhhi%jk+++JRWXw%FX]
(G
|S\ovw  BI  pJ  pJ]e]k]k  PU  ]V  'W  X (-$$&M}}(99LTL`wx4'Hfj#+/3,)001CD!+L$!?!?/3,)001PQ .!3 ,38Xt+LL/6xAUW[/\,#OO!S ,.> ''4 @"+DMM?*T]]O T 04,)001KL*>>OWOc9d)Kim#+/3,)001CD!+ND!A!A/3,)001QR 0A5/3,)001LM#+78Y3O3OS[ScScSkors{  tD  tD  pE  IJ  pJ/3,'/ - 4 45G H%,Xy%A%A - 4 45Z [!)!1!1!9 - 4 45O P - 4 45P Q''+,112OP/3,111 2226 $q(
  //#d6J6J2KK --.lm6688*+K$ %.	(1#'(B(Bx~~~(+HNN(;I&x~~zBBx~~G^G^G^080G0G0K0KO]f0g%'(I*F*F8K[K[K[(+H,<,<(=I )I5(wxY`GaGafnftftft.4X^^4D,EM )I5(FJ8nFZFZF\)vF\dadedpdpqtdu/!SVD\/F\J)v#333 '0Z[eZf.g h'88^_j^kklmxlyy|  ~B  ~G  ~G  HU  ~V  }W  &X  `d  e'88J=/%Zbfg151J1J91U.'88RSiRj%kswx'88RS_`cRd  eT  &U  ]a  b&+5 --0D[MQ  /A  B#::<<./ ( --0A+Nz.{|#MMT__,==XYdXeen*op 11(Q *H +U +^ ')z ($$  %(Q;?-C(Dc$J	'88H  TC  &D  LP  Q*F{mSTU`Taadeieneno|e}d~  L  MZ  L[  )\  ] %)IIK)$;	"iikI5#888 $/@@s-t  }A  !B $ 5 5h U $ 4 4 6$48y  {F  zG  GH  IT  HU  UW  7X$.$/$/$14(" !" !JJsO  }}(99!(8T!B-4X?SUY-Z*,0)%&8$??0B0F0Fx0P-078JHVZ0[-!\16GKj6j,4M,2M*>>+5vz<Yego  rA  CI  +J(7(;(;H<P<PRX(Y(0(8(8(;(I(I$0'8  9J  &K  SW  X *.==,>>IPQY[dIeIejrjzjzjz)9)9!)<)D)D  BFJU_WZD-QeiN!]].BB*,K(/)R(H#*4#>&#H$/$6$6wtVR7P$Q )I HSTYY{-CX\N +$6 X X$($G$G$W W/4 /4 ,t3 ,
 /!9 +
 !LL#'??"3 4D !E&* ) !H . !889JK 11(Q 02C *H +^ +U )4 '$   ==,>>080@0@0C0K0K-#4#?#?#? 71 < 7.2.K.KL]_l.m ( <#4#<#<#<$=ARAZAZ$Z$=#:Q#>$(LL+/??*; <,,C+DF)L%&
 )/(1-i4&L %-OOL$A=ED$:$($:$:8$DGK$D$)373K3KLe3f3l3l3n 0 $ < <=N O $ 5 5h U$46F6N6N$$.$/$/$-t$+-h(" !" x=1, LLDOO+<<o)pq373Z3Z[c3d0 889JK 11(Q !1$ *,@ +^ +U )4 ')X$  !LLDOO+<<i)jrvLw 11(Q 0$ *H +^ +U ($ ')^$  x11hnnn*9$NN%)]]%)]]+
 )8(E(E,;,I,I)'6'C'C+]/1B*L&

 //DDZP
  22BBB"&"9"9"H"HC&t'>'>@\^cdd 3DJJs S $ 0 0DOO3DD`adef`ggstxt~t~s  2A  !BFKD33CQVD33N22mC266:KK611\A1..!3.11_5Q5QQ122o6S6SS266/:[:[[677?;];]]7559Y9YY5 &(
*<<<+2?3T3T2UUVWdVeeghkl{  mN  mN  iN  O\  i\  ]`  ha  ac  *dJf 22DJJ@Z@ZQZ)+<l(*	 ': JJ+%)]]%)]]$+D)R$@' '11= ;;u[E[E[?\\;3>3E3E03>3E3E0  +++% $ 0 0 D D$(OO1@1M1M2A2O2O6E6W6W7F7Y7Y5D5U5U'2'='='I 8=[=S=S7TOS0;0B0B0;0B0B59]]59]]'2'9'9Z'G 2IMQ*.** !E !"(  ///#MM,@OA\]^@__lmw  yL  nM  NO  mP  PX  Yc  dr  Ys  tu  Xv  +w  x  333#}}0DD)0AZ\])^)c)cbc*1(..B_ab*c*h*hgh +2(..BY[_*`V]/1)M)R)RQRcd\c'';OQR*S*X*XWXij%/%@FAG!v'<QRG#'??? $/@PVWXzYZ[abcZddmnuvymz  {B  CJ  KL  BM  MV  .W  !X&+O((:n5EZ)PQB /!#%%,,. q 380/
 ))cde%%hEt==$557;7U7UV^7_4%}]]&::T7S D4L4L84%} )1(8(8(;(C(C%
 %,,8L]LeLegjAkAk+33C!#t,,47GGFB4G4t4t377S\^`Ka4t4teieoeopset)1#C.. "$'D)$44 %T 2!+D$!7!7DHHV<LPV<V %TXXfb-A B!+D$!7!7FdN %Sf-> ? %( 59IIe4D)147H)1N,34E|UY,Z,`,`^`)&7&?&?&E&E2O   1 $(??#8#8b "&!4!4"	
 #jj "& "& "& (6 &2 '4 '*,&7 (/x$'G #FFxP 14O0D  366K2L!, %,,,T___+++'88HIZIbIbHc%de'88HIZIbIbcgIhHisv  xI  xQ  xQ  tR  UX  tXjo  ^`  ja  &b  c &---$2M2M2M"3";";"A"A"CK"$&&G[#eg  
 EP!2!24!8!;C!@UWJ!gd4Eq&IA&M! 77ZP %! 778M{\ghl\most -->-F-F-L-L"MM"4)IJJ>?;771<7LLDOO#4  5A  "B  C::a?'88PQUQtQtPuu{%|}  '88y%z  CG  H>?;/3/V/VW_/`,445FG--hM -d&(<''%t#%V   4!ABB:;D7==$55-<:W"4)DEE9:622a72"&"?"?@QS`"aK*.	0J0P0Pb/W/W/Y*Z'^hitixix  zE  jF  HK  _L  _LDb1Q1W1W1Y,Z  RW)26{G^7_2`/*.CGbGb3;8B< U__gimTnTn8<<8O+Ptx(.9oo>U.V+&x6 H H (V 4 CH H (_ = MH H "*i!8!>!>BKOOT]D^DdDdbd eH H "*k!:!@!@bkooVaFbFhFhfh i	H H
 !14G G *  1$OOK8559# LLDOO+<<lmq  nL  nL  mM  MP  *Q  R19...x8 56D2))(I($"H#^#U!4!c  T#>??56D2 %///???'88HM^MiMiIjHkk{%|}+++"3">">B#MMK8H8H7IVXVaVaVkVklpVqUrru*vw #?
 0::;;++43H3HH'+'='=bkk>N>N'OH'x %(99XY[YdYdYiYiXjjpqypzz{&| }3; 0 ; 4E3O3O*3OR;;++43H3HH )((3O ' * *)&t-DEE9:D622a72 %)IIfT5J5J.K$L	'9!'<GJ<GX[]G],s*;e*Cco'88NN_  `R  SW  Sm  Sm  Rn  nq  &r  s55: LLDOO+<  =F  *G  OSL  T9:D6 11(Q 0$ *H +^ +U )4 '+NN_)`$  )-(E(EFWYf(g 6"3">">B!{{//t7L7LL,22;;3C3C2DDghqgr*s +G$OO & . )7-  #? !t%<==562 )+%/::!{{44%dT4L9948JJt4DBKK1$+JtS4I4I47IBKK1#%;;#8#8D#4::<<48BKK1$Q JJt, ;" )(22a72/@/C,	9'88ijsittw  yB  xC  &D  E559 LLDOO+<<TUYUoUoTppv)wx$ !LLDOO+<<w)xy9:D6 261N1NO`bo1p.$OO,>? BS,SARgdATARM,S&7&B&B#%;;#3#3}#D*..h=N.h*hC*I# OH )I %0 3pK ($*F$2BEE$-{1" !# 'C % 23D. 483P3P)444%0 483O3O)444%0 %)$A$ABSUb$cM $5#<#<#B#BL#(K(KL(Y(Y8D5 /8 9 /+ -0C 0&7&B&B0CCC 0&7&B&B0 -) -1K1K1M1M7;D4!___$($<$<\$J$P$P$RE$ ${5'-B COOM2 111! 66t< ,,->]kl 04D,
 =N<X<X Y<Xb!1!1<XI Y ^$44--446  #'"9"9K"559'::)@@A %
 (Fh'O #33a7/;k>Z>Z/Z,/47@]@]@]<@D9 778LkZ///K4O4OP\4]4]9=9O9O$*.*A*A*T*T$5 :P :6"6 04, .6D***84  &7%>%>%D%D"N  >>~NN
 $+41KT#R#8"LL)z{<@D9:;D7%*3x=1+<b"%E&.qk#&776?k#AcgglF[F[13J.1,.?.?/1B9M9Mx-/VVJ-C(2(9(9"&&:S(T /@ 8DDIIjDYCZZ_gjkugvyzgz`c  AC  `D  DG  6HC	N$) &F .2-E-Eh-O-U-U-WN;?D8! *.)@)@AR)S(,(E(EFWYf(g3<i0 6)PSTbPcfiPit0Du0Lo}- LLDOO+<<}  P  ~Q  *R  S LLDOO+<<m)no)2 t%=>>6739=D6 ):: 1113a7 CC)5.<%- D   014/&*&C&CDUWc&d 4 #F%!U( !519...x8 ./+0)B^)S46123/ &*%=%=n%M%S%S%UN $ = =>OQ^ _IOOI.???((+MnM]]{)|}l !d111$$..!3$$..!3DOOO>t?T?T?Y?Y>ZZ[\`\q\q\{\{[|  }N  O  P!88>RN #$.WW>DDWDW3W	 	hi@ 	$$%67 	h= +EJ##!6'5)-h**$T:t<BB H%Cwwv+-#''+2F2F!$[!1 &
n
n
 
 	

 
 u
 ;
 !'$0I5"Q
 TZZ
 
 
 D55
 T77
  !?!?
 !$"A"A
   = =!
" T77#
$  !?!?D55 '$*A*ACWYZ"["`"`_` $"A"A433433/
2 (-$ 4222*.*A*AF&' 	 !% !&&&*++t/I/II"d&;&;;$(!&'D#
 N7L$$--.C^T$$778MN +3HLa--&*8n"7"7 . $	BF ??#'jj z48>>B wE  h ! , ! LNN#EsKKL % V%QSTUUV~  	@NN93??	@2  H* ! fLL!I>[deefL % d *wv $- % $%4 ( '(--b1+/(---..r2"&))+">KLLDOO#44T!U]aLb))(I"&K'Z[fgjZkkv%wN  O	('(--.LM+/(---..r2 ")-?@@QUWmotIuIu4818BB LL#'??"33{ |&* )  % #*)]D"IK$($C$CI$NM;?;];]$/(7&3 <^ <8'
 + ):: MM^;'3. :592EEDEQQ LLDOO+<<t)uv$);; MMV3'3. 9481DD4DPP!T__$55q"rs$)=='3.#D*>?? > >9=6KIIKK!T__$55x"yz$"55FUVYFZFZ&B`u 11^_` 11A+OPTW\_`c\dgi\i 11B3s8*CPrv  sB  sB  rC  C]  p^  _ 11DEFS&y 11STXSY  ZE  F  G 11UVZU[  \E  F  G 11}~ 11uvw 11rst 11rst1$K#'99;#?L!%i!9!9J #I 4 4 6I%)%>%>y%INNNU##"002& !(j) DI#D*i@E$T7I>FCNQ'?TV$LLDOO#44UVaUbbcdocppst~s  AQ  @R  "S  [_L  `LLDOO#44FykQZ[aZb!ckoLpLLDOO#44Fug!NVZL[LLDOO#4ONCS!T\`La"{S'8$+Ivt$D	@IIt(<t( LLDOO+<<Mm_)]eiLjLLDOO#44HVYHZZfgjkwgxfy  zB  CP  QR  BS  SZ  "[  \ 000'88w%x  AE  F--hM,,.,0[\f[ggijn  kD  kD  EH  IR  ES  kT  jU  UW  /X&'')4   #*)]D"IK $s* ; ;)Y6; ;*i7; ; %

(8(8(::	 0 32'-%)%<%<
",";";"\18DJ5:= ,z/K/K K;J7 :>J6
 EJJA LL#'??"3 4N#*1+U<2B'!K '+	 )  -1,/3KK+.x=L=A=S=S (.;(9 >T >:H&:
  #8}|;w?U $ 1 1&A,qAQ R,,3A;n%F!" !%

1CG @ % $s* 0 0'940 0.);0 0 (940 0 )I5	0 0
 #i/ $ '4+?+?#dFZFZB[+[
  $44+/t+;+T+T@R@R@T(/ --.ij#::<<./ ( $s* : :5B: :.);: : -	9	 ) ,+,1,/2JJ LLDOO+<<Z[sZt  u[  *\  dhL  i LLDOO+<  =O  *P  X\L  ]#MMT__,==Z[sZtt~*  A 11(Q *H +U +^ '+`ay`z  {E  *F )4$  )),l  nB  mC  CD  E]  D^  ^a  +b  c'*8}9=9O9O$M$5 :P :6"6
 x=<7 --0CL>QVWZ[cWdVee{.|} JJqM?C<! LLDOO+<<n)ow{L| LLDOO+<  =O  *P  X\L  ]#MMT__,==l*mn 11(Q *H +U +^ ')d )4$  /2c 2 U 2ccc 2 U 2 /+" 3{c7I")'$8Ld*SUegm"n+87S=+H+b+bCP\L]`bLb(+.y/@+AB+F(+0@6:3 LL#'??"3 4%%21$5Ys<?P>Q RI!J '+	 )  3;1Y> m m79Dm m)-ll .
 1&-gd<PRV.WYikq&rG(5#(E(`(`\IZ]`I`I(:> 7 $'+&7 8))6q(93|CTBU V`%a +/	 !- !" /.%)%<%<
",";"; (Fi'P'L7,B&2G LLDOO+<<efmnoepp}  F  GH  ~I  IJ  *K  SWL  X ':'&BG"w'88?J5:=g
HdHd>d:eJ79=J6 EI , H H1HEJA !LLDOO+<<opwxyozz  AH  IJ  @K  KR  *S  [_L  ` LLDOO+<  =J  *K  SWL  X,1,/2JJ LLDOO+<<Z[sZtt~)  HLL  M LLDOO+<  =O  *P  X\L  ]#MMT__,==^_w^x  yC  +D  E 11(Q *H +U +^ '+^_w^x  yC  *D )4$  )),HWXHYYs  uI  tJ  JK  Ld  Ke  ei  +j  k'*8}9=9O9O$M$5 :P :6"6
 x=<77wQXGX"8}|; $ 1 14G~UZ[^_g[hZii  3A  !B JJqM?C<! !LLDOO+<<t)u  ~BL  C LLDOO+<  =~  *  GKL  L#MMT__,==VWdefVg  hI  +J  K 11(Q *H +U +^ '+D]STDUUw)x )4$ $ />+"9z9.EF J J *96H II . !(	64 @ F FBIU_`ikoUpUpIMM'2$>$B$B9b$QvxL'2c'9'k'kl>P>P>R>X>X>Z^k>kO-7S-I  .n  .ncU`NfNfcfNf  .n  .nkv  V  lV  .n  .n  _n  [n*'@ ( (DZ ( (^a^a b E b^a^a^a b E b _ '8 '8 !87 $ ' )),Mk]Zr*st6688*+K$44&/KS\ 5  ))<[M#88CDF '88]^i]jjv%w  @D  E'88J9+U^_e^f%gost'88J5'%RZ^_&*4)8SWbfoWos  DM  tM(N:{c?Q $/@  AL  .M  UY  !Z $/@@  .A  IM  !N $/@@  .A  IM  !N $/@@s-t  }A  !B $/@@y-z  CG  !H $/@@m-nvz { $/@@klrksst-u  ~B  !C#/3u:3C3C3E#E$(LLDOO3D  ED  2E  MQL  %R LLDOO+<<r)s{L  A(99UV_U`&ab '#-=53HCP\L]`bLb LL#'??"3 4S !T&* )  !11(Q,d&''$d#S^   #k1
  :d>a>a%;K ?b ? ? :>6*+K$)),@Mo*pq6688*+K$)-)B)B9)M* --0G}Tabpaq.rs --0Ek]R_`n_o.pq'88MnM]%^fjk !(	=$ GG   # $ = $ $ = $ ! ( + LL#'??"3 4> !? '+ )  !LL#'??"3 4, !- '+ )   n OO[.%vs</@]STDU
 44&/Fi 5  --hM,B;-zZhYi*j*+!JO -o&''$d#^   $(L&(/	:t0TV_ae(f(W]E-J-J&3&7&7&F&j&j-J[J[\iJjG&!)36s7|S3IL(1:'> !)$(!)0<#a;FVXZB[I&)),OPY{Zrs~  BC  tC  sD  DE  FQ  ER  RV  +W  X)),<YK{S^R__`al`mmq*rsNNN!##002! !%		i 7I))+	1444 LLDOO+<<o)px|L} 11(Q 002 04pq|p}}~  @K  L  LN  3O *H +^ +U -t$  

3 2GO	(@ ! 0  ) ! !
  ) ! !R*~  $33 Q-44bkk6F6FA5OPPQ2 -TH  ) ! !  !Zt  2GGWWYZ]^_Z`Yab	,D,-, ,LL+, '''%%&CD
 #( X!2B;C"3-C%c400wwv&0 wwv+5#'',:O:O &.cAgh%7(%7)!T2 .78uuV}7N .An--%7( (
 #&l"3"3B#%ZD-A-A8!$x|;$*F$2BtH$-1G	{/S+"
 !) 8 #4 +/- <> "T%8%81%<<'WXaWb%cN OOV[)^$TU =[2r  E>DDE~    .  	BNN;SAA	Bs  )Cw ?Cw %,Cw- Cw- *Cw- 2Cw? Cw? "0Cx. %BCy .6Cy )Cy Cy Cy ";Cz Cz 
/Cz# >Cz# A
Cz# &$Cz# 
Cz'6CzCz# 5C{= C{ 1C{ AC{ @C{ @0AC{= A3,C{= B AC{= C)$C{= D"C{= D13C{= E%C{= E-I4C{= O"C{= O*$C{= PA'C{= Q7C{= Q<C{= R$C{= R-AC{= S>0C{= T/$C{= U$C{= U9#C{= VC{= V;C{= WC{%W;C{%XDC{= \$C{= \)AC{= ^B=C{= aAC{= bC{= b2D.C{= g!(C{= h
AC{= i'C{= i9C{= jC{= j6C{= kAC{= lAC{= m?C{= nA.C{= pAC{= qC{= q*A1C{= s?C{= t&C{= uI0C{= ~4C{= ~<A*C{= @'B9C{= C!C{= C4CC{+ GC{= GA	C{= H(/C{= I!C{= I:7C{= J2C{= J?C{= K8C{= LAC{= OC%E_ R:E_ SCE_ V!E_ V*AE_ W7E\/ XE\/ X(E\/ YE\/ YBE\/ [E_ [2E_ \E_ \BE_ ^(E_ ^;AE_ `)E_ `1E_ aE] aE_ a#E] bE_ bE_ b*BE_ d=A,E_ f*BE_ iBE_ kE_ kE_ k"AE_ mE_ mE_ m9E_ nE_ n,E_ n8E_ oE_ o+E_ o7E_ p3E_ p9AE_ r'E_ r*-E_ sE_ s*AE_ t3BE_ w-E_ xAE_ y!)E]%zE]%z+DE_ B%E_ A/CE_ EE_ E$E_ E:E]*FE_ FBE_ H)AE_ I8E_JA9E_ LA1E_ M4
E_ M?E_ NAE_ O+E_ PE_ PE_ P8'E_ Q 8E_ RE_ R,*E_ S!E_S7B.E_ V&+E_ WE_ W*AE_ X4E_ YE_ Y$A9E_ ["E_ [;B?E_ ^<AE_ ` A'E_ a)AE_ b-"E_ cAE_ d1	E_ d;A"E_ fE_ k?Eh  l	Eh  t 9Eh0 u:Ei v5Ei w	Ei wCw*w)Cw*w-Cw<w;Cw<w?Cx+x
Cx&x&Cx+x.Cyx9CyyCyyCz	y(CzzCz	zCzzCzzCz# z#C{z.C{{C{{C{"{C{= {!C{"{"	C{= {+C{:{6C{= {9C{:{:C{= {=E\,|$E\,|6A(E\,~"	E\,~,E\,~-,E\'A4E\'A?E\'B0E\'CE\'C'E\'D0E\'D=E\'EE\'E85E\'F.E\'GE\'G-E\'HJ&E\'R/7E\'S'CE\'V;E\,WE\'WE\'W)E\'W7(E\'X DE\'\*E\'\7E\']E\']E\']!E\']/E\']>=E\'^<E\'_(E\'_?E\'`E\'`E\'`#E\'`1E\'aB"E\'c#E\,c)BE\'e8BE\'g=E\,hE\'hE\'h(!E\'i
6E\'j:E\'j<<E\'k9E\'lE\'lE\'lE\'l+.E\'mE\'m1=E\'n/A4E\'p$AE\'q*C=E\'u'E\,u-AE\'wAE\'x!BE\'z1E\,z7#E\'{*E\'|A	E\'};E\'~E\'~E\'~+E\'~8E\'		E\'E\' E\'9 E\'@E\'@+-E\'AE\'A"J9E\'LE\,L!E\'L1E\'ME\'M,E\'NE\'NE\'N(A.E\'PE\'P$E\'P=!E\'QCE\'T&E\,T,	E\'T6AE\'VE\'V EV8V7E\'V8EWWE\'WEWW
E\'WE\'W7B4E\'Z,AE\'\E\,\E\'\'E\,\/E\>\:E_ \=E\>\>E_ ]E]]E_ ]E]]E_ ]E]"]E_ ]!E]"]"E_ ]*E^?^2E^:^3E_ ^:E^?^?	E_ _E__E_ _E__E_ _Eg=_+Eg8_?E``Eg8`)E`<`9Eg8`;E`<`<Eg8aB#Eg8c5Eg8dEed Eed8Eee?Eg8f	A!Eg8g8Eg=h Eh-hEh(h(Eh-h0Eh?h>Eh?iEiiEiiEjiEi<i<Ejc                <   < V ^8  d   QhRS[ RS[S[,          RS[ /# )rq   r  r  rr   )rP   r   rl  )rs   rn   s   "rE   rt   r.  $  s(     ( (C ((82D (PS (rH   c                8    V P                  WR7      pVR,          # )z
Simple chat interface that returns just the final response.

Args:
    message (str): User message
    stream_callback: Optional callback invoked with each text delta during streaming.

Returns:
    str: Final assistant response
)r  r  )ru  )rC   r  r  r]  s   &&& rE   rY  AIAgent.chat$  s#     &&w&P&''rH   )r  r	  r#  r$  r   r  r  r0  r8  r  r  r  r  r?  rA  r&  r  r  rV  r  r  r  r  r  rv  r  r  r1  r/  r0  r2  r  r  r  r	  r  r!  rP  r  r  r  rJ  rD  r  rK  rN  rS  rM  rJ  r  rC  r  r  rt  r  r   r 	  rB  r>  ra  r  r  re  r  rH  rb  rO  r
  rL  rf  r?  r>  r;  r=  r  r1  rY  r%  rd  rc  rF  rE  rJ  re  rL  rK  r;  rC  r^  rB  ri  rj  ra  r`  r<  rR  rQ  rP  rM  rN  rO  rI  rX  r_  rG  rj  rm  rn  rh  rr  rq  rp  rS  rk  r=  rl  rg  ro  r7  ri  rb  r]  rZ  r[  rW  rV  rD  r\  rT  rU  r  r4  rH  )r   r   r   rU   )FF>   r   rm  r  r   r  rY  rJ   r  >   r  r  r  r  r  )NNNNN)re   rf   rg   rh   ri   r   r1  setterrF   r  r  r  r  r  r  r  r  r  r  r  r  r/  rB  rY  r_  r  r  r  r  r  r  r  r  r  r  r  staticmethodr  r  r  r  r  r2  r6  r  rG  rM  rR  r`  rf  ro  rs  r  r  r	  r  r  r  r  r  r  r  r  r  r  r%  r1  rJ  rT  rX  r}  r  r  r  r  r.  r  rw  r  r  r  r  r  r  r  r  r*  r/  r4  r>  rK  rP  rf  r  r  rs  r  r  r  r  r  r	  r  r  r0  r;  rC  rK  rt  rg  rf  r  r  r  r  r  r  r  r  r  r]  r  r  ru  rY  rk   rl   rm   s   @rE   r,  r,    s       __> > %)!% &*'+"' % '+ #'+'+%)!,1(,+/(,+/&*'+%)"&*.&*$(+/15#(!!%.2)-$)(* % $iw wr,=\y
v$*5 * *( &U U(C C
4 4v v	% 	%% %. Ee EeP@ @DB
 B
HV V$	L 	L 
	G h hT* *$K K.F .F`- ->? ?0c cJD D && &&P) ) 4 > >@  P
 &*P Pd  @D @DD%V %VN ( (

 
$ " @ ) )l) l)d + + !!abC CJ  : G G" 8	0! !* 
  
  
     :w wrW Wr{ #	{ {z' '   b0 b0H/ /
 
   : * 8 8t 0 "  D DLW WG Gy yvKg KgZT  :!D ! !F% %N= =J J63&
 373& 3&jD D
;" ;"~    
 
F">BF" F"Tx1 x1x> >D #, - #
K K^    (1 1f*[ *[X "Y YT Tl T  TD, ,@t tl  62 2[ [z]-]a ]-r{ ]- ]-~* *.H HTVT VTpDT DTL
 0%Y %YNU UnE$ E$NH( ( (rH   r,  c                    V ^8  d   QhR\         R\         R\         R\         R\        R\         R\         R\        R	\        R
\        R\        R\        /# )rq   r  rB  r;  r1  	max_turnsrE  rF  
list_toolsrG  save_sampleverboserK  )rP   r   r   )rs   s   "rE   rt   rt   $  s     S/ S/S/S/ S/ 	S/
 S/ S/ S/ S/ S/ S/ S/ S/rH   c                   \        R4       \        RR4       V'       Ed_   ^ RIHpHpHp ^ RIHpHp \        R4       \        RS4       \        R4       \        RT4       V! 4       p. p. p. pVP                  4        Fa  w  ppV! V4      pV'       g   K  VV3pVRU9   d   VP                  V4       K6  VRV9   d   VP                  V4       KP  VP                  V4       Kc  	  \        R4       V FV  w  ppVR,          '       d   RP                  VR,          4      MR	p\        R
VR RVR,           24       \        RV 24       KX  	  \        R4       V Fk  w  ppVR,          '       d   RP                  VR,          4      MR	p\        R
VR RVR,           24       \        RV 24       \        RVR,           24       Km  	  \        R4       V F4  w  pp\        R
VR RVR,           24       \        RVR,           24       K6  	  \        R4       V! 4       pVP                  4        Fi  w  ppVR,          '       d   RMRp\        RV RV RVR,           24       VR,          '       d   KE  \        RRP                  VR,          4       24       Kk  	  V! 4       p\        R\        V4       R 24       \        V4       F  pV! V4      p\        R!V R"V R#24       K  	  \        R$4       \        R%4       \        R&4       \        R'4       \        R(4       \        R4       \        R)4       \        R*4       \        R4       \        R+4       \        R,4       \        R4       \        R-4       \        R.4       R/# R/pR/p V'       d=   VP                  R04       U!u. uF  p!V!P                  4       NK  	  pp!\        R1V 24       V'       d=   VP                  R04       U!u. uF  p!V!P                  4       NK  	  p p!\        R2V  24       V'       d"   \        R34       \        R44       \        R54        \        VVVVVV VV
VR67	      p"T f   R8p$MT p$\        R9T$ 24       \        RW4       T"P#                  T$4      p%\        RW4       \        R:4       \        RR4       \        R;T%R<,           24       \        R=T%R>,           24       \        R?\        T%R@,          4       24       T%RA,          '       d)   \        RB4       \        RX4       \        T%RA,          4       T	'       d   \%        \&        P(                  ! 4       4      RC,          p&RDT& RE2p'T"P+                  T%R@,          T$T%R<,          4      p(RFT(RG\,        P.                  ! 4       P1                  4       RHTR<T%R<,          RIT$/p \3        T'RJRKRL7      ;_uu_ 4       p)T)P5                  \6        P8                  ! TRM^RN7      4       R/R/R/4       \        ROT' 24       \        RQ4       R/# u up!i u up!i   \          d   p#\        R7T# 24        R/p#?#R/# R/p#?#ii ; i  + '       g   i     L\; i  \:         d   p#\        RPT# 24        R/p#?#LoR/p#?#ii ; i)Ya  
Main function for running the agent directly.

Args:
    query (str): Natural language query for the agent. Defaults to Python 3.13 example.
    model (str): Model name to use (OpenRouter format: provider/model). Defaults to anthropic/claude-sonnet-4.6.
    api_key (str): API key for authentication. Uses OPENROUTER_API_KEY env var if not provided.
    base_url (str): Base URL for the model API. Defaults to https://openrouter.ai/api/v1
    max_turns (int): Maximum number of API call iterations. Defaults to 10.
    enabled_toolsets (str): Comma-separated list of toolsets to enable. Supports predefined
                          toolsets (e.g., "research", "development", "safe").
                          Multiple toolsets can be combined: "web,vision"
    disabled_toolsets (str): Comma-separated list of toolsets to disable (e.g., "terminal")
    list_tools (bool): Just list available tools and exit
    save_trajectories (bool): Save conversation trajectories to JSONL files (appends to trajectory_samples.jsonl). Defaults to False.
    save_sample (bool): Save a single trajectory sample to a UUID-named JSONL file for inspection. Defaults to False.
    verbose (bool): Enable verbose logging for debugging. Defaults to False.
    log_prefix_chars (int): Number of characters to show in log previews for tool calls/responses. Defaults to 20.

Toolset Examples:
    - "research": Web search, extract, crawl + vision tools
u   🤖 AI Agent with Tool Calling)get_all_tool_namesr   get_available_toolsets)get_all_toolsetsget_toolset_infou    📋 Available Tools & Toolsets:u'   
🎯 Predefined Toolsets (New System):u   
📌 Basic Toolsets:resolved_toolsr  r  u     • r%  z - r  z    Tools: u5   
📂 Composite Toolsets (built from other toolsets):includesz    Includes: z    Total tools: r  u!   
🎭 Scenario-Specific Toolsets:20u3   
📦 Legacy Toolsets (for backward compatibility):r  u   ✅u   ❌r@  rn  r^  z    Requirements: r  u   
🔧 Individual Tools (z available):u     📌 z (from r  u   
💡 Usage Examples:z  # Use predefined toolsetszR  python run_agent.py --enabled_toolsets=research --query='search for Python news'zN  python run_agent.py --enabled_toolsets=development --query='debug this code'zP  python run_agent.py --enabled_toolsets=safe --query='analyze without terminal'z  # Combine multiple toolsetszM  python run_agent.py --enabled_toolsets=web,vision --query='analyze website'z  # Disable toolsetszQ  python run_agent.py --disabled_toolsets=terminal --query='no command execution'z&  # Run with trajectory saving enabledzF  python run_agent.py --save_trajectories --query='your question here'Nr  u   🎯 Enabled toolsets: u   🚫 Disabled toolsets: u   💾 Trajectory saving: ENABLEDu:      - Successful conversations → trajectory_samples.jsonlu7      - Failed conversations → failed_trajectories.jsonl)	r1  rB  r;  rC  rE  rF  rG  rH  rK  u    ❌ Failed to initialize agent: zTell me about the latest developments in Python 3.13 and what new features developers should know about. Please search for current information and try it out.u   
📝 User Query: u   📋 CONVERSATION SUMMARYu   ✅ Completed: r  u   📞 API Calls: r  u   💬 Messages: r   r  u   
🎯 FINAL RESPONSE:r  sample_r  conversationsr#  rB  r  r  r  r  F)r   r   u"   
💾 Sample trajectory saved to: u   
⚠️ Failed to save sample: u    
👋 Agent execution completed!z2==================================================z2--------------------------------------------------z(----------------------------------------)webr  visioncreativer4  )researchdevelopmentri  content_creation
full_stackz3
==================================================z------------------------------)r'  model_toolsr	  r   r	  r  r	  r	  r6  r   r  rQ   r5  r  r   r,  r+  ru  rP   r8  r9  r  r   r  r&  r  rL   r   r   r   )*r  rB  r;  r1  r	  rE  rF  r	  rG  r	  r	  rK  r	  r   r	  r	  r	  all_toolsetsbasic_toolsetscomposite_toolsetsscenario_toolsetsra   r  r  rA  	tools_strincludes_strlegacy_toolsetsr^  	all_toolsr   enabled_toolsets_listdisabled_toolsets_listr  r  r  r  r]  	sample_idsample_filenamer  r'  s*   &&&&&&&&&&&&                              rE   mainr	  $  s   H 

+,	(O z``?01h 	89h') )//1MD'#D)DttQQ"))%0ff&--e4%,,U3 2 	&'(JD$=ABR=S=S		$'7"89Y_IF4)3tM':&;<=K	{+, ) 	FG,JD$:>z:J:J499T*%56PVLF4)3tM':&;<=N<.12%d<&8%9:;	 - 	23+JD$F4)3tM':&;<=%d<&8%9:; , 	DE02)//1JD$";//UUFBvhavR](;'<=>$$*499T.5I+J*KLM	 2 '(	)#i.)9FG	*I*95GGI;ggYa89 + 	&'+,bc^_`ad-.]^d$%abd67VW !!4D4J4J34O P4Oq4O P'(='>?@5F5L5LS5Q!R5Q!'')5Q!R()?(@AB/0JKGH$24/#-

  }b 	
 
	
|
,-	/ ##J/F	/	
%&	(O	OF;/0
12	VK01
23	OCz 234
56&'hf%&' 

%b)	#I;e4 88:;

 Z113U,Z
	:osW==

5uQGH > 77HIJ 

-.i !Q "S*  045h >=  	:4QC899	:sT   X!X4X $Y
 :)X7#Y
 X4X//X47Y	Y
 
Y-Y((Y-__main__>   	read_filer  
web_searchr  web_extractha_get_statesearch_filesrx  vision_analyzeha_list_entitiesha_list_services>   rM  r	  rL  )Nr   Nr   
   NNFFFFr  )ri   atexitr&  r  concurrent.futuresrV  r  r  r   r   r  re   r  r   rR  r  rx   r  r  r   weakreftypesr   r8  typingr   r   r   r   r  r   firer   pathlibr	   r\  r   hermes_cli.env_loaderr   r  __file__parent_project_env_loaded_env_paths	_env_pathr  r	  r   r   r   r   tools.terminal_toolr   tools.interruptr   rF  tools.browser_toolr   r   rW  r   agent.prompt_builderr   r   r   r   r   r   r  r   r   r    r!   r"   r#   r$   r%   agent.context_compressorr&   agent.subdirectory_hintsr'   agent.prompt_cachingr(   r)   r*   r+   r,   r-   r.   r/   r0   agent.usage_pricingr1   r2   r  r3   r4   rQ  r5   r[  r6   r7   rw  agent.trajectoryr8   r9   r:   r  utilsr;   r<   r>   r|   r~   r	  r   r   r   rU  compileVERBOSEr   r   r   r   r   r   r   r  r  r   r   r  r  r  r*  r,  r	  Firerd   rH   rE   <module>r 
     sJ  *        			8	$ 	  	 
     !  , ,     , 5 H~$$v-&<\Z &	:IF ' KKIJ  + ; . 1 < 
   7 < > }  }  } D   5.* .*b;)7 )7\ "9+.  ! "   CD    

	 JJ  jj!45 )X="? 

-.ZZ<II 0%J   $ -
`wH( wH(tQS/l zIIdO rH   