
    YjN                      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 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&m'Z'  ej(        e)          Z*h dZ+dZ,d Z-dGdZ.dHdZ/dIdZ0dJdZ1dKd Z2dLd$Z3dMd%Z4dNd'Z5dNd(Z6dNd)Z7dOd,Z8dHd-Z9dOd.Z:dOd/Z;dPd2Z<dQd4Z=dRd7Z>dSd:Z?dTd;Z@dUdVd>ZAdWdAZBdXdCZCddDdOdEZDg dFZEdS )Yuu  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)EmptyStreamError)is_native_gemini_base_url)is_local_endpoint)_sanitize_surrogates_repair_tool_call_arguments)is_persistent_env)base_url_host_matchesbase_url_hostname	env_floatenv_int>   pricelatency
throughputg      @c                     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    RC:\Users\server\AppData\Local\hermes\hermes-agent\agent\chat_completion_helpers.py_rar   8   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>._charsT   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>^   s+      55D66$<<555555r   )r'   listsum)r+   r*   s    r   _message_charsz7estimate_request_context_tokens.<locals>._message_chars[   sH    (D)) 	$6(###5555H555555r      toolsinputinstructionsc              3  .   K   | ]} |          V  d S r.   r/   )r0   r$   r*   s     r   r2   z2estimate_request_context_tokens.<locals>.<genexpr>s   s+      CCU66%==CCCCCCr   )r$   r   r!   r"   )r+   r   r!   r"   )r'   r3   dictgetr4   values)r    r5   r+   total_charsr*   s       @r   estimate_request_context_tokensr?   C   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_backendrL   x   st    (92>>D"EENGE+?DDJKKz4((N: 	
. 7$6	r   
est_tokensfloatc                6    | dk    rdS | dk    rdS | dk    rdS dS )u  Minimum wall-clock stale timeout for openai-codex by estimated context.

    Gateway/Telegram sessions routinely ship ~15–25k tokens of tools +
    instructions before the first user message. Subscription-backed Codex can
    legitimately spend several minutes in backend admission/prefill at that
    size; the generic 90s non-stream stale default aborts healthy calls. The
    floor engages above 10k estimated tokens so those gateway-scale payloads
    are covered; smaller requests keep the generic default.
    順 g     @P  g      @'  g     @        r/   )rM   s    r    openai_codex_stale_timeout_floorrT      s9     GvFuFu3r   raw_sortOptional[str]c           	         t          | t                    sdS |                                                                 }|sdS |t          v r|S t
                              d| d                    t          t                                         dS )z;Return a normalized OpenRouter provider.sort value or None.Nz@Ignoring invalid OpenRouter provider.sort value %r (allowed: %s), )	r'   r(   striplower _OPENROUTER_PROVIDER_SORT_VALUESloggerwarningjoinsorted)rU   
sort_values     r   #_validated_openrouter_provider_sortra      s    h$$ t!!''))J t555
NNJ		&9::;;  
 4r   Dict[str, Any]c                    i }| j         r
| j         |d<   | j        r
| j        |d<   | j        r
| j        |d<   t          | j                  }|r||d<   | j        rd|d<   | j        r
| j        |d<   |S )zDBuild the validated provider-routing object shared by request paths.onlyignoreordersortTrequire_parametersdata_collection)providers_allowedproviders_ignoredproviders_orderra   provider_sortprovider_require_parametersprovider_data_collection)rJ   preferencesrm   s      r   _provider_preferences_for_agentrq      s    "$K 6#5F 8 % 7H 5$4G78KLLM ,+F( 1,0()% H).)G%&r   namer(   defaultc                    	 t          t          j        | t          |                              S # t          t
          f$ r |cY S w xY wr.   )rN   osgetenvr(   	TypeError
ValueError)rr   rs   s     r   
_env_floatry      sP    RYtS\\22333z"   s   .1 AAc                f    	 t          t          | dd          pd          S # t          $ r Y dS w xY w)N_consecutive_stale_streamsr   )r"   rI   	ExceptionrJ   s    r   _stale_streakr~      sI    75">BBGaHHH   qqs   " 
00Nonec                X    	 t          |           dz   | _        d S # t          $ r Y d S w xY w)N   )r~   r{   r|   r}   s    r   _bump_stale_streakr      sD    +8+?+?!+C(((   s    
))c                8    	 d| _         d S # t          $ r Y d S w xY wr&   )r{   r|   r}   s    r   _reset_stale_streakr      s7    +,(((   s    
c                    t          dd          }t          |           }|dk    r||k    rt          d| d          dS dS )u   Raise immediately when the consecutive-stale streak is past the
    give-up threshold — no network attempt, no stale-timeout wait.HERMES_STREAM_STALE_GIVEUP   r   z:Provider has been unresponsive (no response received) for u    consecutive stale attempts — aborting this call to avoid an indefinite stall. Switch models or start a new session, then retry.N)r   r~   RuntimeError)rJ   _giveup_streaks      r   _check_stale_giveupr      sj     2A66GE""G{{w'))## # #
 
 	
 {))r   
api_kwargsr;   c          	     p   | j         dk    r2 |d          }|                     ||t          | dd                    S | j         dk    r|                     |          S | 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 ||
          S | j        dk    r | j        j        j        j        di |S  |d          } |j        j        j        di |S )u2  Run one non-streaming LLM request for the active api_mode and return it.

    Shared by the interrupt-worker path (``interruptible_api_call``) and the
    inline path (``direct_api_call``) so the per-api_mode dispatch — codex /
    anthropic / bedrock / MoA / OpenAI-compatible — lives in exactly one place.

    ``make_client(reason)`` builds the per-request OpenAI client for the codex
    and OpenAI-compatible branches; the worker path uses it to register the
    client with its stranger-thread abort machinery, the inline path uses it to
    capture the client for its own ``finally`` close. The anthropic / bedrock /
    MoA branches manage their own clients and never call it. All interrupt,
    abort, cancellation, and close semantics stay in the callers — this helper
    only issues the request.
    codex_responsescodex_stream_request_codex_on_first_deltaN)clienton_first_delta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__moachat_completion_requestr/   )api_mode_run_codex_streamrI   _anthropic_messages_createagent.bedrock_adapterr   r   r   r   popconverser|   rE   r   chatcompletionscreate)rJ   r   make_clientrequest_clientr   r   r   r   regionr   raw_response_bedrock_excs               r   "_dispatch_nonstreaming_api_requestr      s    ~***$%;<<&&!"5*A4HH ' 
 
 	

 ~---//
;;;~+++
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
  4kBB-t444,,V44	*6?88Z88LL 	 	 	 )(66 2))&111	 +*<888~ 4u| ,3AAjAAA [!:;;N1>*1??J???s   -B; ;
C!CC!c                    t          | dd          dk    o)t          | dd          dk    ot          | dd          dk    S )a  Whether a cron OpenAI-wire request should skip the interrupt worker.

    Issue #62151 is specific to OpenRouter's chat-completions path inside the
    gateway cron thread stack. Keep native/Codex/Bedrock/MoA transports on their
    established workers: their cancellation and client ownership differ, and
    the report provides no evidence that those paths share the pre-HTTP wedge.
    platformNcronr   chat_completionsrE   r   )rI   r}   s    r   should_use_direct_api_callr   (  sP     	z4((F2 	6E:t,,0BB	6E:t,,5r   c                    t                                           d           ddit          j                    d fdd fd	}	 t	           |
          }t           dd          rt          d          t                      |t           dd          u rd _        5  d         }dd<   ddd           n# 1 swxY w Y   | 	                    |d           S S # t          $ r# t           dd          rt          d          d w xY w# t           dd          u rd _        5  d         }dd<   ddd           n# 1 swxY w Y   | 	                    |d           w w xY w)u.  Run a non-streaming LLM call inline on the conversation thread.

    Used when ``should_use_direct_api_call`` is True. Skips the interrupt worker
    (whose only job is interactive-interrupt responsiveness, which this context
    does not have) so the nested-pool deadlock (#62151) cannot occur. Because the
    request runs in-flight normally, the per-request OpenAI client's own httpx
    timeout (provider ``request_timeout_seconds`` / ``HERMES_API_TIMEOUT``) bounds
    a genuinely hung provider — the same bound interactive calls already rely on.
    &waiting for non-streaming API responser   Nreasonr(   r!   r   c                    5  d         }ddd           n# 1 swxY w Y   |                     ||            dS dS )z?Abort the inline request from cron's watchdog/interrupt thread.r   Nr   )_abort_request_openai_client)r   r   rJ   request_client_holderrequest_client_locks     r   _abort_active_requestz.direct_api_call.<locals>._abort_active_requestF  s      	= 	=28<N	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	=%..~f.MMMMM &%s   	c                                         |           }5  |d<   d d d            n# 1 swxY w Y   _        |S )Nr   r   r   )_create_request_openai_client_active_request_abort)r   r   r   rJ   r   r   r   s     r   _make_clientz%direct_api_call.<locals>._make_clientM  s    44Fz4ZZ  	5 	5.4!(+	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5 	5&;#s   -11r   _interrupt_requestedF!Agent interrupted during API callr   request_completer   r   r(   r!   r   )r   r(   )r   _touch_activity	threadingLockr   rI   InterruptedErrorr   r   _close_request_openai_clientr|   )rJ   r   r   responser   r   r   r   s   ``   @@@r   direct_api_callr   7  s    	BCCC%t,#.**N N N N N N N N         Z5:<
 
 
 50%88 	H"#FGGGE"""51488<QQQ*.E'  	3 	328<N.2!(+	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 %..~FX.YYYY &    50%88 	R"#FGGTQ 51488<QQQ*.E'  	3 	328<N.2!(+	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 %..~FX.YYYY &sT   C2 &0D" 2CC	C	2-DD" "E??EE?EE? E!E?c           
         ! t                     rt                     S ddd!t                      dddt          j                     ddi fddY  fd !fd}                               } j        dk    }t                     }t                    }|r#|r!t          |          }|rt          ||          }t          dd          }|r|r|dk    rt          ||          }|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 }|s6|dk    r0||k    r*|	}||k     r"t$                              d|||d|           |}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    rt-          j                    |z
  }|}|
r!t9           d*d          t          ||          }                     d+                    d,d-           d.t=          |           d/t=          |           d0           t-          j                    |z
  }|
r||k    rt9           d*d          d}t9           d1d          }t?          |          r3	  |                    d,          2          }n# t@          $ r d}Y nw xY wt$          !                    d3||                    d,d4                     |r@ "                    d5t=          |           d6                    d,d4           d7|            n= "                    d5t=          |           d6                    d,d4           d8           	  d9           n# t@          $ r Y nw xY w                     d:t=          |           d;                                d<t=          |           d=           |                    d>'           !d?         s!d@         k|r6tG          dAt=          |           dBt=          |           dC|           !d?<   n3tG          dAt=          |           dBt=          |           d0          !d?<   n2t9           d*d          }|rC|@t-          j                    |z
  |k    r%t-          j                    |z
  }t$          !                    dD||                    d,d4          |d            "                    dEt=          |           dF                    d,d4           d8           	  dG           n# t@          $ r Y nw xY w                     d<t=          |           dH           |                    d>'           !d?         ;!d@         3tG          dIt=          |           dJt=          |           d0          !d?<   n||k    r4t                    }d}t9           d1d          }t?          |          r3	  |                    d,          2          }n# t@          $ r d}Y nw xY wt$          !                    dK||                    d,d4          |d           |r@ "                    dLt=          |           dM                    d,d4           dN|            n= "                    dLt=          |           dM                    d,d4           dO           	  j        dPk    r. j$        %                                  &                                 n dQ           n# t@          $ r Y nw xY wtO                                           dRt=          |           dS           |                    d>'           !d?         s!d@         k|r6tG          dTt=          |           dUt=          |           dC|           !d?<   n3tG          dTt=          |           dUt=          |           d0          !d?<   n j(        rd$d<   t$          )                    dV           	  j        dPk    r. j$        %                                  &                                 n dW           n# t@          $ r Y nw xY wtU          dX          |                                !d?         !d?         !d@         tW                      !d@         S )Za=  
    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r   error)r   	owner_tidr$   Fc                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S Nr   r   r   	get_identr   r   r   s    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r   r(   r!   r   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 Nr   r   r   r<   r   r   r   r   r   r   r   stranger_threadrJ   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                 :   	 t          fd          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)Nc                D                          |                     S )Nr   )r   )r   r   rJ   r   s    r   <lambda>z7interruptible_api_call.<locals>._call.<locals>.<lambda>  s2    +>+>77%* 8  , , r   r   r   r$   uh   Non-streaming worker caught %s after request cancellation — exiting without surfacing a network error.r   r   )r   r|   r\   debugtype__name__)er   _request_cancelledr   rJ   r   results    r   _callz%interruptible_api_call.<locals>._call  s   	;
 "D     " " "F:  	  	  	 
 "'* AGG$  
  '&'9:::::  F7OOOOOO	  '&'9:::::&&'9::::s7    B 
A=5A8B .A83B 8A==B Br   !HERMES_CODEX_HARD_TIMEOUT_SECONDSg     p@r   rP        f@rQ         ^@rR         N@g      (@!HERMES_CODEX_TTFB_TIMEOUT_SECONDS&HERMES_CODEX_TTFB_DISABLE_ABOVE_TOKENSg     @HERMES_CODEX_TTFB_STRICTrC   >   1onyestruezScaling openai-codex no-byte TTFB watchdog from %.0fs to %.0fs for large request (context=~%s tokens >= %.0f). Set HERMES_CODEX_TTFB_STRICT=1 to keep the smaller cutoff.,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_SECONDSr   Ttargetdaemon333333?timeoutr   d   _codex_stream_last_event_ts   ⏳ waiting on modelthe provider    — zNs with no response yet (provider may be slow or overloaded; auto-reconnect at zs)_codex_silent_hang_hint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_killu!   ⚠ no response from provider in    s — reconnecting...zcodex stream killed after zs with no first byteg       @r   r   z&Codex stream produced no bytes within zs (TTFB threshold: 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.r   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_abortr   r   ),r   r   r   r   r   !_compute_non_stream_stale_timeoutr   rL   r?   rT   maxry   minru   environr<   rY   rZ   r\   infor   _codex_stream_last_progress_tstimer   Threadstartis_aliver^   rI   _emit_wait_noticer"   callabler|   r]   _buffer_statusTimeoutError_anthropic_clientclose_rebuild_anthropic_clientr   r   r   r   r   )"rJ   r   r   _stale_timeout_codex_watchdog_enabled_openai_codex_backend_est_tokens_for_codex_watchdog_codex_floor_codex_hard_timeout_codex_idle_timeout_default_ttfb_enabled_ttfb_timeout_ttfb_disable_above_ttfb_strict_large_request_ttfb_timeout	_ttfb_cap_codex_idle_enabled_codex_idle_timeout_call_startt_poll_count_elapsed	_deadline_silent_hint_hint_fn_last_codex_event_ts_event_stale_elapsed_est_ctxr   r   r   r   r   r   s"   ``                          @@@@@@r   interruptible_api_callr6  k  sh   " "%(( 2uj111..F '+$??#.** "5)     N N N N N N N N@; ; ; ; ; ; ; ; ; ;J <<ZHHN$ $n0AA4U;;%DZ%P%P" ?#8 ?78VWW 	? >>N" %%H&QQB!B  !##^-@AA%//&+##	'&	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*E':::Q "/599'   !<>FF	q==]Y66KKS155   &M1$2#  a# 4 -1)/3,)++K	BCCCd333AGGIIIK
**,, MH	sq !!y{{[0H&I:E#@$GGO	=99	##G*..."I"I G Gx==G G47	NNG G G   9;;, 7	=((<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% % %  
**+<====   ###CMM # # #   !!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    u%%%!!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G[ **,, MH\ g"Wo j%E"""*sn   N6 6OO9R 
RR.X: :
YY\$ $\32\3*A`/ /
`<;`<-Ae2 2
e?>e?api_messagesr3   c                z  * | 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tO          |           }!d}"	 dd*l(m)}#m*}$ | j        pd#                                +                    d+d,          *tY          *fd-|$D                       r |#| j                  }"n# t6          $ r Y nw xY wd}%|r*| j-        pd.t]          t_          j0                              d/}%	 dd0l1m2}&  |&| j                  }'n# t6          $ r d}'Y nw xY w|'rt	          | dd          }(|(d| _        |                     |          }|
                    | j        ||| j        |                                 | j	        |(| j3        | j
        | j        t	          | dd          |'| j4        |!pd| j5        |"| 6                                |%1          S t	          | dd          }(|(d| _        |                     |          }) |
j        dTi d2| j        d3|)d4|d5| j        d6|                                 d7| j	        d8|(d9| j3        d:| j
        d;| j        dt	          | dd          d<| j        pd#                                d=|d>|d?|d@|dA|dB|dC|dD|dE| j        dFk    dG| j4        dH|!pddI| j5        dJ|r| j7        nddK|r| j8        nddL|%dM| dN|dO| 6                                dP|r|                                 nddQ|r| 9                                nddR|"dS| j        S )Uz9Build the keyword arguments dict for the active API mode.r   context_compressorN_ephemeral_max_output_tokens_anthropic_base_urlspeedfast_oauth_1m_beta_disabledF)r   r+   r7   
max_tokensreasoning_configis_oauthpreserve_dotscontext_lengthbase_url	fast_modedrop_context_1m_betar   _bedrock_regionr   _bedrock_guardrail_configi   )r   r+   r7   r?  r   guardrail_configr   zmodels.github.aizgithubcopilot.comrF   rG   rH   >   	xai-oauthxaizapi.x.air   )strip_pattern_and_formatstrip_slash_enumu4   %s⚠️ Failed to sanitize tool schemas for xAI: %s
log_prefixrC   
session_id_codex_reasoning_replay_enabledT)r   r+   r7   r@  rO  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)_get_anthropic_max_output_ANTHROPIC_OUTPUT_LIMITS.-c              3      K   | ]}|v V  	d S r.   r/   )r0   key_model_norms     r   r2   z#build_api_kwargs.<locals>.<genexpr>  s(      FFcsk!FFFFFFr   hermes)	sessionIdpromptIdget_provider_profile)r   r+   r7   rD  r   r?  ephemeral_max_output_tokensmax_tokens_param_fnr@  rQ  rO  provider_profileollama_num_ctxprovider_preferencesopenrouter_min_coding_scoreanthropic_max_outputsupports_reasoningqwen_session_metadatar   r+   r7   rD  r   r?  rh  ri  r@  rQ  model_loweris_openrouteris_nousis_qwen_portalis_github_modelsis_nvidia_nimis_kimiis_tokenhubis_lmstudiois_custom_providercustomrk  rl  rm  qwen_prepare_fnqwen_prepare_inplace_fnrp  fixed_temperatureomit_temperaturero  rU  lmstudio_reasoning_optionsrn  provider_namer/   ):r7   r   _get_transport#_prepare_anthropic_messages_for_apirI   rC  r:  build_kwargsr   r?  r@  _is_anthropic_oauth_anthropic_preserve_dotsrQ  r<   r@   r   rD  rE   rD   rB   &_prepare_messages_for_non_vision_modelcopytools.schema_sanitizerrL  rM  deepcopyr|   r\   r]   _resolved_api_call_timeout#_github_models_reasoning_extra_body_is_qwen_portal_is_openrouter_urlrY   rZ   agent.auxiliary_clientrZ  r[  rq   agent.anthropic_adapterr\  r]  replaceanyrO  r(   uuiduuid4	providersrg  _max_tokens_param_ollama_num_ctxrm  _supports_reasoning_extra_body_qwen_prepare_chat_messages#_qwen_prepare_chat_messages_inplace"_lmstudio_reasoning_options_cached)+rJ   r7  tools_for_api
_transportr   ctx_lenephemeral_out_btr   	guardrail_ctrR  rS  rT  _msgs_for_codex_copyrL  rM  _exc_is_qwen_is_or_is_gh_is_nous
_is_nvidia_is_kimi_is_tokenhub_is_lmstudiorZ  r[  _ft
_omit_temp_fixed_temp_prefs_ant_maxr\  r]  
_qwen_metarg  _profile_ephemeral_out_msgs_for_chatrb  s+                                             @r   build_api_kwargsr  3  s	   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 J$U^5HII 	
 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 	M !68KLL  !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   

 -U33F H		
 	
 	
 	
 	
 	
 	
 	
 {(b//1199#sCCFFFF-EFFFFF 	>00==H    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# #sO   =I 
J+I==J(P5 5QQA"R> >
S
S=T T#"T#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<   |rCg }|D ]8}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/          |!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_callsNrC   z<think>(.*?)</think>flags

c              3  f   K   | ],}|                                 |                                 V  -d S r.   )rY   )r0   bs     r   r2   z*build_assistant_message.<locals>.<genexpr>H  s7      "P"Paggii"P17799"P"P"P"P"P"Pr   zCaptured reasoning (z	 chars): r   )redact_sensitive_text	assistant)rolecontent	reasoningr  reasoning_contentmodel_extra reasoning_details__dict__
model_dumpanthropic_content_blockscodex_reasoning_itemscodex_message_itemsidcall_idfunctionrr   	arguments{}response_item_idrr   r  )r  r  r  r   r  extra_content)%rI   _extract_reasoningr@   r  refindallDOTALLr^   verbose_loggingloggingr   r)   reasoning_callbackstream_delta_callback_stream_callbackr|   r   r'   r(   _strip_think_blocksrY   agent.redactr  hasattrr;   _needs_thinking_reasoning_padr  appendr  r  _split_responses_tool_id_deterministic_call_id"_derive_responses_function_call_idr   r  rr   r  )"rJ   assistant_messager  assistant_tool_callsreasoning_text_from_structuredr  think_blockscombined_raw_content_san_contentr  msgraw_reasoning_contentr  raw_details	preserveddordered_blockscodex_itemsr  r  	tool_callraw_idr  embedded_call_idr  _fn_fn_name_fn_argsr  embedded_response_item_idtc_dictextras"                                     r   build_assistant_messager   7  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!" @'
- =	' =	'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< I==E 5,// /!,,..E+0(g&&&&&LJs   C% %
C21C2r   rE   c                h   t          | dd          }t          |t                    r|sdS d|fd|ffD ]w\  }}|st          t	          j        d| d|                    }|rG|d         }|d|                                          | d| ||                                d          }x|| _        dS )	u-  Point the cached system prompt's ``Model:``/``Provider:`` lines at
    the active runtime after a provider switch.

    The system prompt is session-stable and replayed verbatim for prefix-cache
    warmth, but after a failover the new backend's cache is cold anyway —
    while a stale identity line makes the agent misreport which model it is
    when asked.  Rewrite the lines in place WITHOUT persisting to the session
    DB: the stored row keeps the primary's labels, so when the primary is
    restored the prompt is byte-identical to the stored copy again and its
    prefix cache still matches.

    Only the LAST occurrence of each line is touched — the identity lines
    live in the volatile tail of the prompt, and earlier matches could be
    user content (memory snapshots, context files).
    _cached_system_promptNModelProviderz(?m)^z: .*$: )	rI   r'   r(   r3   r  finditerr  endr  )rJ   r   rE   splabelr$   matcheslasts           r   rewrite_prompt_model_identityr  "  s      
/	6	6Bb# b !5)J+AB I Iu 	r{#8E#8#8#8"==>> 	I2;D}

}%HuHHHr$((**++HHB"$Er   fbtuple[str, str, str]c                   t          |                     d          pd                                                                          t          |                     d          pd                                          t          |                     d          pd                                                              d          fS )NrE   rC   r   rD  /)r(   r<   rY   rZ   rstrip)r  s    r   _fallback_entry_keyr  ?  s    BFF:$"%%++--3355BFF7OO!r""((**BFF:$"%%++--44S99 r   c                J   |                     d          pd                                                                }|dk    rdS 	 ddlm}  |d          pi }n.# t
          $ r!}dt          |          j         cY d}~S d}~ww xY w|                     d          }|                     d	          }t          |t                    o t          |                                          }t          |t                    o t          |                                          }	|s|	sd
S dS )zGReturn a skip reason for fallback entries known to be unusable locally.rE   rC   nousNr   )get_provider_auth_stateznous_auth_unreadable:access_tokenrefresh_tokennous_token_missing)r<   rY   rZ   hermes_cli.authr  r|   r   r   r'   r(   r@   )
rJ   r  fb_providerr  stater  access_valuerefresh_value
has_accesshas_refreshs
             r   +_fallback_entry_unavailable_without_networkr!  G  s?   66*%%+2244::<<Kft<;;;;;;''//52 < < <;tCyy'9;;;;;;;;<99^,,LIIo..ML#..M48J8J8L8L3M3MJ]C00PT-:M:M:O:O5P5PK $+ $##4s   A 
B#A?9B?Br   'FailoverReason | None'c                ^   |t           j        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    rt          | j                  dk    rf|t           j        t           j        t           j        hvrAt          | dd          pd}t!          |t          j                    t"          z             | _        dS | j        | j                 }| xj        dz  c_        t%          |          }t          | d	d
          }|t'                      }|| _        ||v r0t*                              d|           |                     |          S |	                    d          pd                                                                }	|	                    d          pd                                }
|	r|
s|                     |          S t1          | |          }|rG|                    |           t*                              d|	|
|           |                     |          S t          | dd          pd                                                                }t          | dd          pd                                }t7          t          | dd          pd                              d                                          }|	                    d          pd                                                    d                                          }|	|k    r7|
|k    r1t*                              d|	|
           |                     |          S |r>|r<||k    r6|
|k    r0t*                              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(tC          |d          r|st?          j         d          pd
} ||	|
d||          \  }}|Et*                              d|	           |                    |           |                     |          S 	 ddl"m#}  ||
|	          }
n4# tH          $ r'}t*                              d|
|	|           Y d
}~nd
}~ww xY wd}t7          |j%                  }| &                    |          }|	dk    rd}n|	d k    sM|                    d                                          '                    d!          stQ          |          d"k    rd#}nq|rd}nl| )                    |          rd}nT| *                    |
|	$          rd}n:|	d%k    s2tQ          |          +                    d&          rtC          |d'          rd(}| j,        }| j-        }d
| _.        |
| _,        |	| _-        || _%        || _/        ta          | d)          r| j1        2                                 d| _3        t          | d*d
          }|ct          |dd          pd                                                                }|r*||	k    r$t*          4                    d+|	|
|           d
| _5        t          | d*d
          	 dd,l6m7}  ||	          }|r7|8                                r#|| _5        t*          4                    d-|	|
           n4# tH          $ r'} t*                              d.|	|
|            Y d
} ~ nd
} ~ ww xY wts          |	|
          }!|d#k    rdd/l:m;}"m<}#m=}$ |	d k    r|j>        p |#            pdn|j>        pd}%|%| _>        |%| _?        || _@         |"|%| j@        |!0          | _A        |	d k    r |$|%          nd| _B        d
| _C        i | _D        n}|j>        | _>        || _C        t          |d1d
          }&|&st          |d2d
          }&|j>        |d3|&rd2t          |&          ini | _D        |! |!| jD        d4<   | F                    d56           | G                    |	|||
7          \  | _H        | _I        | J                                 ta          | d8          r| jK        rdd9lLmM}' t          | j>        t6                    r| j>        nd}( |'| j,        | j%        |(| j-        t          | d:d
          t          | d;d
          <          })| jK        O                    | j,        |)| j%        t          | dd          | j-        | j/        =           	 dd>lPmQ}* dd?lRmS}+  |+ |*            pi | j,                  | _T        t*          4                    d@| j,        | jT                   n8# tH          $ r+},t*                              dA| j,        |,           Y d
},~,nd
},~,ww xY wt          | |
|	           | V                    dB|
 dC|	            dD| dC| dE|
 dC|	 | _W        t*          4                    dF||
|	           t          |            dS # tH          $ rV}-|	dGk    r|                    |           t*          Y                    dH|
|-           |                     |          cY d
}-~-S d
}-~-ww xY w)Iu  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_activatedFrE   rC   <   r   _rate_limited_untilr   _unavailable_fallback_keysNz/Fallback skip: %s previously marked unavailabler   zMFallback skip: %s/%s is not locally usable (%s); suppressing for this sessionrD  r  z?Fallback skip: chain entry %s/%s matches current provider/modelz>Fallback skip: chain entry base_url %s matches current backend)resolve_provider_client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: %sr   rF   r   	anthropicz
/anthropiczapi.anthropic.comr   )rE   bedrockzbedrock-runtime.zamazonaws.comr   _transport_cache_credential_poolznFallback to %s/%s: clearing primary credential pool (pool_provider=%s) to prevent cross-provider contamination)	load_poolz4Fallback to %s/%s: attached fallback credential poolz7Fallback to %s/%s: could not attach credential pool: %s)build_anthropic_clientresolve_anthropic_token_is_oauth_tokenr   _custom_headersdefault_headers)r)  rD  r   fallback_timeout_applyr   )rE   rD  r   r   r9  )get_model_context_length_config_context_length_custom_providers)rD  r)  rE   config_context_lengthcustom_providers)r   rC  rD  r)  rE   r   )load_config)resolve_reasoning_configz*Fallback %s: reasoning_config resolved: %szGFailed to resolve reasoning_config for fallback %s; keeping current: %su5   🔄 Primary model failed — switching to fallback: z via u!   🔄 Switched to fallback model: u    → u"   Fallback activated: %s → %s (%s)r  z"Failed to activate fallback %s: %s)Zr   
rate_limitbillingupstream_rate_limitr@   rI   rY   rZ   _primary_runtimer<   r  	monotonicr&  _fallback_indexr)   _fallback_chainr  _FALLBACK_EXHAUSTED_COOLDOWN_Sr  setr'  r\   r   _try_activate_fallbackr!  addr]   r(   r  r  r(  ru   rv   r   hermes_cli.model_normalizer0  r|   rD  _is_azure_openai_urlendswithr   _is_direct_openai_url&_provider_model_requires_responses_api
startswithr   rE   r=  r   r  r3  clearr$  r  r4  agent.credential_poolr5  has_credentialsr   r  r6  r7  r8  r)  _anthropic_api_keyr;  r  r  r   _client_kwargsr;   _replace_primary_openai_client_anthropic_prompt_cache_policy_use_prompt_caching_use_native_cache_layout_ensure_lmstudio_runtime_loadedr9  agent.model_metadatar<  r'   update_modelhermes_cli.configrA  hermes_constantsrB  r@  r  r  _pending_fallback_noticer   r   ).rJ   r   fallback_already_activecurrent_providerprimary_provider_existing_cooldownr  fb_keyunavailabler  fb_modellocal_skip_reason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_modelr0  	_norm_errfb_api_modefb_base_url_fb_is_azure	old_modelold_provider_existing_pool_pool_providerr5  fallback_poolr  _fb_timeoutr6  r7  r8  effective_key
fb_headersr<  _fb_ctx_api_keyfb_context_lengthrA  rB  _reasoning_errr   s.                                                 r   try_activate_fallbackr  \  s    .+^-C^Eghhh #'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 : ::: %&&**~8.:PR`Rtuuu!(0Eq!I!I!NQ(+"  #AA) )E% u		u4	5B	Q $$F%!=tDDKee+6(FOOO++F33366*%%+2244::<<Kw%2,,..H 4h 4++F333CE2NN 4[		
 	
 	
 ++F333  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	
 	
 	
 ++F333
4
4 "%555%%L!	
 	
 	
 ++F333
M4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@   OOF###//777	OOOOOO33HkJJHH 	 	 	NNK+y       	 )),--11+>>.((+KK;&&!!#&&,,..77EE ' --1DDD /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>  
 *.&5,d33;;;;;;; )	+ 6 6  ]%B%B%D%D -:E*KKN#X      M3        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   	555555AAAAAA%=%=#U[& &E" KK<U3     	 	 	LLY^       	 	&eX{CCC,, ,), ,	
 	
 	
0	 0 0 0 00 0"-0 0 	& 	0x	
 	
 	
 	E"""t 4 4 4&  OOF###98QGGG++F33333333	4s   E
m V. -m .
W8Wm WG&m A
` m 
a`=8m =aHm Aj' &m '
k1!km kA.m 
n,An'!n,'n,r+   api_call_countc           
     n   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<   tO          |           }i } 	 ddl(m)}!  |!| j                  }"|":|"*                    tW          | dd          |pd| j        | j        | j                   } n# t(          $ r Y nw xY w| r|%                    |            |rNd!| v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| !                                }$|$1                    | j        |d| j$        | j        | j2        | 3                                +          }%| 4                    |%          }|$"                    || j2        ,          }&|&j#        pd                                }nm | 5                    d-.          j6        j7        j8        d9i |}| !                                "                    |          }&|&j#        pd                                }|rXd/|v r4ts          j:        d0d|tr          j;        1                                          }|r|                    d2|d           n]d3}nY| j        dk    r|                     |          }|                    dd           |                      |          }'| !                                }(|("                    |'          })|)j#        pd                                }nn| j        d*k    r| !                                }*|*1                    | j        |d| j2        | j$        | j        | 3                                4          }+| 4                    |+          }'|*"                    |'| j2        ,          },|,j#        pd                                }n| j        |d}|||d<   | j$        -|%                    | &                    | j$                             |||d<   |r||d)<    | 5                    d5.          j6        j7        j8        d9i |}| !                                "                    |          },|,j#        pd                                }|rVd/|v r4ts          j:        d0d|tr          j;        1                                          }|r|                    d2|d           nd3}nd3}nN# t(          $ rA}-tx          =                    d6|-            d7| j         d8t}          |-           }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)r  r  )r  r  _thinking_prefillN)	tool_namer  r  	timestampc                f    g | ].}t          |t                    |                    d           ,|/S )r  )r'   r(   rS  )r0   ks     r   
<listcomp>z)handle_max_iterations.<locals>.<listcomp>  s9     ` ` `qz!S7I7I `all[^N_N_ ` ` ` `r   r  rC   r  systemr   r   rY  rW  rX  r  Tmedium)enabledeffort)nous_portal_tagstagsr   r7   )r   r+   temperaturereasoning_effortrf  rO  )rO  rl  r   rD  r@  rE   
openrouterzopenrouter/pareto-coderS   g      ?zpareto-router)r  min_coding_scoreplugins
extra_bodyr   )r   r+   r7   r?  r@  rA  rB  )strip_tool_prefixiteration_limit_summaryr   z<think>z<think>.*?</think>\s*r  r  z>I reached the iteration limit and couldn't generate a summary.)r   r+   r7   rA  r?  r@  rB  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_callsr  _copy_reasoning_content_for_apir   #_sanitize_tool_calls_for_strict_apir   r  ephemeral_system_promptrY   prefill_messages	enumerateinsert_sanitize_api_messages#_drop_thinking_only_and_merge_usersr  rZ  r[  r|   rD  rB   rE   rZ   r  *_resolve_lmstudio_summary_reasoning_effortr@  agent.portal_tagsr  r   _build_api_kwargsr   r  normalize_responser  r?  updater  rq   r  rg  build_extra_bodyrI   r  rm  rN   rw   rx   r  r  r  r   _ensure_primary_openai_clientr   r   r   r  subr  r\   r]   r(   ).rJ   r+   r  summary_request_needs_sanitizer7  r  api_msginternal_fieldschema_foreigninternal_keyeffective_system
sys_offsetidxpfmsummary_extra_bodyrZ  
_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_kwargsrl  profile_extra_bodyrg  rj  _ps_tsum_ant_kw_summary_resultretry_response	_ct_retry
_cnr_retry_tretry_ant_kw2_retry_resultr   s.                                                 r   handle_max_iterationsr    s   	
_1E
_
_
_```	* 
 OOV@@AAAb~  ;;== 	) 	)ChhjjG11#w???"U 2 2ND1111 #m 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 $C5#I#I !#::::::#7#7#G#G #/)9)J)J#*5,#E#E-A-IT#k!&).)? *K * *&     " >"))*<===# F
:L(L(L%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{}}~ s   Fc'  G	 c' 	Gc' GG c' AO. -c' .
O;8c' :O;;Cc' S c' S30c' 2S33O3c' '
d217d--d2task_idc                   	 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 r  Nz#Failed to cleanup browser for task )
r   r  r  r   r   
cleanup_vmr|   r\   r]   cleanup_browser)rJ   r  r   s      r   cleanup_task_resourcesr    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)r   c               \    !"#$%&'()*  j         rt          d          t                     r                               S  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          |	                                @ j         rt          d          *d         *d         *d         S ddg d*t                      dddd(t          j                    )ddi"()fd#d[ ()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#          d!d"          }|d"k    rK j        rDt'           j                  r0t)          d#          $t*                              d$ j                   nut/                    }|d%k    rt1          |d&          $n|d'k    rt1          |d(          $n|$d)d*lm}	  |	                    d+                    }
|
t1          $|
          $t          j        |d          }|                                 t          j                    }d,}|	                                r|
                    d           t          j                    }||z
  |k    r|}t9          |'d         z
            }||k    r_$'$t)          d#          k    rd-t9          $           d.}nd/}                     d0                    d+d1           d2| d3| d4           n                     d5| d6           t          j                    'd         z
  }|$k    rt/                    }t*                              d7|$                    d+d8          |d9                                 d:t9          |           d;                    d+d8           d<|d9d=           	  d>           n# tB          $ r Y nw xY wtE                       j        d?k    r?	  j#        $                                  %                                 n8# tB          $ r Y n,w xY w	  &                    d@A           n# tB          $ r Y nw xY wt          j                    'd<                        dBt9          |           dC                                dDt9          |           dE            j         rd"d<   t*                              dF           	  j        d?k    r. j#        $                                  %                                 n dG           n# tB          $ r Y nw xY wt          dH          |	                                 j         rt          dI          *d         3%d         r"tO           dJd/          pd/(                                pd}tS          *                    dK          pg           }|rdL
                    |ddM                   }tU          |          dMk    r|dNtU          |          dMz
   dOz  }dP| dQ}|pd/|z   }	  +                    |           n# tB          $ r Y nw xY wt*                              dR|tU          |pd/          *d                    tX          }n8t*                              dStU          |pd/          *d                    tX          }t[          dT|ddU          }d}	 d)dVl.m/}m0}  |*d         tc          tO           dWd/          pd/          tc          tO           d+d/          pd/          X          }|j2        |j3        k    }n# tB          $ r d}Y nw xY wt[          th          tO           d+d8          t[          d)||Y          gd|pdZ          }|rd|_5        tm                      |S *d         *d         tm                      *d         S )\u  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 callr   Nr   r   doneFr   c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S Nr  Tr|   first_delta_firedr   s   r   _fire_firstz5interruptible_streaming_api_call.<locals>._fire_first  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   )r   r   r    is_streaming_access_denied_errorr   stream_converse_with_callbacksr   r   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.r   c                P                                       |            dd<   d S )NTr   )_fire_stream_delta)textr  rJ   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)rr   r  rJ   s    r   _on_toolzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_toolE  s(    KMMM0066666r   c                F                                       |            d S r.   )_fire_reasoning_delta)r  r  rJ   s    r   _on_reasoningzNinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_reasoningI  s(    KMMM//55555r   c                      j         S r.   )r   r}   s   r   r   zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>R  s
    u/I r   )on_text_deltaon_tool_starton_reasoning_deltaon_interrupt_checkr   r/   )r   r   r   r   r  r   r  r   converse_streamr|   _disable_streaming_safe_printr\   r  r   r   r   _has_stream_consumersr  r  )r   r   r   r  r   r  r   r   r   r   r  r  r  r   r  rJ   r   r  r   s                 r   _bedrock_callz7interruptible_streaming_api_call.<locals>._bedrock_call  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 callz7Agent interrupted during Bedrock API call (post-worker)r   r   )r   r   partial_tool_names)r   diagr   r$   c                r    5  | d<   t          j                    d<   d d d            n# 1 swxY w Y   | S r   r   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!   r   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 r   r   r   s       r   r   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Mr   r-  c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S r  r  r  s   r   _fire_first_deltaz;interruptible_streaming_api_call.<locals>._fire_first_delta  sq     ( 	^ 	(,f%        		 	 	 	r  c                   	0 ddl } t          4j        4j                  }||nt	          dd          }||}nt	          dd          }|dk    r?4j        r8t          4j                  r$|}t                              d4j        |           n>|dk    r8363t          d          k    r#3|k    r3}t                              d	|           |t          |d
          nd}i 5d|                     ||||          d}t          4j                  sddi|d<    24                    d|                    }t          j                    7d<   4                    d           4                                }|8d<    |j        j        j        dCi |}t)          |d          rt                              d4j        pd4j        pd           d4_        |j        }	t1          |	t2          t4          f          r
|	r|	d         nd}
t7          |
dd          }|t7          |dd          pt7          |dd          }t1          |t8                    r!|r 1             4                    |           t7          |dd          }t1          |t8                    r!|r 1             4                    |           |S 4                    t7          |dd                     4                     t7          |dd                     4!                    |t7          |dd                     4"                    t7          |dd                     g }i 0tG                      }i }i }d}d}d}g }d}|D ]}t          j                    7d<   4                    d           	 tI          |%                    d d                    d!z   |d <   |%                    d"          7d         |d"<   	 tI          |%                    d#d                    tM          tO          |                    z   |d#<   n# tP          $ r Y nw xY wn# tP          $ r Y nw xY w4j)        r n|j        s>t)          |d$          r|j        r|j        }t)          |d%          r|j*        r|j*        }-|j        d         j+        }t)          |d$          r|j        r|j        }t7          |dd          pt7          |dd          }|r4|,                    |            1             4                    |           |r|j-        r|,                    |j-                   0s* 1             4                    |j-                   d6d&<   nM4j.        rF	 4.                    |j-                   4/                    |j-                   n# tP          $ r Y nw xY w|r*|j0        r"|j0        D ]}|j1        |j1        nd}|j2        pd'}||vr|||<   |r)||v r%|||         k    rtg          0d()          d!z   }|||<   |r|||<   ||         }|0vr:|j2        }t1          |tH                    rt9          |          }|pd'd*d'd'd+dd,0|<   0|         }|j2        2|j2        } t1          | tH                    rt9          |           } | r| |d-<   |j4        rM|j4        j5        r|j4        j5        |d*         d.<   |j4        j6        r |d*         d/xx         |j4        j6        z  cc<   t7          |d0d          }!|!Ft)          |d1          r6t1          |j7        tp                    r|j7        ni %                    d0          }!|!)t)          |!d2          r|!9                                }!|!|d0<   |d*         d.         }"|"rS||vrO|:                    |            1             4;                    |"           9d3         ,                    |"           |j        d         j<        r|j        d         j<        }t)          |d%          r|j*        r|j*        }d'=                    |          pd}#d}$d4}%0rg }$t}          0          D ]}0|         }&|&d*         d/         }'|&d*         d.         pd5}(|'rZ|'?                                rF	 t          jA        |'           n0# t          jB        $ r t          |'|(          })|)d6k    r|)}'nd}%Y nw xY w|$,                    t          |&d-         |&d7         |&%                    d0          t          |&d*         d.         |'+          8                     ||s|s0st          d9          |%o|du }*|*r0fd:t}          0          D             }+t          F                    d;|+           d'=                    |          pd},t          ||#d|,<          }-t          d|-t          =          }.t          t          ||.g||+pd>          S |pd?}/|%rd@}/d'=                    |          pd},t          ||#|$|,<          }-t          d|-|/=          }.t          dAt9          t          jJ                              z   ||.g|B          S )Dz#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)connectreadwritepool)streamr   include_usagestream_optionschat_completion_stream_requestr   r-  z)waiting for provider response (streaming)r  choicesz}Streaming request returned a final response object instead of an iterator; switching %s/%s to non-streaming for this session.r  messager  r  r  r   r  receiving stream responsechunksr   first_chunk_atbytesr   usager   rC   r  )rs   r  r  )r  r   r  r  r  rr   r  r  r  r  r  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  rr   r  r/   )r0   r  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.r  r  r  r  indexr  r  r  r   r  r  _dropped_tool_namesstoplengthzstream-)r  r   r  r  r/   )Khttpxr   rE   r   r   rD  r   r\   r   rN   r  Timeoutr   r   r  r   _stream_diag_initr   r   r   r  r  r  r  r'   r3   tuplerI   r(   r  r  _capture_rate_limits_capture_credits_stream_diag_capture_response_check_openrouter_cache_statusrK  r"   r<   r)   reprr|   r   r  deltar  r  r  _record_streamed_assistant_textr  r  r  r  r  rr   r  r  r;   r  rM  r  r  r^   r_   rY   jsonloadsJSONDecodeErrorr   r   r   r]   r   r
   r  r  ):_httpx_provider_timeout_cfg_base_timeout_stream_read_timeout	_conn_capstream_kwargsr   _diagr  r  first_choicer  r  r  content_partstool_gen_notified_last_id_at_idx_active_slot_by_idxr  
model_namer  reasoning_parts	usage_objchunkr%  tc_deltaraw_idxdelta_idnew_slotr  _tc_identry_new_idr  rr   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_timeoutrJ   r   r  last_chunk_timer   r   s:                                                   @r   _call_chat_completionsz@interruptible_streaming_api_call.<locals>._call_chat_completions  sE    !=U^U[ Y Y %0 "!/88 	 !,#8  #,-I5#Q#Q 
 $u,,,DUV[VdDeDe,'4$ZN$8   
 %--)5)U5\\99),@@@ (=$23G   1F0QCt,,,W[		
	
~~!)#	 &  	
 	
 	
  )88 	F/>.EM*+,,//7( 0  
 
  $y{{IJJJ ''))(-f%7$07HH-HH  69%% 	KKR+)(y	   (,E$
 nG)3GdE])K)KaPWa71::]aLlIt<<G"G%8$?? ;wT::  nc22 @~ @%%'''//???!'9d;;gs++ 6 6%%''',,W555M
 	""76:t#D#DEEEwvz4@@AAA 	++E76:t3T3TUUU 	,,WVZ-N-NOOO !!$
 !#$&
 "	 T	( T	(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$     GB) GB % 0 FB F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!)%fc22 1%([[F"(,B$.13"(E(E-1	/ /s+ +3/E{."*+%gs33 3&)'llG" 2*1E$K( Z#,1 	O 9A8I8NE*-f5#,6 Z!*-k:::h>O>YY:::#HotDDE}=)I)I}9CHDXZ^9_9_!g!5!5eg l lm| } }("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	P=(AP,+P=,
P96P=8P99P==
Q
	Q
;4V00
V=<V=b33*c c c            	        d} 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 ]}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                                  |           j        r	 d
d
d
           d
S 	 |                                }n!# t(          $ r |st+          d          d
 w xY w|s3|"t	          |dd
          s t	          |dd
          t+          d           |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-  r  r   )sanitize_anthropic_kwargsrN  rC   )rN  r   NTr  r  r   r  r  r   content_block_startcontent_blocktool_userr   content_block_deltar%  
text_deltar  r   thinking_deltathinkingzeProvider returned an empty stream with no events (possible upstream error or malformed event stream).r  stop_reasonzjProvider returned an empty stream with no stop_reason (possible upstream error or malformed event stream).r/   )r  r  r  rP  rI   r  r+   r  r"  r|   r   r"   r<   r)   r$  r   r  r  r  get_final_messageAssertionErrorr   )has_tool_usesaw_stream_eventr0  rP  r  event
event_typeblockr  r%  
delta_typer  thinking_text_final_messager  rJ   r   r  rM  r   s                 r   _call_anthropicz9interruptible_streaming_api_call.<locals>._call_anthropicb
  s     !  $y{{''))(-f%
 	FEEEEE!!75,#C#C	
 	
 	
 	
 5U$-4BBzBB h	"f
3376:t<<        3K 3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 ) Qh	" h	" h	" h	" h	" h	" h	" h	"^!'!9!9!;!;!   '  *O      $ 
&	4@@ '  tDDL 'K   "Qh	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	" h	"s   .L;0%BL;
B# L;"B##5L;A	E8#AE'&E8'
E41E83E44E87L;8
FL;FD/L;KL;K559L;;L?L?c                 ~  	 dd l } t          dd          }	 t          |dz             D ]K}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          }                    |          }t          |t(                    }d         rt+                              d                    }d}	|sg|seddlm}
 t          ||
          rOt3          |dd           s>t5          |                                          d}t9          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           j        dk    r?	 j!        "                                 #                                 n8# t          $ r Y n,w xY w	 $                    d           n# t          $ r Y nw xY wY d }~d}|sg|seddlm}
 t          ||
          rOt3          |dd           s>t5          |                                          d}t9          fd|D                       }|s	|s|s|s|r'||k     r                     ||dz   |dz   d                    d                      d           j        dk    r?	 j!        "                                 #                                 n8# t          $ r Y n,w xY w	 $                    d           n# t          $ r Y nw xY wY d }~B%                    d||dz   |dz   d                    d                      |r
d!|dz    d"}n|r
d#|dz    d"}n	d$|dz    d"}&                    |           nt5          |                                          }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 retryr   r   stream_request_completer$   uP   Streaming worker caught %s after request cancellation — exiting without retry.r   r  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/   )r0   phrase_err_lower_previews     r   r2   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>?  s=       ?" ?"(. %+.@$@?" ?" ?" ?" ?" ?"r   z9Streaming failed after partial delivery, not retrying: %sr   u9   

⚠ Connection dropped mid tool-call; reconnecting…

r  Tr  )r   attemptmax_attemptsmid_tool_callr  stream_mid_tool_retry_cleanup"stream_mid_tool_retry_pool_cleanupr   c              3      K   | ]}|v V  	d S r.   r/   )r0   rl  _err_lower_sses     r   r2   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)kindr   rn  ro  rp  r  u5   ❌ Provider returned malformed streaming data after uM    attempts. The provider may be experiencing issues — try again in a moment.u5   ❌ Provider returned an empty response stream after 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_errorr   r@   r<   openairh  rI   r(   rZ   r  r]   r  _reset_stream_delivery_tracking_emit_stream_dropr  r  r  rY  _log_stream_retryr  r   r  r  r  r  ) r*  _max_stream_retries_stream_attemptr   _is_timeout_is_conn_err_is_stream_parse_err_is_empty_stream_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_exhausted_msg
_err_lower_is_stream_unsupported_is_bedrock_stream_deniedr  rm  rt  rc  rN  r   r   rJ   r  r  r   r   s                         @@r   r   z/interruptible_streaming_api_call.<locals>._call
  sf	   %&=qAA|	B#()<q)@#A#A s s - T*+RSSSj~)===GGIII-<_->->z**-C-C-E-Ez*X	 '&'@AAAAAW	 ! c c c *'2 F GG,  
 x '&'@AAAAAw #-F.0EvGYZ# #K $.F/1K_]$ $L ,1+P+PQR+S+S('1!5E'F'F$ (. a!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"FFFFn '&'@AAAAA_!!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 >-AAA% % 7 = = ? ? ? % ? ? A A A A#, % % % $%% % D D+O !E !" !" !" !" $- % % % $%  (-$& | @@@@@@%a33 GA}VZ<[<[ -0VV\\^^N1- 03 3 3 3 3.?3 3 3 0 0, $u'u ,u 0	u
 ,u +-@@@!33&'(7!(;-@1-D.3%:%>%>v%F%F 4    767MNNN  %~1EEE!)$)$;$A$A$C$C$C$)$C$C$E$E$E$E'0 !) !) !)$(D!)!)$)$H$H/J %I %& %& %& %& (1 !) !) !)$(D!)$HHHH //!,"#$7!$;)<q)@*/!6!:!:6!B!B 0    0 !9#6#:!9 !9 !9 +N . !9)<q)@!9 !9 !9 +N!9#6#:!9 !9 !9 + ,,^<<<<%(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AW	c!sh	   	 	 	  F7OFFF&&'@AAAAA	i	sv	 '&'@AAAAA&&'@AAAAs_  +U9 :B?U9 U55U0U9 D8U0U9 *I ?U0 
I
U0IU0I&%U0&
I30U02I33AU0-K=<U0=
L
U0	L

U0L%$U0%
L2/U01L22U05U9 ;CU0-P/.U0/
P<9U0;P<<U0 QU0
Q$!U0#Q$$U0'U9 -C1U0U9 0U55U9 8V/ 9
VVV/ VV/ /V<HERMES_STREAM_STALE_TIMEOUTr   r  u>   Local provider detected (%s) — stale stream timeout disabledrP   g     r@rQ   g      n@r   )!get_reasoning_stale_timeout_floorr   r  z; auto-reconnect at r
  rC   r   r   r  zRs with no output yet (provider may be slow or overloaded, or the model is thinking)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  z
s (model: z, context: ~z tokens). Reconnecting...stale_stream_killr   stale_stream_pool_cleanupr   u    ⚠ no output from provider for r  zstale stream detected after zs, reconnectingzLForce-closing streaming httpx client due to interrupt (not a network error).stream_interrupt_abortz+Agent interrupted during streaming API callz9Agent interrupted during streaming API call (post-worker) _current_streamed_assistant_textr  rX      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: %sr  r  )classify_api_errorr   rE   )rE   r   r  r  r   )7r   r   r   _interruptible_api_callr   r   r   r  r  r  r^   r   r   r  r	   rE   r   r   rD  r   rN   r\   r   r?   r  agent.reasoning_timeoutsr  r<   r"   r  r   r]   r  r|   r   r  r  r  rY  rI   rY   r3   r)   r  r   r   agent.error_classifierr  r   r(   r   content_policy_blockedr
   _content_filter_terminatedr   )+rJ   r   r   r  r-  r   
_cfg_stale_stream_stale_timeout_base_est_tokensr  _reasoning_floor_last_heartbeat_HEARTBEAT_INTERVAL_hb_now_waiting_secs	_recovery_stale_elapsedr5  _partial_text_partial_names	_name_str_warn_stub_finish_reason	_stub_msgr  r  r   _cls_stubrc  rN  r   r  r  r   r   rL  r  r  rM  r   r   r   s+   ```                          @@@@@@@@@@@@@@r    interruptible_streaming_api_callr    si     ! NLMMM "%(( 9,,Z888~***
 '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 !     n
 n
 n
 n
 n
 n
 n
 n
 n
 n
 n
 n
 n
`K" K" K" K" K" K" K" K" K" K"ZAB AB AB AB AB AB AB AB AB AB AB AB ABH
 ,ENEKHHJ%/""%./Le%T%T" "U**u~*BSTYTbBcBc* %eUW\Weffff 6jAA  $'(BE$J$J!!6!!$'(BE$J$J!!$>! 	ONNNNN<<Z^^G=T=TUU'$'(=?O$P$P!d333AGGIIIikkO
**,, jR	s )++_$(;;;%O/#*> >??M 333 *5-u== Ts;P7Q7Q T T TII "I''PjnnWn&M&M P P$P PCLP P P    %%TMTTT   s';;1116zBBHNNC 5w	22xOO	     #N8K8K # #%>>'9==# #%3# # #  **+>????    u%%% ~!555+11333335555    D88@[8\\\\    D $(9;;OC ###3~3F3F # # #   !!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QU **,, jR` ! \Z[[[g"E" V	 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 */&3UUUUUUUU))7O 
B!?!?!E2FFgeWb99?R@@   K>#HH +*  3 3 3-2***3#)eWi88(Y>Q    $2$:d  E * 8370  &&&LWo j%E"""*sz   A; ;	BR* *
R76R7-T 
TTT+ +
T87T8AX	 	
XX	\ 
\,+\,7A(`   `/.`/)r6  r  r   r  r  r  r  )r    r   r!   r"   )r!   r@   )rM   r"   r!   rN   )rU   r   r!   rV   )r!   rb   )rr   r(   rs   rN   r!   rN   )r!   r"   )r!   r   )r   r;   )r7  r3   r!   r;   )r  r(   r!   r;   )r   r(   rE   r(   r!   r   )r  r;   r!   r  )r  r;   r!   rV   r.   )r   r"  r!   r@   )r+   r3   r  r"   r!   r(   )r  r(   r!   r   )F__doc__
__future__r   r'  r  ru   r  r   r  r  typesr   typingr   r   r   hermes_cli.timeoutsr   r	   ra  r
   r   r  r   agent.errorsr   agent.gemini_native_adapterr   r^  r   agent.message_sanitizationr   r   tools.terminal_toolr   utilsr   r   r   r   	getLoggerr   r\   r[   rJ  r   r?   rL   rT   ra   rq   ry   r~   r   r   r   r   r   r   r6  r  r   r  r  r!  r  r  r  r  __all__r/   r   r   <module>r     s    # " " " " "   				 				       ! ! ! ! ! ! & & & & & & & & & & X X X X X X X X I I I I I I I I 1 1 1 1 1 1 ) ) ) ) ) ) A A A A A A 2 2 2 2 2 2        2 1 1 1 1 1 N N N N N N N N N N N N		8	$	$#E#E#E   "%   2$ 2$ 2$ 2$j	 	 	 	   &   "   &   $         
 
 
 
5@ 5@ 5@ 5@p   1Z 1Z 1Z 1ZhD D D DP@ @ @ @Hg g g gV% % % %:      *j4 j4 j4 j4 j4\o o o ofQ Q Q Q@ QU M M M M M Mf*  r   