
    Fj)                   X   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZ ddlmZmZmZ ddlmZmZ ddlmZmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ ddlm Z m!Z!  ej"        e#          Z$d Z%d.dZ&d/dZ'd0dZ(d1dZ)d2dZ*d3d!Z+d4d5d$Z,d6d'Z-d7d*Z.dd+d1d,Z/g d-Z0dS )8uu  Helper functions for the chat-completions code path.

Extracted from :class:`AIAgent` for cleanliness — bodies of the
non-streaming API call, request kwargs builder, assistant-message
materializer, provider-fallback activator, max-iterations handler,
and per-turn resource cleanup.

Each function takes the parent ``AIAgent`` as its first argument
(``agent``).  :class:`AIAgent` keeps thin forwarder methods so call
sites unchanged.  Symbols that tests patch on ``run_agent`` (e.g.
``cleanup_vm`` / ``cleanup_browser`` in
``test_zombie_process_cleanup.py``) are resolved through
:func:`_ra` so the patch contract is preserved.
    )annotationsN)SimpleNamespace)AnyDictOptional)get_provider_request_timeoutget_provider_stale_timeout)PARTIAL_STREAM_STUB_IDFINISH_REASON_LENGTH)FailoverReason)is_local_endpoint)_sanitize_surrogates_repair_tool_call_arguments)is_persistent_env)base_url_host_matchesbase_url_hostnamec                     ddl } | S )zLazy ``run_agent`` reference.

    Used to honor test patches like
    ``patch("run_agent.cleanup_vm")`` / ``patch("run_agent.cleanup_browser")``
    that target symbols imported into ``run_agent``'s namespace.
    r   N	run_agentr   s    </usr/local/lib/hermes-agent/agent/chat_completion_helpers.py_rar   *   s         api_payloadr   returnintc                   dddfd}t          | t                    r ||           dz  S t          | t                    r|                     d          }t          |t                    r5 ||          }d	| v r!| |                     d	                    z  }|dz  S d
| v ra |                     d
                     |                     d                    z    |                     d	                    z   }|dz  S t	          fd|                                 D                       dz  S  |           dz  S )a   Estimate context/load tokens from an API payload, dict or messages list.

    The stale-call detectors historically assumed a Chat Completions request:
    they pulled ``api_kwargs["messages"]`` and ran a cheap char/4 estimate.
    Codex / Responses API requests carry the conversational payload in
    ``input`` (with additional load in ``instructions`` and ``tools``), so the
    legacy estimator reported ~0 tokens for every Codex turn and the
    context-tier scaling never fired.

    This helper handles both shapes:
      - bare list -> treat as Chat Completions ``messages``
      - dict with ``messages`` -> Chat Completions (+ ``tools`` if present)
      - dict with ``input`` -> Responses API (+ ``instructions``/``tools``)
      - any other dict -> fall back to summing string values
    valuer   r   r   c                    | dS t          | t                    rt          |           S t          t          |                     S )Nr   )
isinstancestrlen)r   s    r   _charsz/estimate_request_context_tokens.<locals>._charsF   s<    =1eS!! 	u::3u::r   messagesc                z    t          | t                    s |           S t          fd| D                       S )Nc              3  .   K   | ]} |          V  d S N ).0itemr"   s     r   	<genexpr>zJestimate_request_context_tokens.<locals>._message_chars.<locals>.<genexpr>P   s+      55D66$<<555555r   )r   listsum)r#   r"   s    r   _message_charsz7estimate_request_context_tokens.<locals>._message_charsM   sH    (D)) 	$6(###5555H555555r      toolsinputinstructionsc              3  .   K   | ]} |          V  d S r&   r'   )r(   r   r"   s     r   r*   z2estimate_request_context_tokens.<locals>.<genexpr>e   s+      CCU66%==CCCCCCr   )r   r   r   r   )r#   r   r   r   )r   r+   dictgetr,   values)r   r-   r#   total_charsr"   s       @r   estimate_request_context_tokensr7   5   s   "   6 6 6 6 6 6
 +t$$ 0~k**a//+t$$ I??:..h%% 	$(.22K+%%vvkoog&>&>???!##k!!{w//00&8899:&11223 
 !##CCCCk.@.@.B.BCCCCCqHH6+!##r   boolc                    t          t          | dd          pd          }t          t          | dd          pd          }t          | dd           dk    p	|dk    od|v S )N_base_url_lower _base_url_hostnameprovideropenai-codexchatgpt.com/backend-api/codex)r    getattr)agentbase_url_lowerr   s      r   _is_openai_codex_backendrD   j   st    (92>>D"EENGE+?DDJKKz4((N: 	
. 7$6	r   namer    defaultfloatc                    	 t          t          j        | t          |                              S # t          t
          f$ r |cY S w xY wr&   )rG   osgetenvr    	TypeError
ValueError)rE   rF   s     r   
_env_floatrM   v   sP    RYtS\\22333z"   s   .1 AA
api_kwargsr3   c           	         ddddddt          j                    fdfd}dW fd
 fd}                               } j        dk    }t	                     }t                    }|rF|rD|dk    rt          |d          }n-|dk    rt          |d          }n|dk    rt          |d          }|dk    rd}n|dk    rd}n|dk    rd}nd}|}	t          dd          }
|
dk    rd}	n|rt          dd          }t          j	        
                    dd                                                                          dv }|s-|dk    r'||k    r!d}	t                              d |d!|           n=t          d"d#          }|dk    r'|
|k    r!t                              d$|
||d!           |}
|}t          d%|          }|dk    rd}|rd _        d _        t#          j                    }                     d&           t          j        |d'(          }|                                 d}|                                rq|                    d)*           |d+z  }|d,z  dk    r<t#          j                    |z
  }                     d-t/          |           d.           t#          j                    |z
  }|	r||
k    rt1           d/d          d}t1           d0d          }t3          |          r3	  |
                    d1          2          }n# t4          $ r d}Y nw xY wt                              d3||

                    d1d4                     |r@                     d5t/          |           d6
                    d1d4           d7|            n=                     d5t/          |           d6
                    d1d4           d8           	  d9           n# t4          $ r Y nw xY w                     d:t/          |           d;           |                    d<*           d=         sd>         k|r6t;          d?t/          |           d@t/          |
           dA|           d=<   n3t;          d?t/          |           d@t/          |
           dB          d=<   nt1           d/d          }|rC|@t#          j                    |z
  |k    r%t#          j                    |z
  }t                              dC||
                    d1d4          |d!                                dDt/          |           dE
                    d1d4           d8           	  dF           n# t4          $ r Y nw xY w                     d:t/          |           dG           |                    d<*           d=         ;d>         3t;          dHt/          |           dIt/          |           dB          d=<   n||k    r%t                    }d}t1           d0d          }t3          |          r3	  |
                    d1          2          }n# t4          $ r d}Y nw xY wt                              dJ||
                    d1d4          |d!           |r@                     dKt/          |           dL
                    d1d4           dM|            n=                     dKt/          |           dL
                    d1d4           dN           	  j        dOk    r. j                                                                            n dP           n# t4          $ r Y nw xY w                     dQt/          |           dR           |                    d<*           d=         sd>         k|r6t;          dSt/          |           dTt/          |           dA|           d=<   n3t;          dSt/          |           dTt/          |           dB          d=<   n j!        re	  j        dOk    r. j                                                                            n dU           n# t4          $ r Y nw xY wtE          dV          |                                qd=         d=         d>         S )Xa=  
    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.

    Includes a stale-call detector: if no response arrives within the
    configured timeout, the connection is killed and an error raised so
    the main retry loop can try again with backoff / credential rotation /
    provider fallback.
    Nresponseerror)client	owner_tidc                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S NrS   rT   	threading	get_identrS   request_client_holderrequest_client_locks    r   _set_request_clientz3interruptible_api_call.<locals>._set_request_client   s      	G 	G.4!(+ 2;1D1F1F!+.	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G    ,00c                 ~    5                       d          } d d<   d d<   | cd d d            S # 1 swxY w Y   d S rV   r4   rZ   s    r   _take_request_clientz4interruptible_api_call.<locals>._take_request_client         	 	*..x88F.2!(+15!+.		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	   !266reasonr    r   Nonec                R   5                       d          }                     d          }|d uo|d uo|t          j                    k    }|s
d d<   d d<   d d d            n# 1 swxY w Y   |d S |r                    ||            d S                     ||            d S NrS   rT   rd   r4   rX   rY   _abort_request_openai_client_close_request_openai_clientrd   request_clientrT   stranger_threadrB   r[   r\   s       r   _close_request_client_oncez:interruptible_api_call.<locals>._close_request_client_once   s*    ! 	: 	:266x@@N-11+>>Id* 7T)7!4!6!66 
 # :26%h/59%k2	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: !F 	N..~f.MMMMM..~f.MMMMM   AA&&A*-A*c            	        	 j         dk    rK                     d                    }                     | t          dd                     d<   nj         dk    r                              d<   nωj         dk    rd	d
lm}m}m}m	} 
                    dd          }
                    dd             ||          }	  |j        di }n)# t          $ r} ||          r ||            d }~ww xY w ||          d<   n:                     d                    }  | j        j        j        di d<   n# t          $ r}	|	d<   Y d }	~	nd }	~	ww xY w 
d           d S #  
d           w xY w)Ncodex_responsescodex_stream_requestrd   rN   _codex_on_first_delta)rS   on_first_deltarQ   anthropic_messagesbedrock_converser   )_get_bedrock_runtime_clientinvalidate_runtime_clientis_stale_connection_errornormalize_converse_response__bedrock_region__	us-east-1__bedrock_converse__chat_completion_requestrR   request_completer'   )api_mode_create_request_openai_client_run_codex_streamrA   _anthropic_messages_createagent.bedrock_adapterry   rz   r{   r|   popconverse	Exceptionchatcompletionscreate)rm   ry   rz   r{   r|   regionrS   raw_response_bedrock_excero   r]   rB   rN   results             r   _callz%interruptible_api_call.<locals>._call   sm   1	;~!222!4!4775#- 8  " " &+%<%<)#*52I4#P#P &= & &z""
 #777%*%E%Ej%Q%Qz""#555
            $(<kJJ5t<<<44V<<#26?#@#@Z#@#@LL     10>> :11&999 &A%@%N%Nz""!4!4778#- 8  " " &L^%8%D%K%Y%Yj%Y%Yz" 	  	  	 F7OOOOOO	  '&'9:::::&&'9::::sU   CE C E 
D $C;;D  AE E6 
E&E!E6 !E&&E6 6Frr   順 g     @P  g      @ia  g     @     f@      ^@i'        N@g      (@!HERMES_CODEX_TTFB_TIMEOUT_SECONDSr   F&HERMES_CODEX_TTFB_DISABLE_ABOVE_TOKENSg     j@HERMES_CODEX_TTFB_STRICTr;   >   1onyestruezDisabling openai-codex no-byte TTFB watchdog for large request (context=~%s tokens >= %.0f). Waiting for backend response instead. Set HERMES_CODEX_TTFB_STRICT=1 to force early reconnects.,HERMES_CODEX_TTFB_MAX_SECONDSg      4@z~Capping openai-codex no-byte TTFB timeout from %.0fs to %.0fs (context=~%s tokens). Set HERMES_CODEX_TTFB_MAX_SECONDS to tune.(HERMES_CODEX_EVENT_STALE_TIMEOUT_SECONDSz&waiting for non-streaming API responseTtargetdaemon333333?timeout   d   z$waiting for non-streaming response (z
s elapsed)_codex_stream_last_event_ts_codex_silent_hang_hintmodel)r   zCodex stream produced no bytes within TTFB cutoff (%.0fs > %.0fs, model=%s). Backend accepted the connection but sent no stream events. Killing connection so the retry loop can reconnect.unknownu&   ⚠️ No first byte from provider in zs (codex stream, model: z). Reconnecting. z). Reconnecting.codex_ttfb_killzcodex stream killed after zs with no first byteg       @rR   rQ   z&Codex stream produced no bytes within zs (TTFB threshold: zs). zs)zCodex stream produced no SSE events for %.0fs after first byte (threshold %.0fs, model=%s, context=~%s tokens). Killing connection so the retry loop can reconnect.u'   ⚠️ Codex stream sent no events for zs after first byte (model: codex_stream_idle_killzs with no SSE eventsz(Codex stream produced no SSE events for zs after first byte (threshold: zjNon-streaming API call stale for %.0fs (threshold %.0fs). model=%s context=~%s tokens. Killing connection.%   ⚠️ No response from provider for zs (non-streaming, model: z). z). Aborting call.rw   stale_call_killz&stale non-streaming call killed after sz'Non-streaming API call timed out after zs with no response (threshold: interrupt_abortz!Agent interrupted during API callrd   r    r   re   )#rX   Lock!_compute_non_stream_stale_timeoutr   rD   r7   maxrM   rI   environr4   striplowerloggerinfor   _codex_stream_last_progress_tstime_touch_activityThreadstartis_alivejoinr   rA   callabler   warning_buffer_statusTimeoutError_anthropic_clientclose_rebuild_anthropic_client_interrupt_requestedInterruptedError)rB   rN   ra   r   _stale_timeout_codex_watchdog_enabled_openai_codex_backend_est_tokens_for_codex_watchdog_codex_idle_timeout_default_ttfb_enabled_ttfb_timeout_ttfb_disable_above_ttfb_strict	_ttfb_cap_codex_idle_enabled_codex_idle_timeout_call_startt_poll_count_elapsed_silent_hint_hint_fn_last_codex_event_ts_event_stale_elapsed_est_ctxro   r]   r[   r\   r   s   ``                       @@@@@r   interruptible_api_callr   }   s%    ..F'+$??#.**          N N N N N N N N@2; 2; 2; 2; 2; 2; 2; 2; 2;t <<ZHHN$ $n0AA4U;;%DZ%P%P" 8#8 8)G33 88NN+f44 77NN+f44 77N%//&+##	'&	0	0&+##	'&	0	0&*##&*#+MBDIIM	 *()QS[\\z~~&@"EEKKMMSSUU Z
 
 	*#a''.2EEE!MKKL 255#    ##BDIII1}}!:!:W!599   !*1$2#  a# 4 -1)/3,)++K	BCCCd333AGGIIIK
**,, sH	sq !!y{{[0H!!Ps8}}PPP   9;;, 3	=((<dCCK*.Lu&?FFH!! ((#+8*..2I2I#J#J#JLL  ( ( (#'LLL(NN& -)K)K    $$4S]] 4 4-7^^GY-O-O4 4%14 4    $$%S]] % %-7^^GY-O-O% % %  
**+<====   !!PS]]PPP   FF3Fg&6*+=+E 	&2SX S S,/,>,>S SDPS S' 'F7OO
 '3CX C C,/,>,>C C C' 'F7O 
  'u.KTRR!	$0337JJJ#'9;;1E#E NN> %#w	22155     !#>R:S:S ! !,6NN7I,N,N! ! !  
**+CDDDD   !!\S1E-F-F\\\   FF3Fg&6*+=+E".QsCW?X?X Q Q478K4L4LQ Q Q# #w  n$$6zBBH*.Lu&?FFH!! ((#+8*..2I2I#J#J#JLL  ( ( (#'LLL(NNC.w	22xOO	    $$&CMM & &.8nnWi.P.P& &#& &    $$&CMM & &.8nnWi.P.P& & &  
>%999+11333335555../@AAA   !!IXIII   FF3Fg&6*+=+E 
&2*#h-- * *8;N8K8K* *'* *' 'F7OO '3P#h-- P P8;N8K8KP P P' 'F7O % 	H>%999+11333335555../@AAA   "#FGGGg **,, sHh g"Wo*sn   L, ,L;:L;/O; ;
PP>V
 

VVY4 4ZZ:A]? ?
^^Ab 
b! b!api_messagesr+   c                   | j         }| j        dk    r|                                 }|                     |          }t	          | dd          }|r|j        nd}t	          | dd          }|d| _        |                    | j        ||||n| j	        | j
        | j        |                                 |t	          | dd          | j        pi                     d          dk    t          t	          | dd	                    
          S | j        dk    r_|                                 }t	          | dd          pd}t	          | dd          }	|                    | j        ||| j	        pd||	          S | j        dk    r|                                 }
t!          | j        d          pt!          | j        d          }| j        dk    p| j        dk    od| j        v }| j        dv p
| j        dk    }|                     |          }|r	 ddl}ddlm}m} |                    |          } ||          \  }} ||          \  }}nB# t6          $ r5}t8                              dt	          | dd          |           Y d}~nd}~ww xY w|
                    | j        ||| j
        t	          | dd          | j	        |                                 | j        ||||r|                                 ndt          t	          | dd                     !          S |                                 }
|                                  }| !                                }t!          | j        d          pt!          | j        d          }d"| j        v }d#| j        v }t!          | j        d$          p)t!          | j        d%          pt!          | j        d&          }t!          | j        d'          }| j        pd"                                #                                d(k    }	 dd)l$m%}m&}  || j        | j                  }||u }|s|nd} n# t6          $ r d	}d} Y nw xY wi }!| j'        r
| j'        |!d*<   | j(        r
| j(        |!d+<   | j)        r
| j)        |!d,<   | j*        r
| j*        |!d-<   | j+        rd |!d.<   | j,        r
| j,        |!d/<   d}"|s|rEd0| j        pd#                                v r(	 dd1l-m.}#  |#| j                  }"n# t6          $ r Y nw xY wd}$|r*| j/        pd2ta          tc          j2                              d3}$	 dd4l3m4}%  |%| j                  }&n# t6          $ r d}&Y nw xY w|&rt	          | dd          }'|'d| _        |                     |          }|
                    | j        ||| j        |                                 | j	        |'| j5        | j
        | j        t	          | dd          |&| j6        |!pd| j7        |"| 8                                |$5          S t	          | dd          }'|'d| _        |                     |          }( |
j        dXi d6| j        d7|(d8|d9| j        d:|                                 d;| j	        d<|'d=| j5        d>| j
        d?| j        dt	          | dd          d@| j        pd#                                dA|dB|dC|dD|dE|dF|dG|dH|dI| j        dJk    dK| j6        dL|!pddM| j7        dN|r| j9        nddO|r| j:        nddP|$dQ| dR|dS| 8                                dT|r|                                 nddU|r| ;                                nddV|"dW| j        S )Yz9Build the keyword arguments dict for the active API mode.rw   context_compressorN_ephemeral_max_output_tokens_anthropic_base_urlspeedfast_oauth_1m_beta_disabledF)r   r#   r/   
max_tokensreasoning_configis_oauthpreserve_dotscontext_lengthbase_url	fast_modedrop_context_1m_betarx   _bedrock_regionr~   _bedrock_guardrail_configi   )r   r#   r/   r   r   guardrail_configrr   zmodels.github.aizapi.githubcopilot.comr>   r?   r@   >   	xai-oauthxaizapi.x.air   )strip_pattern_and_formatstrip_slash_enumu4   %s⚠️ Failed to sanitize tool schemas for xAI: %s
log_prefixr;   
session_id_codex_reasoning_replay_enabledT)r   r#   r/   r   r   r   r   request_overridesis_github_responsesis_codex_backendis_xai_responsesgithub_reasoning_extrareplay_encrypted_reasoningnousresearchzintegrate.api.nvidia.comzapi.kimi.comzmoonshot.aizmoonshot.cnztokenhub.tencentmaas.comlmstudio_fixed_temperature_for_modelOMIT_TEMPERATUREonlyignoreordersortrequire_parametersdata_collectionclaude)_get_anthropic_max_outputhermes)	sessionIdpromptId)get_provider_profile)r   r#   r/   r   r   r   ephemeral_max_output_tokensmax_tokens_param_fnr   r   r   provider_profileollama_num_ctxprovider_preferencesopenrouter_min_coding_scoreanthropic_max_outputsupports_reasoningqwen_session_metadatar   r#   r/   r   r   r   r  r  r   r   model_loweris_openrouteris_nousis_qwen_portalis_github_modelsis_nvidia_nimis_kimiis_tokenhubis_lmstudiois_custom_providercustomr  r  r  qwen_prepare_fnqwen_prepare_inplace_fnr  fixed_temperatureomit_temperaturer  r  lmstudio_reasoning_optionsr  provider_namer'   )<r/   r   _get_transport#_prepare_anthropic_messages_for_apirA   r   r   build_kwargsr   r   r   _is_anthropic_oauth_anthropic_preserve_dotsr   r4   r8   r   r   r=   r<   r:   &_prepare_messages_for_non_vision_modelcopytools.schema_sanitizerr   r   deepcopyr   r   r   _resolved_api_call_timeout#_github_models_reasoning_extra_body_is_qwen_portal_is_openrouter_urlr   r   agent.auxiliary_clientr  r  providers_allowedproviders_ignoredproviders_orderprovider_sortprovider_require_parametersprovider_data_collectionagent.anthropic_adapterr  r   r    uuiduuid4	providersr  _max_tokens_param_ollama_num_ctxr  _supports_reasoning_extra_body_qwen_prepare_chat_messages#_qwen_prepare_chat_messages_inplace"_lmstudio_reasoning_options_cached))rB   r   tools_for_api
_transportrw   ctx_lenephemeral_out_btr   	guardrail_ctr   r   r   _msgs_for_codex_copyr   r   _exc_is_qwen_is_or_is_gh_is_nous
_is_nvidia_is_kimi_is_tokenhub_is_lmstudior  r  _ft
_omit_temp_fixed_temp_prefs_ant_maxr  
_qwen_metar  _profile_ephemeral_out_msgs_for_chats)                                            r   build_api_kwargsrh    sD
   KM~---))++
"FF|TT%!5t<<,3='(('EtLL$15E.&&+'(5(A}}uGW"3.88::"U$94@@.4"99'BBfL!%ge5NPU&V&V!W!W ' 
 
 	
  ~+++""$$ 1488GKE#>EE	+!'/4&   
 
 	
 ~***""$$!%.2DEE N$U^5LMM 	
 Nn, (M9 B(E,AA	 	 !>-AAkUE]akEkFF|TT$  	$$$$        !&} = =#;#;M#J#J q#3#3M#B#B qq   JE<44c        +$"3ulD99'4466#5 3--Re#o5#L#L#N#N#Nko'+@$GG( (   
 
 	
& 


 
 C $$&&H%%''Fe35GHH 	Q !68OPP  !66H+u/DDJenn== 	@ ??	@ ?? 
 ))>@Z[[LN(b//117799ZGLYYYYYYYY**5;GG,,
!+5cc   

  F 10v 3 2x 0/w -,v( ,'+#$% C$)$B ! H ( U[->B,E,E,G,G G G	IIIIII00==HH 	 	 	D	 J 
)5XDJLL))
 

222222''77     
 (FMM%15E.
 CCLQQ+!^4466'(6 % 7"3#5ulD99% 0!'4(-(I!)$CCEE",'   
 
 	
2 U$BDIIN!-1* AA,OON3 # # #kk## m# 	#
 00222# ### %3N# "33# //#  11# 5,555# [&B--///# f# #  x#   !#" !j##$ %#& !L'#( !L)#* !>X55+#, ,,-#. $^t/#0 %*$E$E1#2 >FO9943#4 NV _ I I[_5#6 )j7#8 &+9#: $;#< !??AAA=#> OU^uHHJJJZ^?#@ R^#g5#K#K#M#M#McgA#B &XC#D nnE# #sN   =I 
J+I<<J(P4 4QQS& &
S32S3%T< <U
Ufinish_reasonc                .   t          |dd          }|                     |          }t          |          }|sO|j        pd}t	          j        d|t          j                  }|r#d                    d |D                       }|pd}|r.| j        r't          j
        dt          |           d	|            |r<| j        r5| j        s.| j        s'	 |                     |           n# t          $ r Y nw xY w|j        pd}	t!          |	          }
|rt!          |          }t#          |
t$                    r)|
r'|                     |
                                          }
t#          |
t$                    r|
rd
dlm}  ||
          }
d|
||d}t          |dd          }|Dt/          |d          r4t          |dd          pi }t#          |t0                    rd|v r|d         }|t!          |          |d<   n|r|                                 r|pd|d<   d|vr|r||d<   t/          |d          r|j        r|j        }g }|D ]}t#          |t0                    r|                    |           -t/          |d          r|                    |j                   Xt/          |d          r'|                    |                                           |r||d<   t          |dd          }|r||d<   t          |dd          }|r||d<   |rg }|D ]}t          |dd          }t          |dd          }t#          |t$                    r|                                s|                     |          \  }}|}t#          |t$                    r|                                st#          |t$                    r)|                                r|                                }n_t          |dd          }|rt          |dd          nd}|rt          |dd          nd}|                     ||t          |                    }|                                }t          |dd          }t#          |t$                    r|                                s|                     |          \  }}|}|                      |t#          |t$                    r|nd          }||||j!        |j"        j#        |j"        j$        dd}t#          |d         d         t$                    r&d
dlm}  ||d         d                   |d         d<   t          |dd          } | )t/          | d          r|                                 } | |d<   |                    |           ||d<   |S ) 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.
    
tool_callsNr;   z<think>(.*?)</think>flags

c              3  f   K   | ],}|                                 |                                 V  -d S r&   )r   )r(   bs     r   r*   z*build_assistant_message.<locals>.<genexpr>$  s7      "P"Paggii"P17799"P"P"P"P"P"Pr   zCaptured reasoning (z	 chars): r   )redact_sensitive_text	assistant)rolecontent	reasoningri  reasoning_contentmodel_extra reasoning_details__dict__
model_dumpcodex_reasoning_itemscodex_message_itemsidcall_idfunctionrE   	arguments{}response_item_idrE   r  )r~  r  r  typer  extra_content)%rA   _extract_reasoningr8   rt  refindallDOTALLr   verbose_loggingloggingdebugr!   reasoning_callbackstream_delta_callback_stream_callbackr   r   r   r    _strip_think_blocksr   agent.redactrq  hasattrr3   _needs_thinking_reasoning_padry  appendrz  r{  _split_responses_tool_id_deterministic_call_id"_derive_responses_function_call_idr  r  rE   r  )!rB   assistant_messageri  assistant_tool_callsreasoning_text_from_structuredrt  think_blockscombined_raw_content_san_contentrq  msgraw_reasoning_contentrw  raw_details	preserveddcodex_itemsr}  rk  	tool_callraw_idr  embedded_call_idrU  _fn_fn_name_fn_argsr  embedded_response_item_idtc_dictextras!                                    r   build_assistant_messager    s    ##4lDII--.?@@NN++
  .#+1rz"97")TTT 	.{{"P"Pl"P"P"PPPH%-N ]%/ ][S-@-@[[>[[\\\ %2  * 	53I 	((8888   
 %,2L'55L >-n== ,$$ G G00>>DDFF ,$$ ; ;666666,,\:: #&	 C $$57JDQQ$1BM)R)R$/EEKk4(( 	E-@K-O-O$/0C$D!(#78M#N#N  	 9%"E"E"G"G 9 $2#8S 0 #%%.%#1  "566 1;L;^ 1
 (9	 	1 	1A!T"" 1  ####J'' 1  ,,,,L)) 1  000 	1'0C#$ +-DdKKK 3'2#$
 ""35JDQQ 9%8!" ;'
- 8	' 8	'IYd33FiD99Ggs++ +7==?? +&+&D&DV&L&L# !*gs++ `7==?? `fc** `v||~~ `$llnnGG!)Z>>C;>FwsFB777BHBEOwsK>>>4H#::8XsS]__GmmooG&y2DdKK.44 =<L<R<R<T<T =/4/M/Mf/U/U,,#< $GG$./?$E$EO  4    "$4!%.3!*!3!= 	 	G" '*-k:C@@ >>>>>>3H3HJ'44 4
#K0 I==E 5,// /!,,..E+0(g&&&&&LJs   C% %
C21C2rd   'FailoverReason | None'c                   |t           j        t           j        hv rt          t	          | dd                    }t	          | dd          pd                                                                }| j        pi                     d          pd                                                                }|r|r!||k    rt          j
                    dz   | _        | j        t          | j                  k    rdS | j        | j                 }| xj        dz  c_        |                    d          pd                                                                }|                    d          pd                                }|r|s|                                 S t	          | dd          pd                                                                }t	          | dd          pd                                }t!          t	          | dd          pd                              d	                                          }	|                    d          pd                                                    d	                                          }
||k    r6||k    r0t$                              d
||           |                                 S |
r=|	r;|
|	k    r5||k    r/t$                              d|
           |                                 S 	 ddlm} |                    d          pd                                pd}|                    d          pd                                pd}|si|                    d          p|                    d          pd                                }|r)t-          j        |d                                          pd}|r(t1          |d          r|st-          j        d          pd} |||d||          \  }}|/t$                              d|           |                                 S 	 ddlm}  |||          }n4# t6          $ r'}t$                              d|||           Y d}~nd}~ww xY wd}t!          |j                  }|                     |          }|dk    rd}n|dk    s:|                    d	                                                              d          rd}nq|rd}nl|                     |          rd}nT|                      ||          rd}n:|d k    s2tC          |          "                    d!          rt1          |d"          rd#}| j#        }d| _$        || _#        || _%        || _        || _&        tO          | d$          r| j(        )                                 d| _*        t	          | d%d          }|ct	          |dd          pd                                                                }|r*||k    r$t$          +                    d&|||           d| _,        t[          ||          }|dk    rdd'l.m/}m0}m1} |dk    r|j2        p |            pdn|j2        pd}|| _2        || _3        || _4         ||| j4        |(          | _5        |dk    r ||          nd| _6        d| _7        i | _8        n}|j2        | _2        || _7        t	          |d)d          }|st	          |d*d          }|j2        |d+|rd*ts          |          ini | _8        | || j8        d,<   | :                    d-.           | ;                    ||||/          \  | _<        | _=        | >                                 tO          | d0          r| j?        rdd1l@mA} t          | j2        t                     r| j2        nd}  || j#        | j        | | j%        t	          | d2d          t	          | d3d          4          }!| j?        C                    | j#        |!| j        t	          | dd          | j%        | j&        5           | D                    d6| d7|            t$          +                    d8|||           dS # t6          $ r:}"t$          E                    d9||"           |                                 cY d}"~"S d}"~"ww xY w):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.
    _fallback_activatedFr=   r;   <   r   r   r   /z?Fallback skip: chain entry %s/%s matches current provider/modelz>Fallback skip: chain entry base_url %s matches current backendr   )resolve_provider_clientNapi_keykey_envapi_key_envz
ollama.comOLLAMA_API_KEYT)r   	raw_codexexplicit_base_urlexplicit_api_keyz.Fallback to %s failed: provider not configured)normalize_model_for_providerz9Could not normalize fallback model %r for provider %r: %schat_completionsr>   rr   	anthropicz
/anthropicrw   )r=   bedrockzbedrock-runtime.zamazonaws.comrx   _transport_cache_credential_poolznFallback to %s/%s: clearing primary credential pool (pool_provider=%s) to prevent cross-provider contamination)build_anthropic_clientresolve_anthropic_token_is_oauth_tokenr   _custom_headersdefault_headers)r  r   r   fallback_timeout_applyrh   )r=   r   r   r   r   )get_model_context_length_config_context_length_custom_providers)r   r  r=   config_context_lengthcustom_providers)r   r   r   r  r=   r   u5   🔄 Primary model failed — switching to fallback: z via u"   Fallback activated: %s → %s (%s)z"Failed to activate fallback %s: %s)Fr   
rate_limitbillingr8   rA   r   r   _primary_runtimer4   r   	monotonic_rate_limited_until_fallback_indexr!   _fallback_chain_try_activate_fallbackr    rstripr   r   r;  r  rI   rJ   r   hermes_cli.model_normalizer  r   r   _is_azure_openai_urlendswith_is_direct_openai_url&_provider_model_requires_responses_apir   
startswithr   r  r=   r   r  r  clearr  r   r  r   rB  r  r  r  r  _anthropic_api_keyr   r   r1  rS   _client_kwargsr3   _replace_primary_openai_client_anthropic_prompt_cache_policy_use_prompt_caching_use_native_cache_layout_ensure_lmstudio_runtime_loadedr   agent.model_metadatar  r   update_modelr   rR   )#rB   rd   fallback_already_activecurrent_providerprimary_providerfbfb_providerfb_modelcurrent_modelcurrent_base_urlfb_base_url_for_dedupr  fb_base_url_hintfb_api_key_hint
fb_key_env	fb_client_resolved_fb_modelr  	_norm_errfb_api_modefb_base_url_fb_is_azure	old_model_existing_pool_pool_provider_fb_timeoutr  r  r  effective_key
fb_headersr  _fb_ctx_api_keyfb_context_lengthr   s#                                      r   try_activate_fallbackr    s^
    .+^-CDDD #'wu6KU'S'S"T"T#E:r::@bGGIIOOQQ"39r>>zJJPbWWYY__aa' 	>-= 	>BRVfBfBf(,(8(82(=E%E$9 : :::u		u4	5B	Q66*%%+2244::<<Kw%2,,..H .h .++---  z266<"CCEEKKMMUGR006B==??M75*b99?R@@GGLLRRTTVVJ//52<<>>EEcJJPPRR&&&8}+D+DM	
 	
 	
 ++---
.
. "%555%%L!	
 	
 	
 ++---
D.BBBBBB FF:..4";;==E66),,299;;Ct 	L &&++Jrvvm/D/DJQQSSJ L"$)J";";"A"A"C"C"Kt  	B 56F U U 	B^m 	B i(899ATO(?(?x4.,). ). ).%	% NN@   //111	OOOOOO33HkJJHH 	 	 	NNK+y       	 )),--11+>>.((+KKK'';+=+=c+B+B+H+H+J+J+S+ST`+a+a'.KK 	- -KK((55 	-+KK99  : 
 
 	- ,KKI%%k**556HII &%k?CC & -KK	
 (,$$$$5,-- 	+"((***$(! !(:DAA%%nj"EEKRRTTZZ\\N ..K"?"?Q>  
 *.&
 3;II...ppppppppppVaepVpVpY.Q2I2I2K2KQr  xA  xI  xO  MOM)EM'4E$(3E%&<&<u8+' ' 'E# KVYdJdJd(F(F(FjoE%EL#%E   &-EM$EL !,=tDDJ I$Y0A4HH
$,'$ $ =GN%tJ'7'788B$E 
 &2=$Y/ 44<T4UUU 00$$$	 1   	B!5#A 	--/// 5.// 	E4L 	EEEEEE
 0:%-/M/MUemmSUO 8 8en'%.&-e5Mt&T&T!(0CT!J!J	! ! ! $11k0y"55 2    	,, ,), ,	
 	
 	
 	0x	
 	
 	
 t . . .98QGGG++--------.sJ   ?D4a< 5Q a< 
Q9Q4/a< 4Q99Pa< <
c /b;5c ;c r#   api_call_countc           
     L   t          d| j         d           d}|                    d|d           	 |                                 }g }|D ]s}|                                }|                     ||           dD ]}|                    |d           |r|                     |           |                    |           t| j        pd}	| j	        r|	d	z   | j	        z   
                                }	|	r	d
|	dg|z   }| j        rK|	rdnd}
t          | j                  D ]0\  }}|                    |
|z   |                                           1|                     |          }|                     |          }i }	 ddlm}m} n# t&          $ r d}d}Y nw xY w| || j        | j                  nd}||u }|rdn|}d| j        v }| j        pd
                                                                dk    o|                                 }|r|                                 nd}|s.|                                 r| j        | j        |d<   nddd|d<   |rddlm}  |            |d<   | j        dk    r|                     |          }|                    dd           |                      |          }| !                                }|"                    |          }|j#        pd
                                }n| j        |d}|||d<   | j$        -|%                    | &                    | j$                             |||d<   i }| j'        r
| j'        |d<   | j(        r
| j(        |d<   | j)        r
| j)        |d<   | j*        r
| j*        |d<   |rJ| j        pd
                                                                dk    s| +                                r||d <   | j        d!k    r| j        pd
                                                                dk    s| +                                r\| j,        U| j,        dk    rJ	 t[          | j,                  }n# t\          t^          f$ r d}Y nw xY w|d"|cxk    rd#k    rn n	d$|d%g|d&<   |r||d'<   | j        d(k    r| !                                }|0                    | j        |d| j$        | j        | j1        | 2                                )          } | 3                    |           }|"                    || j1        *          }!|!j#        pd
                                }nm | 4                    d+,          j5        j6        j7        d7i |}| !                                "                    |          }!|!j#        pd
                                }|rXd-|v r4tq          j9        d.d|tp          j:        /          
                                }|r|                    d0|d           n]d1}nY| j        dk    r|                     |          }|                    dd           |                      |          }"| !                                }#|#"                    |"          }$|$j#        pd
                                }nn| j        d(k    r| !                                }%|%0                    | j        |d| j1        | j$        | j        | 2                                2          }&| 3                    |&          }"|%"                    |"| j1        *          }'|'j#        pd
                                }n| j        |d}|||d<   | j$        -|%                    | &                    | j$                             |||d<   |r||d'<    | 4                    d3,          j5        j6        j7        d7i |}| !                                "                    |          }'|'j#        pd
                                }|rVd-|v r4tq          j9        d.d|tp          j:        /          
                                }|r|                    d0|d           nd1}nd1}nN# t&          $ rA}(tv          <                    d4|(            d5| j         d6t{          |(           }Y d}(~(nd}(~(ww xY w|S )8zSRequest 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.user)rs  rt  )ru  ri  _thinking_prefillNr;   rn  systemr   r   r  r  r  ru  Tmedium)enabledeffort)nous_portal_tagstagsrr   r/   )r   r#   temperaturereasoning_effortr  r	  r
  r  
openrouterr=   zopenrouter/pareto-codeg        g      ?zpareto-router)r~  min_coding_scoreplugins
extra_bodyrw   )r   r#   r/   r   r   r   r   )strip_tool_prefixiteration_limit_summaryrh   z<think>z<think>.*?</think>\s*rl  rr  z>I reached the iteration limit and couldn't generate a summary.)r   r#   r/   r   r   r   r   iteration_limit_summary_retryz Failed to get summary response: z"I reached the maximum iterations (z!) but couldn't summarize. Error: r'   )>printmax_iterationsr  _should_sanitize_tool_callsr4  _copy_reasoning_content_for_apir   #_sanitize_tool_calls_for_strict_api_cached_system_promptephemeral_system_promptr   prefill_messages	enumerateinsert_sanitize_api_messages#_drop_thinking_only_and_merge_usersr;  r  r  r   r   r   r:   r=   r   rH  *_resolve_lmstudio_summary_reasoning_effortr   agent.portal_tagsr  r   _build_api_kwargsr   r.  normalize_responsert  r   updaterF  r<  r=  r>  r?  r:  r  rG   rK   rL   r0  r1  r2  r   _ensure_primary_openai_clientr   r   r   r  subr  r   r   r    ))rB   r#   r  summary_request_needs_sanitizer   r  api_msginternal_fieldeffective_system
sys_offsetidxpfmsummary_extra_bodyr  
_OMIT_TEMP_raw_summary_temp_omit_summary_temperature_summary_temperaturerZ  _is_lmstudio_summary_lm_reasoning_effort_portal_tagscodex_kwargssummary_response_ct_sum_cnr_sumfinal_responsesummary_kwargsr  _ps_tsum_ant_kw_summary_resultretry_response	_ct_retry
_cnr_retry_tretry_ant_kw2_retry_resultr   s)                                            r   handle_max_iterationsrI    s
   	
_1E
_
_
_```	* 
 OOV@@AAAI~  ;;== 	) 	)ChhjjG11#w???"U 2 2ND1111 C99'BBB(((( 6<"( 	c 06 9E<Y Y``bb 	\%-:JKKL|[L! 	B.5AJ%e&<== B BS##J$4chhjjAAAA 33LAA @@NN	kkkkkkkkk 	 	 	+/(JJJ	
 ,7 )(enEEE 	
 %6$C!'@WttFW!U%:: ^!r((**0022j@ 74466 	 $.E<<>>>)- 	 $ 	(L(L(N(N 	%1272H";//  $&3 3";/  	8JJJJJJ)5v&>... 22<@@LWd+++$66|DD**,,G112BCCH&.4";;==NN ( N $/0D}-+%%e&=&=e>N&O&OPPP#/5I12 $& & G/4/F$V,& I161H$X.$ F050E$W-" C/4/B$V,# F%2,,..4466,FF++-- G 2F":. 777^)r002288::lJJ//11 K 5A5;; ABBCC!:.   CCC?sc'8'8'8'8S'8'8'8'8'8.CHH5&y1 " B/A|,~!555,,..,,5;]a*/*:UMc(-(A-2-K-K-M-M - O O $)#C#CG#L#L "'":":;K_d_x":"y"y"1"9"?R!F!F!H!H $A5#F#FNg#F#h#h#m#y  $A  $S  $S  DR  $S  $S "'"6"6"8"8"K"KL\"]"]"1"9"?R!F!F!H!H 3	bN**!#(@"n\^\e!f!f!f!l!l!n!n b P PQQQQ!a ~!222$66|DD  $///!&!8!8!F!F!0022	&99.II
","4":!A!A!C!C#777..00"//ekL`d).)B+0+;eNd.3.L.L.N.N 0 P P "'!A!A(!K!K ' : :>]b]v : w w"/"7"=2!D!D!F!F #[ ," " (34HN=1#/"))%*A*A%BR*S*STTT'39MN#56% F3EN<0 $G5#F#FNm#F#n#n#s#  $G  $Y  $Y  JX  $Y  $Y  % 4 4 6 6 I IJZ [ ["/"7"=2!D!D!F!F b..%'V,Db.`b`i%j%j%j%p%p%r%rN! fOO[^$T$TUUUU%eNN!a ~ ~ ~=!==>>>}e>R}}uxyzu{u{}}~ sb   Ea 9F a Fa FJ#a 7Q a Q"a !Q""O3a 
b! 7bb!task_idre   c                   	 t          |          r | j        rt          j        d| d           n!t	                                          |           n># t          $ r1}| j        r t                              d| d|            Y d}~nd}~ww xY w	 t	                      	                    |           dS # t          $ r8}| j        r&t                              d| d|            Y d}~dS Y d}~dS d}~ww xY w)a(  Clean up VM and browser resources for a given task.

    Skips ``cleanup_vm`` when the active terminal environment is marked
    persistent (``persistent_filesystem=True``) so that long-lived sandbox
    containers survive between turns. The idle reaper in
    ``terminal_tool._cleanup_inactive_envs`` still tears them down once
    ``terminal.lifetime_seconds`` is exceeded. Non-persistent backends are
    torn down per-turn as before to prevent resource leakage (the original
    intent of this hook for the Morph backend, see commit fbd3a2fd).
    z0Skipping per-turn cleanup_vm for persistent env z; idle reaper will handle it.zFailed to cleanup VM for task z: Nz#Failed to cleanup browser for task )
r   r  r  r  r   
cleanup_vmr   r   r   cleanup_browser)rB   rJ  r   s      r   cleanup_task_resourcesrN    sl   LW%% 	&$ 3w 3 3 3  
 EEW%%% L L L  	LNNJGJJqJJKKKLQg&&&&& Q Q Q  	QNNOOOAOOPPPPPPPPP	Q 	Q 	Q 	Q 	Q 	QQs0   AA 
B'B		B!B5 5
C7?'C22C7)rv   c          	         !"  j         rt          d           j        dk    r0 _        	                                d _        S # d _        w xY w j        dk    rddd"ddiddifd	 "fd
}t          j        |d          }|                                 |                                r@|	                    d            j         rt          d          |                                @"d         "d         "d         S ddg d"dddd t          j
                    ! !fd !fd}dK  !fdddiddidt          j                    ifd  "fd  fd  "fd}t           j         j                  }||}n"t          t!          j        d d!                    }|d!k    rK j        rDt'           j                  r0t          d"          }	t(                              d# j                   n?t-                    }
|
d$k    rt/          |d%          }	n|
d&k    rt/          |d'          }	n|}	t          j        |d          }|                                 t          j                    }d(}|                                r|	                    d           t          j                    }||z
  |k    r3|}t1          |d         z
            }                     d)| d*           t          j                    d         z
  }||	k    rt-                    }t(                              d+||	                    d,d-          |d.                                d/t1          |           d0                    d,d-           d1|d.d2           	  d3           n# t:          $ r Y nw xY w	                      d45           n# t:          $ r Y nw xY wt          j                    d<                        d6t1          |           d7            j         re	  j        d8k    r. j                                           !                                 n d9           n# t:          $ r Y nw xY wt          d:          |                                "d         d         rtE           d;d<          pd<#                                pd}tI          "                    d=          pg           }|rd>	                    |dd?                   }tK          |          d?k    r|d@tK          |          d?z
   dAz  }dB| dC}|pd<|z   }	  &                    |           n# t:          $ r Y nw xY wt(                              dD|tK          |pd<          "d                    tN          }n8t(                              dEtK          |pd<          "d                    tN          }tQ          dF|ddG          }tQ          tR          tE           d,d-          tQ          dH||I          gd|pdJ          S "d         "d         S )Lu  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.
    z+Agent interrupted before streaming API callrr   Nrx   rP   doneFr   c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S NrP  Tr   first_delta_firedrv   s   r   _fire_firstz5interruptible_streaming_api_call.<locals>._fire_first  sq    $V,  ,0!&)"N$$$$$    DD	      
 
,,c                    	 ddl m} m}m}m}                     dd          }                    dd             | |          }	  |j        di }n)# t          $ r} ||          r ||            d }~ww xY wfd}fd}	fd}
 ||                                r|nd |	j	        sj
        r|
nd fd	
          d<   d S # t          $ r}|d<   Y d }~d S d }~ww xY w)Nr   )ry   rz   r{   stream_converse_with_callbacksr}   r~   r   c                P                                       |            dd<   d S )NTr   )_fire_stream_delta)textrV  rB   deltas_were_sents    r   _on_textzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_text,  s3    KMMM,,T222.2$U+++r   c                F                                       |            d S r&   )_fire_tool_gen_started)rE   rV  rB   s    r   _on_toolzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_tool1  s(    KMMM0066666r   c                F                                       |            d S r&   )_fire_reasoning_delta)r\  rV  rB   s    r   _on_reasoningzNinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_reasoning5  s(    KMMM//55555r   c                      j         S r&   )r   )rB   s   r   <lambda>zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>>  s
    u/I r   )on_text_deltaon_tool_starton_reasoning_deltaon_interrupt_checkrQ   rR   r'   )r   ry   rz   r{   rY  r   converse_streamr   _has_stream_consumersr  r  )ry   rz   r{   rY  r   rS   r   r   r^  ra  rd  r   rV  rB   rN   r]  r   s               r   _bedrock_callz7interruptible_streaming_api_call.<locals>._bedrock_call  s   ($            $(<kJJ5t<<<44V<<#96#9#G#GJ#G#GLL     10>> :11&9993 3 3 3 3 3 3
7 7 7 7 7 76 6 6 6 6 6 &D%C .3.I.I.K.K"U((QU"*8=8P'yTYTo'y}}uy'I'I'I'I& & &z"""  $ $ $"#w$s=   AC A C 
A;A66A;;AC 
C)C$$C)Tr   r   r   z)Agent interrupted during Bedrock API callrR   rQ   )rQ   rR   partial_tool_names)rS   diagrT   c                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S rV   rW   rZ   s    r   r]   z=interruptible_streaming_api_call.<locals>._set_request_clientQ  s      	G 	G.4!(+1:1D1F1F!+.	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G r^   c                 ~    5                       d          } d d<   d d<   | cd d d            S # 1 swxY w Y   d S rV   r`   rZ   s    r   ra   z>interruptible_streaming_api_call.<locals>._take_request_clientX  rb   rc   rd   r    r   re   c                R   5                       d          }                     d          }|d uo|d uo|t          j                    k    }|s
d d<   d d<   d d d            n# 1 swxY w Y   |d S |r                    ||            d S                     ||            d S rg   ri   rl   s       r   ro   zDinterruptible_streaming_api_call.<locals>._close_request_client_once_  s*   
 ! 
	: 
	:266x@@N-11+>>Id* 7T)7!4!6!66 
 # :26%h/59%k2
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: 
	: !F 	N..~f.MMMMM..~f.MMMMMrp   r   c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S rR  rS  rT  s   r   _fire_first_deltaz;interruptible_streaming_api_call.<locals>._fire_first_delta}  sq     ( 	^ 	(,f%        		 	 	 	rW  c                    ddl } t          +j        +j                  }||n!t	          t          j        dd                    }||}nft	          t          j        dd                    }|dk    r>+j        r7t          +j                  r#|}t          
                    d+j        |           |t          |d          nd	}i ,d
dd
i|                     ||||          d} *+                    d|                    }t          j                    .d<   +                    d           +                                }|/d<    |j        j        j        d7i |}+                    t+          |dd                     +                    |t+          |dd                     +                    t+          |dd                     g }	i }
t1                      }i }i }d}d}d}g }d}|D ]X}t          j                    .d<   +                    d           	 t3          |                    dd                    dz   |d<   |                    d          .d         |d<   	 t3          |                    dd                    t7          t9          |                    z   |d<   n# t:          $ r Y nw xY wn# t:          $ r Y nw xY w+j        r nr|j        s>tA          |d          r|j        r|j        }tA          |d          r|j!        r|j!        }-|j        d         j"        }tA          |d          r|j        r|j        }t+          |dd          pt+          |dd          }|r4|#                    |            )             +$                    |           |r|j%        r|	#                    |j%                   |
s* )             +&                    |j%                   d
-d<   nM+j'        rF	 +'                    |j%                   +(                    |j%                   n# t:          $ r Y nw xY w|r|j)        r|j)        D ]}|j*        |j*        nd}|j+        pd}||vr|||<   |r)||v r%|||         k    rtY          |
d !          dz   }|||<   |r|||<   ||         }||
vr|j+        pdd"ddd#dd$|
|<   |
|         }|j+        r
|j+        |d%<   |j-        rM|j-        j.        r|j-        j.        |d"         d&<   |j-        j/        r |d"         d'xx         |j-        j/        z  cc<   t+          |d(d          }|,tA          |d)          r|j0        pi                     d(          }|)tA          |d*          r|1                                }||d(<   |d"         d&         }|rS||vrO|2                    |            )             +3                    |           0d+         #                    |           |j        d         j4        r|j        d         j4        }tA          |d          r|j!        r|j!        }Zd5                    |	          pd}d}d,} |
rg }tm          |
          D ]}|
|         }!|!d"         d'         }"|!d"         d&         pd-}#|"rZ|"7                                rF	 tq          j9        |"           n0# tp          j:        $ r tw          |"|#          }$|$d.k    r|$}"nd
} Y nw xY w|#                    ty          |!d%         |!d/         |!                    d(          ty          |!d"         d&         |"#          0                     |pd1}%| rd2}%d5                    |          pd}&ty          ||||&3          }'ty          d|'|%4          }(ty          d5t{          t}          j?                              z   ||(g|6          S )8z#Stream a chat completions response.r   NHERMES_API_TIMEOUTg      @HERMES_STREAM_READ_TIMEOUTr   uD   Local provider detected (%s) — stream read timeout raised to %.0fsr         >@Tinclude_usage)connectreadwritepool)streamstream_optionsr   chat_completion_stream_requestrt   r   z)waiting for provider response (streaming)ro  rQ   rr  receiving stream responsechunksr   first_chunk_atbytesr   usagerv  ru  r   r;   )rF   r  r  )r~  r  r  r  r~  rE   r  r  rw  r{  rn  F?r  r  )r~  r  r  r  stoplengthrs  rt  rk  rv  indexmessageri  zstream-)r~  r   choicesr  r'   )@httpxr   r=   r   rG   rI   rJ   r   r   r   r  minTimeoutr   r   r   _stream_diag_initr   r   r   _capture_rate_limitsrA   _stream_diag_capture_response_check_openrouter_cache_statussetr   r4   r!   reprr   r   r  r  r  deltar  rc  rt  r[  r  _record_streamed_assistant_textrk  r  r~  r   r  rE   r  rw  r{  addr`  ri  r   sortedr   jsonloadsJSONDecodeErrorr   r   r    rC  rD  )1_httpx_provider_timeout_cfg_base_timeout_stream_read_timeout	_conn_capstream_kwargsrm   _diagr~  content_partstool_calls_acctool_gen_notified_last_id_at_idx_active_slot_by_idxri  
model_namers  reasoning_parts	usage_objchunkr  r  tc_deltaraw_idxdelta_idnew_slotr/  entryr  rE   full_contentmock_tool_callshas_truncated_tool_argstcr  	tool_namerepairedeffective_finish_reasonfull_reasoningmock_messagemock_choicert  r]   rB   rN   r]  last_chunk_timer[   r   s1                                            r   _call_chat_completionsz@interruptible_streaming_api_call.<locals>._call_chat_completions  s	    !=U^U[ Y Y %0 "!ry!5v>>?? 	 !,#8  #(3OQV)W)W#X#X 
 $u,,,DUV[VdDeDe,'4$ZN$8   1F0QCt,,,W[	



.5~~!)#	 &  	

 

 

 -,//7( 0  
 
  $y{{IJJJ ''))(-f%7$07HH-HH
 	""76:t#D#DEEE 	++E76:t3T3TUUU 	,,WVZ-N-NOOO !!$
 !#$&
 "	 L	( L	(E#'9;;OC !!"=>>>
"%eii!&<&<"="="Ah99-..6.=c.BE*+
%(7A)>)>%?%?#d5kkBRBR%RE'NN    D    ) = 5'** -u{ -!&J5'** ,u{ , %IM!$*Eug&& )5; )"[
 %U,?FFk'RWYdfjJkJkN <&&~666!!###++N;;;   $$U]333% %%''',,U];;;.2$U++ 0 33EMBBB==emLLLL$     ?B) ?B % 0 >B >BH080JhnnPQG'{0bH &9997>+G4 @#66$(@@@#&~r#B#B#BQ#F7?+G4 <3;0-g6C.00"*+"3$.13"(E(E-1	/ /s+ +3/E{ 2&.kd( Z#,1 	O 9A8I8NE*-f5#,6 Z!*-k:::h>O>YY:::#HotDDE}=)I)I}!)!5!; @ @ Q Q("5,77 7$)$4$4$6$6E16o. ,V4D B+< < <)--c222))+++44T::: 34;;DAAA}Q- ? %a 0 > ug&& (5; (!K	 ww}--5"'  	 On--  #C(zN;7	zN629c	 ;!2!2 ;;
9----/ ; ; ; $?y)#T#T#t++(0II 7;3;  &&$xF"$&&"9"9,
^F3"+  	( ( (     #0"96" 	/&.#119T& &,	
 
 
 & 1
 
 

 3tz||,,, M	
 
 
 	
s\   !A	K +AJ/.K /
J<9K ;J<<K  
KK>4P33
Q ?Q 9[*[;:[;c            	     f   d} t          j                     d<                                   }|d<    j        j        j        di 5 }	                     |t          |dd                     n# t          $ r Y nw xY w|D ] }t          j                     d<                       d           	 t          |
                    dd                    d	z   |d<   |
                    d
          d         |d
<   	 t          |
                    dd                    t          t          |                    z   |d<   n# t          $ r Y nw xY wn# t          $ r Y nw xY wj        r nt          |dd          }|dk    r^t          |dd          }|rIt          |dd          dk    r4d} t          |dd          }|r                                  |           ]|dk    rt          |dd          }|rt          |dd          }|dk    r;t          |dd          }	|	r&| s$                                  |	           dd<   |dk    r2t          |dd          }
|
r                                  |
           |                                cddd           S # 1 swxY w Y   dS )a$  Stream 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   ro  rQ   Nr  r  r   r   r  r  r  content_block_startcontent_blocktool_useTrE   content_block_deltar  
text_deltar\  r;   r   thinking_deltathinkingr'   )r   r  r   r#   r~  r  rA   r   r   r   r4   r!   r  r   r`  r[  rc  get_final_message)has_tool_user  r~  event
event_typeblockr  r  
delta_typer\  thinking_textrt  rB   rN   r]  r  r[   s              r   _call_anthropicz9interruptible_streaming_api_call.<locals>._call_anthropic  s      $y{{''))(-f%4U$-4BBzBB @	.f
3376:t<<        2K 2K (,y{{$%%&ABBB	&)%))Ha*@*@&A&AA&EE(Oyy!122:2A#2F./),UYYw-B-B)C)Cc$u++FVFV)Vg$       D - E$UFD99
!666#E?DAAE D!=!=!K!K'+$+E64$@$@	$ D--///!88CCC#888#E7D99E K%,UFD%A%A
%55#*5&"#=#=D# ?L ? 1 1 3 3 3 % 8 8 > > >:> 0 7'+;;;,3E:r,J,JM, K 1 1 3 3 3 % ; ;M J J J ++--A@	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	. @	.s   
J&%A21J&2
A?<J&>A??3J&3A	E=AE E
EEEEJ&
EJ&ED:J&&J*-J*c                 `	   dd l } t          t          j        dd                    }	 t	          |dz             D ]*}j        rt          d          	 j        dk    r"                                              d<   n             d<     d           d S # t          $ r}t          || j        | j        | j        f          }t          || j        | j        t           f          }                    |          }d	         rt%                              d
                    }d}|sg|seddlm}	 t          ||	          rOt-          |dd           s>t/          |                                          d}
t3          fd|
D                       }|p|p|p|}|o|o||k     }|s2t4                              d|           |d<   Y d }~  d           d S 	                     d           n# t          $ r Y nw xY w	                                  n# t          $ r Y nw xY wg d
<   dd	<   dd<                       ||dz   |dz   d                    d                      d           	                     d           n# t          $ r Y nw xY wY d }~jd}|sg|seddlm}	 t          ||	          rOt-          |dd           s>t/          |                                          d}t3          fd|D                       }|s|s|s|r||k     rl                    ||dz   |dz   d                    d                      d           	                     d           n# t          $ r Y nw xY wY d }~O                     d||dz   |dz   d                    d                     !                    |r	d|dz    d nd!|dz    d            nbt/          |                                          }d"|v od#|v }|rd_"        #                    d$           t4          $                    d%|           |d<   Y d }~  d           d S d }~ww xY wn(# t          $ r}|d<   Y d }~ d           d S d }~ww xY w	  d           d S #  d           w xY w)&Nr   HERMES_STREAM_RETRIES   r   z%Agent interrupted before stream retryrw   rQ   stream_request_completer   rn  F)APIErrorstatus_code)
zconnection lostzconnection resetzconnection closedzconnection terminatedznetwork errorznetwork connection
terminatedzpeer closedzbroken pipezupstream connect errorc              3      K   | ]}|v V  	d S r&   r'   )r(   phrase_err_lower_previews     r   r*   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>6  s=       ?" ?"(. %+.@$@?" ?" ?" ?" ?" ?"r   z9Streaming failed after partial delivery, not retrying: %srR   u9   

⚠ Connection dropped mid tool-call; reconnecting…

rP  Tro  )rR   attemptmax_attemptsmid_tool_callro  stream_mid_tool_retry_cleanup"stream_mid_tool_retry_pool_cleanuprh   c              3      K   | ]}|v V  	d S r&   r'   )r(   r  _err_lower_sses     r   r*   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>  s<       3 3$* !'. 83 3 3 3 3 3r   stream_retry_cleanupstream_retry_pool_cleanup	exhausted)kindrR   r  r  r  ro  u5   ❌ Provider returned malformed streaming data after uM    attempts. The provider may be experiencing issues — try again in a moment.u(   ❌ Connection to provider failed after r~  znot supportedu   
⚠  Streaming is not supported for this model/provider. Switching to non-streaming.
   To avoid this delay, set display.streaming: false in config.yaml
z$Streaming failed before delivery: %s)%r  r   rI   rJ   ranger   r   r   )_try_refresh_anthropic_client_credentialsr   r   ReadTimeoutConnectTimeoutPoolTimeoutConnectErrorRemoteProtocolErrorConnectionError_is_provider_stream_parse_errorr8   r4   openair  rA   r    r   anyr   r   r[  _reset_stream_delivery_tracking_emit_stream_dropr  _log_stream_retryr   _disable_streaming_safe_printr   )r  _max_stream_retries_stream_attemptr   _is_timeout_is_conn_err_is_stream_parse_err_partial_tool_in_flight_is_sse_conn_err_preview	_APIError_SSE_PREVIEW_PHRASES_is_transient_can_silent_retry_is_sse_conn_err_SSE_CONN_PHRASES
_err_lower_is_stream_unsupportedr  r  r  r  ro   rB   r]  rU  r[   r   s                    @@r   r   z/interruptible_streaming_api_call.<locals>._call  s   !"),CQ"G"GHHp	B#()<q)@#A#A g g - T*+RSSS^~)===GGIII-<_->->z**-C-C-E-Ez*@ '&'@AAAAA ! W W W",F.0EvGYZ# #K $.F/1K_]$ $L ,1+P+PQR+S+S( (. Z!26"JJ';<<3 3/ 490* "< "DDDDDD)!Y77 "=Z^@_@_ "58VV\\^^ 28" 4 <? ?" ?" ?" ?"2F?" ?" ?" <" <" 8
 ( 4+474  4	 & 4 F -F /2E E *
  1 # #NN []^   /0F7O"FFFFv '&'@AAAAAg!!44!6     ) ! ! ! D!!!AACCCC( ! ! ! D!
 8:3427(/49)&1//"#$3a$7)<q)@*.!6!:!:6!B!B 0    323RSSS!!@@'K A      ) ! ! ! D!  (-$& | @@@@@@%a33 GA}VZ<[<[ -0VV\\^^N1- 03 3 3 3 3.?3 3 3 0 0,
 # @l @6F @J^ @ +-@@@!33&'(7!(;-@1-D.3%:%>%>v%F%F 4    767MNNN% % D D+F !E !" !" !" !" $- % % % $%$HHHH //!,"#$7!$;)<q)@*/!6!:!:6!B!B 0    ,,
  4	5 52Q65 5 5 5
52Q65 5 5
 
 
 
 &)VV\\^^
$
2 > /: = / 2 7;E4!--!3   B   '(F7OFFFF '&'@AAAAAW!gP   	 	 	  F7OFFF&&'@AAAAA	Qg^ '&'@AAAAA&&'@AAAAs  +Q* :BQ* Q&*D#Q!Q*  G65Q!6
H Q!HQ!HQ!
H)&Q!(H))AQ!:JQ!
JQ!JQ!!Q* 'B7Q!M65Q!6
N Q!NQ!Q* CQ!Q* !Q&&Q* )R  *
R4R
9R  
RR   R-HERMES_STREAM_STALE_TIMEOUTr   infu>   Local provider detected (%s) — stale stream timeout disabledr   g     r@r   g      n@rx  zwaiting for stream response (zs, no chunks yet)uq   Stream stale for %.0fs (threshold %.0fs) — no chunks received. model=%s context=~%s tokens. Killing connection.r   r   r   r   z
s (model: z, context: ~z tokens). Reconnecting...stale_stream_killstale_stream_pool_cleanuprh   zstale stream detected after zs, reconnectingrw   stream_interrupt_abortz+Agent interrupted during streaming API call _current_streamed_assistant_textr;   rn  z,    z, +z moreu$   

⚠ Stream stalled mid tool-call (zH); the action was not executed. Ask me to retry if you want to continue.z[Partial stream dropped tool call(s) %s after %s chars of text; surfaced warning to user: %szPartial stream delivered before error; returning length-truncated stub with %s chars of recovered content so the loop can continue from where the stream died: %srr  r  r   r  )r~  r   r  r  _dropped_tool_namesr   )*r   r   r   ru   _interruptible_api_callrX   r   r   r   r   r   r   r	   r=   r   rG   rI   rJ   r   r   r   r  r7   r   r   r   r   r4   r   r   r  r   r   r   rA   r   r+   r!   r[  r   r   r
   )#rB   rN   rv   rm  r   ra   r   
_cfg_stale_stream_stale_timeout_base_stream_stale_timeout_est_tokens_last_heartbeat_HEARTBEAT_INTERVAL_hb_now_waiting_secs_stale_elapsedr   _partial_text_partial_names	_name_str_warn_stub_finish_reason	_stub_msgr  r  ro   rV  rt  r]   r]  rU  r  r[   r\   r   s#   ```                    @@@@@@@@@@@@r    interruptible_streaming_api_callr    s=	     ! NLMMM~***
 '5#	/00<<*.E''$E'.... ~+++"T22#UO!5>	 	 	 	 	 	)	$ )	$ )	$ )	$ )	$ )	$ )	$ )	$ )	$V M$???				jjll 	TFF3F) T&'RSSS jjll 	T '?&/!j!!RHHF'+TMM#.**          N N N N N N N N.  u~ DIKK(O     ]
 ]
 ]
 ]
 ]
 ]
 ]
 ]
 ]
 ]
 ]
 ]
~P. P. P. P. P. P. P. P. P. P.duB uB uB uB uB uB uB uB uB uB uB uBp ,ENEKHHJ%/""%*295RTY+Z+Z%[%[" "U**u~*BSTYTbBcBc* %eUW\Weffff 6jAA  $'(BE$J$J!!6!!$'(BE$J$J!!$>!d333AGGIIIikkO
**,, ?R	s )++_$(;;;%O/#*> >??M!!PPPP   s';;1116zBBHNNC 5w	22xOO	     #N8K8K # #%>>'9==# #%3# # #  **+>????   44<W4XXXX    $(9;;OC !!Ss>/B/BSSS   % 		R>%999+11333335555../GHHH   "#PQQQ **,, ?R@ g"E" 8	 A2FFL"egg  "&**-A"B"B"HbIIN ; IInRaR&899	~&&**!Es>':':Q'>!E!E!EEI@!@ @ @ 
 "/!4" =,,U3333    D<"C(;$<$<fWo  
 ';##& +,,7O   ';#' -D"&  I #)eWi88(Y>Q    $2$:d    Wo*sT   A 	AO 
O! O!%O< <
P	P	AR 
R"!R"?V 
V"!V")r   rh  r  r  rI  rN  r  )r   r   r   r   )r   r8   )rE   r    rF   rG   r   rG   )rN   r3   )r   r+   r   r3   )ri  r    r   r3   r&   )rd   r  r   r8   )r#   r+   r  r   r   r    )rJ  r    r   re   )1__doc__
__future__r   r  r  rI   r  rX   r   rC  typesr   typingr   r   r   hermes_cli.timeoutsr   r	   hermes_constantsr
   r   agent.error_classifierr   r  r   agent.message_sanitizationr   r   tools.terminal_toolr   utilsr   r   	getLogger__name__r   r   r7   rD   rM   r   rh  r  r  rI  rN  r  __all__r'   r   r   <module>r*     sx    # " " " " "   				 				       ! ! ! ! ! ! & & & & & & & & & & X X X X X X X X I I I I I I I I 1 1 1 1 1 1 2 2 2 2 2 2        2 1 1 1 1 1 : : : : : : : :		8	$	$  2$ 2$ 2$ 2$j	 	 	 	   N N N Nd@ @ @ @HV V V Vt@. @. @. @. @.HV V V VtQ Q Q Q@ QU [ [ [ [ [ [B  r   