
    $*j	                   \   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!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,Z0g d-Z1d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_hostnameenv_intc                     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    B/home/ubuntu/.hermes/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_tokensr8   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_backendrE   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'   )rH   osgetenvr!   	TypeError
ValueError)rF   rG   s     r   
_env_floatrN   v   sP    RYtS\\22333z"   s   .1 AA
api_kwargsr4   c           	         ddddddt          j                    ddi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}|                                r|                    d()           |d*z  }|d+z  dk    r<t#          j                    |z
  }                     d,t/          |           d-           t#          j                    |z
  }|r||	k    rt1           d.d          d}t1           d/d          }t3          |          r3	  |
                    d0          1          }n# t4          $ r d}Y nw xY wt                              d2||	
                    d0d3                     |r@                     d4t/          |           d5
                    d0d3           d6|            n=                     d4t/          |           d5
                    d0d3           d7           	  d8           n# t4          $ r Y nw xY w                     d9t/          |           d:           |                    d;)           d<         sd=         k|r6t;          d>t/          |           d?t/          |	           d@|           d<<   n3t;          d>t/          |           d?t/          |	           dA          d<<   n#t1           d.d          }|rC|@t#          j                    |z
  |k    r%t#          j                    |z
  }t                              dB||
                    d0d3          |d!                                dCt/          |           dD
                    d0d3           d7           	  dE           n# t4          $ r Y nw xY w                     d9t/          |           dF           |                    d;)           d<         ;d=         3t;          dGt/          |           dHt/          |           dA          d<<   n||k    r%t                    }d}t1           d/d          }t3          |          r3	  |
                    d0          1          }n# t4          $ r d}Y nw xY wt                              dI||
                    d0d3          |d!           |r@                     dJt/          |           dK
                    d0d3           dL|            n=                     dJt/          |           dK
                    d0d3           dM           	  j        dNk    r. j                                                                            n dO           n# t4          $ r Y nw xY w                     dPt/          |           dQ           |                    d;)           d<         sd=         k|r6t;          dRt/          |           dSt/          |           d@|           d<<   n3t;          dRt/          |           dSt/          |           dA          d<<   n j!        rd&d<   t          "                    dT           	  j        dNk    r. j                                                                            n dU           n# t4          $ r Y nw xY wtG          dV          |                                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_tidr   Fc                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S NrT   rU   	threading	get_identrT   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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 NrT   rU   r`   r5   rY   rZ   _abort_request_openai_client_close_request_openai_clientr`   request_clientrU   stranger_threadrC   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<   nb# t          $ rU}	d         r>t                               dt%          |	          j                   Y d }	~	 
d           d S |	d<   Y d }	~	nd }	~	ww xY w 
d           d S #  
d           w xY w)Ncodex_responsescodex_stream_requestr`   rO   _codex_on_first_delta)rT   on_first_deltarR   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_requestr   uh   Non-streaming worker caught %s after request cancellation — exiting without surfacing a network error.request_completerS   r(   )api_mode_create_request_openai_client_run_codex_streamrB   _anthropic_messages_createagent.bedrock_adapterru   rv   rw   rx   popconverse	Exceptionchatcompletionscreateloggerdebugtype__name__)ri   ru   rv   rw   rx   regionrT   raw_response_bedrock_excerk   _request_cancelledr^   rC   rO   results             r   _callz%interruptible_api_call.<locals>._call   s   <	;~!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" 	  	  	 
 "'* AGG$  
  '&'9:::::  F7OOOOOO	  '&'9:::::&&'9::::sa   CE C E 
D $C;;D  AE F< 
F,5F'F< F'"F< 'F,,F< <G	rn   順 g     @P  g      @ia  g     @     f@      ^@i'        N@g      (@!HERMES_CODEX_TTFB_TIMEOUT_SECONDSr   &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_SECONDSz~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       @rS   rR   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.rs   stale_call_killz&stale non-streaming call killed after sz'Non-streaming API call timed out after zs with no response (threshold: zBForce-closing httpx client due to interrupt (not a network error).interrupt_abortz!Agent interrupted during API callr`   r!   r   ra   )$rY   Lock!_compute_non_stream_stale_timeoutr~   rE   r8   maxrN   rJ   environr5   striplowerr   infor   _codex_stream_last_progress_tstime_touch_activityThreadstartis_alivejoinr   rB   callabler   warning_buffer_statusTimeoutError_anthropic_clientclose_rebuild_anthropic_client_interrupt_requestedr   InterruptedError)rC   rO   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_ctxrk   r   r^   r\   r]   r   s   ``                      @@@@@@r   interruptible_api_callr   }   sB    ..F'+$??#.** "5)     N N N N N N N N@=; =; =; =; =; =; =; =; =; =;J <<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BEJJM	 *()QS[\\z~~&@"EEKKMMSSUU Z
 
 	*#a''.2EEE!MKKL 255#    ##BEJJI1}}!:!:W!599   !*1$2#  a# 4 -1)/3,)++K	BCCCd333AGGIIIK
**,, {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
 +/w'LLT  >%999+11333335555../@AAA   "#FGGGw **,, {Hx g"Wo*sn   L, ,L;:L;/O; ;
PP>V
 

VVY4 4ZZ:A]? ?
^^.Ab3 3
c ?c 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.rs   context_compressorN_ephemeral_max_output_tokens_anthropic_base_urlspeedfast_oauth_1m_beta_disabledF)r   r$   r0   
max_tokensreasoning_configis_oauthpreserve_dotscontext_lengthbase_url	fast_modedrop_context_1m_betart   _bedrock_regionrz   _bedrock_guardrail_configi   )r   r$   r0   r   r   guardrail_configrn   zmodels.github.aizapi.githubcopilot.comr?   r@   rA   >   	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$   r0   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$   r0   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$   r0   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(   )<r0   r~   _get_transport#_prepare_anthropic_messages_for_apirB   r   r   build_kwargsr   r   r   _is_anthropic_oauth_anthropic_preserve_dotsr   r5   r9   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))rC   r   tools_for_api
_transportrs   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_kwargsri  +  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<   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	reasoningrj  reasoning_contentmodel_extra reasoning_details__dict__
model_dumpanthropic_content_blockscodex_reasoning_itemscodex_message_itemsidcall_idfunctionrF   	arguments{}response_item_idrF   r  )r  r  r  r   r  extra_content)%rB   _extract_reasoningr9   ru  refindallDOTALLr   verbose_loggingloggingr   r"   reasoning_callbackstream_delta_callback_stream_callbackr   r   r    r!   _strip_think_blocksr   agent.redactrr  hasattrr4   _needs_thinking_reasoning_padrz  appendr{  r|  _split_responses_tool_id_deterministic_call_id"_derive_responses_function_call_idr   r  rF   r  )"rC   assistant_messagerj  assistant_tool_callsreasoning_text_from_structuredru  think_blockscombined_raw_content_san_contentrr  msgraw_reasoning_contentrx  raw_details	preserveddordered_blockscodex_itemsr  rl  	tool_callraw_idr  embedded_call_idrV  _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#$ .0JDQQN 9*8&' +-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r`   '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?   rn   	anthropicz
/anthropicrs   )r>   bedrockzbedrock-runtime.zamazonaws.comrt   _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_applyrd   )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billingr9   rB   r   r   _primary_runtimer5   r   	monotonic_rate_limited_until_fallback_indexr"   _fallback_chain_try_activate_fallbackr!   rstripr   r   r<  r  rJ   rK   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   rC  r  r  r  r  _anthropic_api_keyr   r   r2  rT   _client_kwargsr4   _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   rS   )#rC   r`   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           
        t          d| j         d           d}|                    d|d           	 |                                 }g }|D ]}|                                }|                     ||           dD ]}|                    |d           dD ]}	|                    |	d           d	 |D             D ]}
|                    |
d           |r|                     || j        
           |                    |           | 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        d:i |}| !                                "                    |          }#|#j#        pd                                }|rXd0|v r4tq          j9        d1d|tp          j:        2                                          }|r|                    d3|d           n]d4}nY| j        dk    r|                     |          }|                    dd           |                      |          }$| !                                }%|%"                    |$          }&|&j#        pd                                }nn| j        d+k    r| !                                }'|'0                    | j        |d| j1        | j$        | j        | 2                                5          }(| 3                    |(          }$|'"                    |$| j1        -          })|)j#        pd                                }n| j        |d}|||d<   | j$        -|%                    | &                    | j$                             |||d<   |r||d*<    | 4                    d6/          j5        j6        j7        d:i |}| !                                "                    |          })|)j#        pd                                }|rVd0|v r4tq          j9        d1d|tp          j:        2                                          }|r|                    d3|d           nd4}nd4}nN# t(          $ rA}*tv          <                    d7|*            d8| j         d9t{          |*           }Y d}*~*nd}*~*ww xY w|S );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.user)rt  ru  )rv  rj  _thinking_prefillN)	tool_namer~  r  c                f    g | ].}t          |t                    |                    d           ,|/S )rV  )r    r!   r  )r)   ks     r   
<listcomp>z)handle_max_iterations.<locals>.<listcomp>8  s9     ` ` `qz!S7I7I `all[^N_N_ ` ` ` `r   r   r<   ro  systemr   r   r  r  r  rv  Tmedium)enabledeffort)nous_portal_tagstagsrn   r0   )r   r$   temperaturereasoning_effortr	  r
  r  r  
openrouterr>   zopenrouter/pareto-codeg        g      ?zpareto-router)r  min_coding_scoreplugins
extra_bodyrs   )r   r$   r0   r   r   r   r   )strip_tool_prefixiteration_limit_summaryrd   z<think>z<think>.*?</think>\s*rm  rs  z>I reached the iteration limit and couldn't generate a summary.)r   r$   r0   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_callsr5  _copy_reasoning_content_for_apir   #_sanitize_tool_calls_for_strict_apir   _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   rI  *_resolve_lmstudio_summary_reasoning_effortr   agent.portal_tagsr  r~   _build_api_kwargsr   r/  normalize_responseru  r   updaterG  r=  r>  r?  r@  r;  r  rH   rL   rM   r1  r2  r3  r   _ensure_primary_openai_clientr   r   r   r  subr  r   r   r!   )+rC   r$   r  summary_request_needs_sanitizer   r  api_msginternal_fieldschema_foreigninternal_keyeffective_system
sys_offsetidxpfmsummary_extra_bodyr  
_OMIT_TEMP_raw_summary_temp_omit_summary_temperature_summary_temperaturer[  _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_iterationsrP    s$   	
_1E
_
_
_```	* 
 OOV@@AAAU~  ;;== 	) 	)ChhjjG11#w???"U 2 2ND1111 #` 2 2ND1111 ` `G ` ` ` 0 0L$//// V99'9UUU(((( 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   Fb  G	 b 	Gb GJ#b >R b R)&b (R))O3b 
c('7c##c(task_idra   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)rC   rQ  r   s      r   cleanup_task_resourcesrU    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)rr   c          	     0    !"  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
                    !ddi !fddL  !fdddiddidt          j                    id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         rdd<   t(                              d8           	  j        d9k    r. j                                           !                                 n d:           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|dAtK          |          d@z
   dBz  }dC| dD}|pd=|z   }	  &                    |           n# t:          $ r Y nw xY wt(                              dE|tK          |pd=          "d                    tN          }n8t(                              dFtK          |pd=          "d                    tN          }tQ          dG|ddH          }tQ          tR          tE           d,d-          tQ          dI||J          gd|pdK          S "d         "d         S )Mu  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 callrn   Nrt   rQ   doneFr   c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S NrW  Tr   first_delta_firedrr   s   r   _fire_firstz5interruptible_streaming_api_call.<locals>._fire_firstD  sq    $V,  ,0!&)"N$$$$$    DD	      
 
,,c                    	 ddl m} m}m}m}m}m}                     dd          }                    dd             | |          }	  |j        di }n# t          $ r}	 ||	          rhd_
                            d           t                              dt          |	          j                    | |j        di           d	<   Y d }	~	d S  ||	          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   )ru   rv   rw    is_streaming_access_denied_errorrx   stream_converse_with_callbacksry   rz   r{   Tu   
⚠  AWS IAM denied bedrock:InvokeModelWithResponseStream — falling back to non-streaming InvokeModel.
   Grant that action to restore streaming output.
u`   bedrock: converse_stream denied by IAM (%s) — using non-streaming converse() for this session.rR   c                P                                       |            dd<   d S )NTr   )_fire_stream_delta)textr]  rC   deltas_were_sents    r   _on_textzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_texty  s3    KMMM,,T222.2$U+++r   c                F                                       |            d S r'   )_fire_tool_gen_started)rF   r]  rC   s    r   _on_toolzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_tool~  s(    KMMM0066666r   c                F                                       |            d S r'   )_fire_reasoning_delta)rd  r]  rC   s    r   _on_reasoningzNinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_reasoning  s(    KMMM//55555r   c                      j         S r'   )r   )rC   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_checkrS   r(   )r   ru   rv   rw   r`  rx   ra  r   converse_streamr   _disable_streaming_safe_printr   r   r   r   r   _has_stream_consumersr  r  )ru   rv   rw   r`  rx   ra  r   rT   r   r   rf  ri  rl  r   r]  rC   rO   re  r   s                 r   _bedrock_callz7interruptible_streaming_api_call.<locals>._bedrock_callL  s   A$                $(<kJJ5t<<<44V<<#96#9#G#GJ#G#GLL     87EE 370))R  
 O ..7  
 .I-H+FO99j99. .z*  10>> :11&9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$sJ   AE A E 
C2#A-C-E C--C22AE 
E EE Tr   r   r   z)Agent interrupted during Bedrock API callrS   rR   )rR   rS   partial_tool_names)rT   diagrU   r   c                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S rW   rX   r[   s    r   r^   z=interruptible_streaming_api_call.<locals>._set_request_client  s      	G 	G.4!(+1:1D1F1F!+.	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G r_   r`   r!   r   ra   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 rc   re   rh   s       r   rk   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Mrl   r   c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S rY  rZ  r[  s   r   _fire_first_deltaz;interruptible_streaming_api_call.<locals>._fire_first_delta  sq     ( 	^ 	(,f%        		 	 	 	r^  c                   	* ddl } t          .j        .j                  }||n!t	          t          j        dd                    }||}nt	          t          j        dd                    }|dk    r?.j        r8t          .j                  r$|}t          
                    d.j        |           n>|dk    r8-6-t	          d          k    r#-|k    r-}t          
                    d	|           |t          |d
          nd}i /dddi|                     ||||          d} ,.                    d|                    }t          j                    1d<   .                    d           .                                }|2d<    |j        j        j        d=i |}.                    t+          |dd                     .                    t+          |dd                     .                    |t+          |dd                     .                    t+          |dd                     g }	i *t3                      }
i }i }d}d}d}g }d}|D ]X}t          j                    1d<   .                    d           	 t5          |                    dd                    dz   |d<   |                    d          1d         |d<   	 t5          |                    dd                    t9          t;          |                    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>tC          |d          r|j        r|j        }tC          |d          r|j"        r|j"        }-|j         d         j#        }tC          |d          r|j        r|j        }t+          |dd          pt+          |dd          }|r4|$                    |            +             .%                    |           |r|j&        r|	$                    |j&                   *s* +             .'                    |j&                   d0d <   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t[          *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.        j0        r |d$         d)xx         |j.        j0        z  cc<   t+          |d*d          }|,tC          |d+          r|j1        pi                     d*          }|)tC          |d,          r|2                                }||d*<   |d$         d(         }|rS||
vrO|
3                    |            +             .4                    |           3d-         $                    |           |j         d         j5        r|j         d         j5        }tC          |d          r|j"        r|j"        }Zd!6                    |	          pd}d}d.}*rg }to          *          D ]}*|         } | d$         d)         }!| d$         d(         pd/}"|!rZ|!8                                rF	 ts          j:        |!           n0# tr          j;        $ r ty          |!|"          }#|#d0k    r|#}!nd}Y nw xY w|$                    t{          | d'         | d1         |                     d*          t{          | d$         d(         |!%          2                     ||	s|s*st}          d3          |o|du }$|$r*fd4to          *          D             }%t          ?                    d5|%           d!6                    |          pd}&t{          ||d|&6          }'t{          d|'t          7          }(t{          t          ||(g||%pd8          S |pd9})|rd:})d!6                    |          pd}&t{          ||||&6          }'t{          d|'|)7          }(t{          d;t          t          jD                              z   ||(g|<          S )>z#Stream a chat completions response.r   NHERMES_API_TIMEOUTg      @HERMES_STREAM_READ_TIMEOUTr   uD   Local provider detected (%s) — stream read timeout raised to %.0fsinfuV   Cloud reasoning stream — read timeout raised to %.0fs to match stale-stream detectorr         >@Tinclude_usage)connectreadwritepool)streamstream_optionsr   chat_completion_stream_requestrp   r   z)waiting for provider response (streaming)ry  rR   rs  receiving stream responsechunksr   first_chunk_atbytesr   usagerw  rv  r   r<   )rG   r  r  )r  r   r  r  r  rF   r  r  rx  r|  rx  F?r  r   )r  r   r  r  zlProvider returned an empty stream with no finish_reason (possible upstream error or malformed SSE response).c                <    g | ]}|         d          d         pdS )r  rF   r  r(   )r)   r6  tool_calls_accs     r   r  zTinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>.<listcomp>  s=         $Z08?C  r   zStream ended with no finish_reason while a tool call's arguments were still incomplete (tools=%s); treating as a mid-tool-call stream drop, not an output-length truncation.rt  ru  rl  rw  indexmessagerj  r  r   choicesr  _dropped_tool_namesstoplengthzstream-)r  r   r  r  r(   )Ehttpxr   r>   r   rH   rJ   rK   r   r   r   r   minTimeoutr   r   r   _stream_diag_initr   r   r   _capture_rate_limitsrB   _capture_credits_stream_diag_capture_response_check_openrouter_cache_statussetr   r5   r"   reprr   r   r  r  r  deltar  rk  ru  rc  r  _record_streamed_assistant_textrl  r  r  r   r  rF   r  rx  r|  addrh  rj  r   sortedr   jsonloadsJSONDecodeErrorr   r   RuntimeErrorr   r   r
   r!   rD  rE  )4_httpx_provider_timeout_cfg_base_timeout_stream_read_timeout	_conn_capstream_kwargsri   _diagr  content_partstool_gen_notified_last_id_at_idx_active_slot_by_idxrj  
model_namert  reasoning_parts	usage_objchunkr  r  tc_deltaraw_idxdelta_idnew_slotr6  entryr  rF   full_contentmock_tool_callshas_truncated_tool_argstcr  r  repaired_tool_args_dropped_no_finish_dropped_namesfull_reasoningmock_messagemock_choiceeffective_finish_reasonr  r}  r^   _stream_stale_timeoutrC   rO   re  last_chunk_timer\   r   s4                                             @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   
 %--)5)U5\\99),@@@ (=$23G   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wvz4@@AAA 	++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"+  	( ( (     !! "# " # "
 G  2 (?'X=TXCX$' 	   !.11  N NNN 	    WW_55=N*$"0	  L *$2  K
 #) $$2$:d    #0"96" 	/&.#119T& &,	
 
 
 & 1
 
 

 3tz||,,, M	
 
 
 	
s\   A	L$ALL$
L L$L  L$$
L10L1"4R
R$#R$\22*]]c            	        d} t          j                     d<                                   }|d<   ddlm}  |t	          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   ry  r   )sanitize_anthropic_kwargsr   r<   )r   rR   Nr  r  r   r  r  r   content_block_startcontent_blocktool_useTrF   content_block_deltar  
text_deltard  r   thinking_deltathinkingr(   )r   r  rC  r  rB   r   r$   r  r  r   r   r   r5   r"   r  r   rh  rc  rk  get_final_message)has_tool_user  r  r  event
event_typeblockr  r  
delta_typerd  thinking_textr}  rC   rO   re  r  r\   s               r   _call_anthropicz9interruptible_streaming_api_call.<locals>._call_anthropicQ  s      $y{{''))(-f%
 	FEEEEE!!75,#C#C	
 	
 	
 	
 5U$-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   ,K.%BK
B!K B!!3KA	E4AE#"E4#
E0-E4/E00E43K4
F>K FD:KKKc                 
  	 dd l } t          dd          }	 t          |dz             D ]}j        rt	          d          	 j        dk    r"                                              d<   n             d<     d           d S # t          $ r"}d	         r?t          	                    d
t          |          j                   Y d }~  d           d S t          || j        | j        | j        f          }t          || j        | j        t$          f          }                    |          }d         rt)                              d                    }d}|sg|seddlm}	 t          ||	          rOt1          |dd           s>t3          |                                          d}
t7          fd|
D                       }|p|p|p|}|o|o||k     }|s2t                              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 }~d}|sg|seddlm}	 t          ||	          rOt1          |dd           s>t3          |                                          d}t7          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 }~!                    d||dz   |dz   d                    d                      "                    |r	d!|dz    d"nd#|dz    d"           nt3          |                                          }d$|v od%|v }d}|sd&|v rdd'l#m$}  ||          }|s|r d_%        &                    |rd(nd)           t          '                    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 retryrs   rR   stream_request_completer   uP   Streaming worker caught %s after request cancellation — exiting without retry.r   rx  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>  s=       ?" ?"(. %+.@$@?" ?" ?" ?" ?" ?"r   z9Streaming failed after partial delivery, not retrying: %srS   u9   

⚠ Connection dropped mid tool-call; reconnecting…

rW  Try  )rS   attemptmax_attemptsmid_tool_callry  stream_mid_tool_retry_cleanup"stream_mid_tool_retry_pool_cleanuprd   c              3      K   | ]}|v V  	d S r'   r(   )r)   r  _err_lower_sses     r   r+   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>Z	  s<       3 3$* !'. 83 3 3 3 3 3r   stream_retry_cleanupstream_retry_pool_cleanup	exhausted)kindrS   r  r  r  ry  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 supportedinvokemodelwithresponsestream)r`  u   
⚠  AWS IAM denied bedrock:InvokeModelWithResponseStream. Switching to non-streaming.
   Grant that action to restore streaming output.
u   
⚠  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   ranger   r   r~   )_try_refresh_anthropic_client_credentialsr   r   r   r   r   r    ReadTimeoutConnectTimeoutPoolTimeoutConnectErrorRemoteProtocolErrorConnectionError_is_provider_stream_parse_errorr9   r5   openair  rB   r!   r   anyr   rc  _reset_stream_delivery_tracking_emit_stream_dropr  _log_stream_retryr   r   r`  rt  ru  r   )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_unsupported_is_bedrock_stream_deniedr`  r  r  r  r  rk   r   rC   re  r\  r\   r   s                      @@r   r   z/interruptible_streaming_api_call.<locals>._call  s]   %&=qAAX	B#()<q)@#A#A O O - T*+RSSSF~)===GGIII-<_->->z**-C-C-E-Ez*P '&'@AAAAAO !    *'2 F GG,  
 p '&'@AAAAAo #-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"FFFFh '&'@AAAAAY!!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,
 # Yl Y6F YJ^ Y +-@@@!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 > /: = / 5:1 6 ?: M M      !A @ C C 6 2 5N 7;E4!-- $=!3 !V !V!3	 	 	 B   '(F7OFFFF '&'@AAAAAO!O`   	 	 	  F7OFFF&&'@AAAAA	aOn '&'@AAAAA&&'@AAAAs  +R> :B?R> R:5R5R> D#R5R> H+*R5+
H85R57H88R5<IR5
IR5IAR5/KR5
KR5KR5R> B7R5N+*R5+
N85R57N88R5;R> C"R5#R> 5R::R> =S4 >
S#SS4 S##S4 4THERMES_STREAM_STALE_TIMEOUTr   r  u>   Local provider detected (%s) — stale stream timeout disabledr   g     r@r   g      n@r  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_cleanuprd   zstale stream detected after zs, reconnectingzLForce-closing streaming httpx client due to interrupt (not a network error).rs   stream_interrupt_abortz+Agent interrupted during streaming API call _current_streamed_assistant_textr<   rx  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: %srs  r  r   r  r  r   )*r   r   r~   rq   _interruptible_api_callrY   r   r   r   r   r   r   r	   r>   r   rH   rJ   rK   r   r   r   r   r8   r   r   r   r   r5   r   r   r  r   r   r   rB   r   r,   r"   rc  r   r   r
   )#rC   rO   rr   rw  r   r   
_cfg_stale_stream_stale_timeout_base_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  rk   r]  r}  r   r^   r  re  r\  r  r\   r]   r   s#   ```                  @@@@@@@@@@@@@@r    interruptible_streaming_api_callr+    sv	     ! NLMMM~***
 '5#	/00<<*.E''$E'.... ~+++"T22#UO!5>	 	 	 	 	 	B	$ B	$ B	$ B	$ B	$ B	$ B	$ B	$ B	$H M$???				jjll 	TFF3F) T&'RSSS jjll 	T '?&/!j!!RHHF'+TMM#.** "5)     N N N N N N N N.  u~ DIKK(O !     t
 t
 t
 t
 t
 t
 t
 t
 t
 t
 t
 t
 t
lX. X. X. X. X. X. X. X. X. X.t]B ]B ]B ]B ]B ]B ]B ]B ]B ]B ]B ]B ]B@	 ,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
**,, H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
 +/w'LL)  >%999+11333335555../GHHH   "#PQQQQ **,, HR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%)P   
PP3AR8 8
SS"V8 8
WW)r   ri  r  r  rP  rU  r+  )r   r   r   r   )r   r9   )rF   r!   rG   rH   r   rH   )rO   r4   )r   r,   r   r4   )rj  r!   r   r4   r'   )r`   r  r   r9   )r$   r,   r  r   r   r!   )rQ  r!   r   ra   )2__doc__
__future__r   r  r  rJ   r  rY   r   rD  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   r   	getLoggerr   r   r   r8   rE   rN   r   ri  r  r  rP  rU  r+  __all__r(   r   r   <module>r8     s~    # " " " " "   				 				       ! ! ! ! ! ! & & & & & & & & & & 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 C C C C C C C C C C		8	$	$  2$ 2$ 2$ 2$j	 	 	 	   j j j j\@ @ @ @Hb b b bL@. @. @. @. @.Hb b b bLQ Q Q Q@ QU M M M M M Mf"  r   