
    epjJ                   `   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
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! ddl"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-m.Z.m/Z/m0Z0  ej1        e2          Z3h dZ4dZ5d Z6d Z7dbdZ8dcdZ9dddZ:ded"Z;dfd$Z<dgd'Z=dhd+Z>did-Z?djd7Z@dkd8ZAdld:ZBdld;ZCdld<ZDdmd>ZEdndBZFdodCZGdcdDZHdodEZIdodFZJdpdqdKZKdrdMZLdsdPZMdtdSZNdudTZOdpdvdWZPdwdZZQdxd\ZRdd]d^ZSdd_dod`ZTg daZUd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)substitute_api_content)is_native_gemini_base_url)is_local_endpoint)flatten_message_text)_sanitize_surrogates_repair_tool_call_arguments)claim_stream_writerstream_writer_is_current)is_persistent_env)base_url_host_matchesbase_url_hostname	env_floatenv_int>   pricelatency
throughputg      @c                8     t          j                     fdS )z=Bind a no-argument thread target to the caller's ContextVars.c                 .                                    S N)runcallbackcontexts   C/home/thesage/.hermes/hermes-agent/agent/chat_completion_helpers.py<lambda>z(_context_thread_target.<locals>.<lambda>@   s    7;;x((     )contextvarscopy_contextr"   s   `@r%   _context_thread_targetr*   =   s$    &((G((((((r'   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    r%   _rar.   C   s     r'   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   r0   r1   c                    | dS t          | t                    rt          |           S t          t          |                     S Nr   )
isinstancestrlenr3   s    r%   _charsz/estimate_request_context_tokens.<locals>._chars_   s<    =1eS!! 	u::3u::r'   messagesc                z    t          | t                    s |           S t          fd| D                       S )Nc              3  .   K   | ]} |          V  d S r     ).0itemr:   s     r%   	<genexpr>zJestimate_request_context_tokens.<locals>._message_chars.<locals>.<genexpr>i   s+      55D66$<<555555r'   )r6   listsum)r;   r:   s    r%   _message_charsz7estimate_request_context_tokens.<locals>._message_charsf   sH    (D)) 	$6(###5555H555555r'      toolsinputinstructionsc              3  .   K   | ]} |          V  d S r    r>   )r?   r3   r:   s     r%   rA   z2estimate_request_context_tokens.<locals>.<genexpr>~   s+      CCU66%==CCCCCCr'   )r3   r   r0   r1   )r;   r   r0   r1   )r6   rB   dictgetrC   values)r/   rD   r;   total_charsr:   s       @r%   estimate_request_context_tokensrN   N   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)r7   getattr)agentbase_url_lowerr   s      r%   _is_openai_codex_backendr[      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     @        r>   )r\   s    r%    openai_codex_stale_timeout_floorrd      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), )	r6   r7   striplower _OPENROUTER_PROVIDER_SORT_VALUESloggerwarningjoinsorted)re   
sort_values     r%   #_validated_openrouter_provider_sortrq      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_orderrq   provider_sortprovider_require_parametersprovider_data_collection)rY   preferencesr}   s      r%   _provider_preferences_for_agentr      s    "$K 6#5F 8 % 7H 5$4G78KLLM ,+F( 1,0()% H).)G%&r'   anthropic_kwargsrJ   c           	     V   t          | dd          dvr|S 	 ddlm}  |d          }|L|                    di                               |                    t          | dd          	                     n2# t          $ r%}t                              d
|           Y d}~nd}~ww xY w|S )u  Merge Portal ``tags`` / ``session_id`` onto an Anthropic Messages kwargs dict.

    The Nous provider profile is only consulted by the OpenAI-wire transport;
    anthropic_messages callers must merge it themselves. Passes ``session_id``
    only — not ``provider_preferences`` (those become a top-level ``provider``
    routing object on the OpenAI wire). Never blocks a turn on tagging.
    rT   N>   nousnousresearchnous-portalr   get_provider_profiler   
extra_body
session_id)r   z'Nous Portal extra_body merge failed: %s)	rX   	providersr   
setdefaultupdatebuild_extra_body	Exceptionrl   debug)rY   r   r   nous_profileexcs        r%   &_merge_nous_portal_messages_extra_bodyr      s     uj$''/VVVE222222++F33#''b99@@--&ulDAA .    
  E E E>DDDDDDDDEs   AA7 7
B&B!!B&namer7   defaultc                    	 t          t          j        | t          |                              S # t          t
          f$ r |cY S w xY wr    )r]   osgetenvr7   	TypeError
ValueError)r   r   s     r%   
_env_floatr      sP    RYtS\\22333z"   s   .1 AAchunkc                   d}	 t          | dd          }|rt          |d         dd          }|dD ]:}t          ||d          }t          |t                    r|t          |          z  };t          |dd          }|r|D ]}t          |dd          }|pt          |d	d          }	t          |	t                    r|t          |	          z  }t          |d
d          }
t          |
t                    r|t          |
          z  }nLdD ]I}t          t          | dd          |d          }t          |t                    r|t          |          z  }Jn# t          $ r Y nw xY w|S )u   Cheap per-chunk size estimate for the stream diagnostic counters.

    The previous implementation used ``len(repr(chunk))`` — a full recursive
    repr of a pydantic model on EVERY streaming chunk (5.5-8.8 µs each,
    ~20-30 ms of pure CPU on a 3,000-chunk response, in the hottest loop in
    the agent). The counter only feeds a retry-diagnostic log line, so an
    estimate based on the delta payload lengths is plenty (2.1-2.4 µs, ~3x
    cheaper, and independent of model/pydantic field count). Chat Completions
    chunks are sized from their delta content/reasoning/tool-argument strings
    plus a small framing constant; anything shape-unknown (Anthropic events,
    stub providers) falls back to a flat constant so `bytes` stays monotonic
    and roughly proportional to traffic.
    (   choicesNr   delta)contentreasoning_content	reasoning
tool_callsfunction	argumentsr   )textpartial_json)rX   r6   r7   r8   r   )r   sizer   r   attrvr   tcfnargsr   s              r%   _estimate_chunk_bytesr      s    D%D11 	#GAJ66E I ' 'DtT22A!!S)) 'A$UL$??
 	2( 2 2$RT::>#*2{D#A#AD)$44 2 $D		 1#*2vt#<#<D)$44 2 $D		 1 1 # #GE7D994FFa%% #CFFND   Ks   EE 
E#"E#stale_timeoutttfb_enabledttfb_timeoutlast_event_tsOptional[float]
call_startidle_enabledidle_timeoutelapsedc                   g }t          j        |           r|                    |            |,|r)t          j        |          r|                    |           n?|r=t          j        |          r)|                    t          d||z
            |z              |rt	          |          |k    rdS dt          t	          |                     dS )zBDescribe the earliest enabled Codex watchdog on the call timeline.Nrc   rR   ; auto-reconnect at s)mathisfiniteappendmaxminr1   )	r   r   r   r   r   r   r   r   	deadliness	            r%   _codex_wait_notice_recoveryr     s      I}]## (''' 	+DM,77 	+\***	 N$-55 NS-*"<==LMMM I'11r8#c)nn"5"58888r'   c                f    	 t          t          | dd          pd          S # t          $ r Y dS w xY w)N_consecutive_stale_streamsr   )r1   rX   r   rY   s    r%   _stale_streakr   9  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r5   )r   r   r   s    r%   _reset_stale_streakr   G  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)rY   _giveup_streaks      r%   _check_stale_giveupr   N  sj     2A66GE""G{{w'))## # #
 
 	
 {))r'   
api_kwargsc                   t          | j        | j                  }||}nt          dd          }t	          |          }|dk    rt          |d          }n|dk    rt          |d          }n|}dd	lm} |                    d
          p|                    d          pd} ||          }|*|                    d          rt          |d                   }|t          ||          }|S )u  Stale-stream patience for a provider that is never a local endpoint.

    Mirrors the main streaming path's derivation — provider config → env base
    → context-size scaling → reasoning-model floor — minus the local-endpoint
    ``float('inf')``/900s disable branch, which cannot apply to Bedrock (its
    endpoint is always the AWS cloud). Factored so the Bedrock streaming
    watchdog shares the exact same patience budget as the OpenAI/Anthropic
    stale-stream detector below.
    NHERMES_STREAM_STALE_TIMEOUT     f@r_        r@r`         n@r   !get_reasoning_stale_timeout_floormodelmodelIdrR   )
r	   rT   r   r   rN   r   agent.reasoning_timeoutsr   rK   _bedrock_reasoning_stale_floor)	rY   r   
_cfg_stale_base_est_tokens_timeoutr   	_model_id_reasoning_floors	            r%   _derive_stream_stale_timeoutr   \  s    ,ENEKHHJ7??1*==KWue$$	v		ue$$JJJJJJ w''J:>>)+D+DJI88CCJNN9$=$=9*Y:OPP#x!122Or'   model_idobject'float | None'c                   ddl m} | rt          | t                    sdS |                                                                 }dD ]0}|                    |          r|t          |          d         } n1|g}d|v rY|                    |	                    dd          d                    |                    |
                    ddd                     g }|D ]O}t          j        dd|          }t          j        d	d|          }|||fD ]}	|	|vr|                    |	           P|D ]} ||          }
|
|
c S dS )
u  Map a Bedrock inference-profile id to its reasoning stale-timeout floor.

    Bedrock carries the model as a dotted, region-prefixed id such as
    ``us.anthropic.claude-opus-4-6-v1:0``, whereas
    :func:`get_reasoning_stale_timeout_floor` anchors its slug patterns at the
    start of a bare slug (``claude-opus-4``). Strip the region prefix
    (``us.``/``eu.``/``apac.``/...) and try two candidate slugs against the
    floor:

    * the segment after the provider namespace (``claude-opus-4-6-v1:0``) —
      matches Anthropic-style slugs whose floor key excludes the provider
      (``claude-opus-4``); and
    * the region-stripped id with the provider dot rewritten to a dash
      (``deepseek-r1-v1:0``) — matches provider-qualified floor keys
      (``deepseek-r1``).

    The floor's right-anchor (``$`` or ``-``/``.``/``_``) tolerates the
    trailing date-stamp / ``-v1:0`` version suffix, so no suffix stripping is
    needed. First non-None wins; returns None for unknown models.

    The floor table mixes version-separator conventions: some keys are
    keyed with a dashed version (``claude-opus-4``) while others embed a
    dotted version (``claude-sonnet-4.5``, ``claude-sonnet-4.6``). Bedrock
    always dashes the version (``claude-sonnet-4-5-v1:0``), so for every
    candidate slug we also try the alternate version-separator form —
    digit-dash-digit rewritten to digit-dot-digit and vice-versa — so a
    dashed Bedrock id matches a dotted floor key (and the reverse). The
    rewrite only touches version-number separators (a dash/dot flanked by
    digits), never other dashes in the slug, so ``claude-sonnet`` is left
    intact while ``4-5`` becomes ``4.5``.
    r   r   N)zglobal.zus.zeu.zapac.zap.zau.zjp.zca.zsa.zme.zaf..r   -z(?<=\d)-(?=\d)z(?<=\d)\.(?=\d))r   r   r6   r7   ri   rj   
startswithr8   r   rsplitreplaceresub)r   r   r   prefixbase_candidates
candidatescanddashed_to_dotteddotted_to_dashedformfloors              r%   r   r     s   @ KJJJJJ :h44 t>>!!##D   ??6"" 	F%DE	 fO
d{{t{{32215666t||Ca88999J ( ( 6"3S$??6"4c4@@+-=> 	( 	(D:%%!!$'''	(   11$77LLL 4r'   c          	        | j         dk    r2 |d          }|                     ||t          | dd                    S | j         dk    r$ |dd          }|                     ||	          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 )um  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, kind=...)`` builds the per-request client for the
    codex / OpenAI-compatible (``kind="openai"``) and anthropic
    (``kind="anthropic_messages"``) 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
    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anthropic_messages_requestkind)r   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_streamrX   _anthropic_messages_createagent.bedrock_adapterr  r  r  r  popconverser   rT   r   chatcompletionscreate)rY   r   make_clientrequest_clientr  r  r  r  regionr   raw_response_bedrock_excs               r%   "_dispatch_nonstreaming_api_requestr    s     ~***$%;<<&&!"5*A4HH ' 
 
 	

 ~--- %(/C
 
 
 //
>/RRR~+++
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
  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   <C
 

C0C++C0c                    t          | dd          dk    rdS t          | dd          dk    rdS t          | dd          dk    rd	S 	 d
dlm}  |            rd	S n# t          $ r Y nw xY wt          | dd          dk    S )u
  Whether an OpenAI-wire request should skip the interrupt worker.

    Two nested-pool contexts wedge before the socket opens when the request
    is pushed onto yet another daemon worker thread:

    - Gateway cron turns (#62151): gateway asyncio loop → cron thread →
      interrupt worker. Fixed by running inline.
    - Delegated children (#60203): gateway loop → async-delegation executor
      (module-lifetime daemon pool) → per-child timeout executor → interrupt
      worker. Same fingerprint after multi-day gateway uptime — children hang
      at their FIRST API call with zero stale-detector output (the worker
      never reaches dispatch), all providers, restart cures it. The cron fix
      originally excluded delegation "for lack of evidence"; #60203 is that
      evidence.

    Running inline drops the deepest thread layer (whose only job is
    interactive-interrupt responsiveness). Interrupts still work: the inline
    path registers ``agent._active_request_abort``, which ``interrupt()``
    invokes cross-thread to shut the active sockets — the same mechanism the
    async-delegation stall monitor (#72227) relies on.

    Keep native/Codex/Bedrock/MoA transports on their established workers:
    their cancellation and client ownership differ.
    r  Nchat_completionsFrT   r  platformcronTr   )is_delegated_child_contextsubagent)rX   agent.delegation_contextr!  r   )rY   r!  s     r%   should_use_direct_api_callr$    s    2 uj$''+===uuj$''500uuj$''611tGGGGGG%%'' 	4	   5*d++z99s   A 
A'&A'c                    t                                           d           ddit          j                    d fddd fd}d}	 t	           |          }t           dd          rt          d          t                      d}|t           dd          u rd _        5  d         }dd<   ddd           n# 1 swxY w Y   | 	                    ||rdn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   | 	                    ||rdn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 (cron turns and
    delegated children). Skips the interrupt worker (whose only job is
    interactive-interrupt responsiveness, which these contexts do not have)
    so the nested-pool deadlock (#62151, #60203) 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reasonr7   r0   r   c                    5  d         }|                     ||            ddd           dS # 1 swxY w Y   dS )z:Abort the inline request from a watchdog/interrupt thread.r   Nr'  )_abort_request_openai_client)r'  r  rY   request_client_holderrequest_client_locks     r%   _abort_active_requestz.direct_api_call.<locals>._abort_active_request>  s     ! 	R 	R28<N)22>&2QQQ	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	R 	Rs   "377openair  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   r-  rY   r   r+  r,  s      r%   _make_clientz%direct_api_call.<locals>._make_clientK  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Fr  _interrupt_requested!Agent interrupted during API callTr2  request_completerequest_error_cleanupr)  r'  r7   r0   r   r.  )r'  r7   r  r7   )r   _touch_activity	threadingLockr  rX   InterruptedErrorr   r2  _close_request_openai_clientr   )	rY   r   r3  	succeededresponser  r-  r+  r,  s	   ``    @@@r%   direct_api_callrB  .  s    	BCCC%t,#.**R R R R R R R R	 	 	 	 	 	 	 	 	 	 	 I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 %..-6S))<S /     &!    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 %..-6S))<S /     &sT   C; )2D+ 7CC	C	;-D((D+ +FE"F"E&&F)E&*"Fc           
     :    !" t                     rt                     S ddd"t                      dddddi t          j                    !ddiddd_ !fd
d`  !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        t3          |          d'(          }|                                 d}|                                r|                    d)*           |d+z  }|d,z  dk    rt-          j                    |z
  }	 t;          ||
|t=           d-d          ||||.          }                     d/                    d0d1           d2tA          |           d3| d4           n,# tB          $ r t$          "                    d5d'6           Y nw xY wt-          j                    |z
  }|
r||k    rt=           d-d          d}t=           d7d          }tG          |          r3	  |                    d0          8          }n# tB          $ r d}Y nw xY wt$          $                    d9||                    d0d:                     |r@ %                    d;tA          |           d<                    d0d:           d=|            n= %                    d;tA          |           d<                    d0d:           d>           	  d?           n# tB          $ r Y nw xY w                     d@tA          |           dA                                dBtA          |           dC           |                    dD*           "dE         s"dF         k|r6tM          dGtA          |           dHtA          |           dI|           "dE<   n3tM          dGtA          |           dHtA          |           dJ          "dE<   nt=           d-d          }|rC|@t-          j                    |z
  |k    r%t-          j                    |z
  }t$          $                    dK||                    d0d:          |d"            %                    dLtA          |           dM                    d0d:           d>           	  dN           n# tB          $ r Y nw xY w                     dBtA          |           dO           |                    dD*           "dE         ;"dF         3tM          dPtA          |           dQtA          |           dJ          "dE<   ni||k    rt                    }d}t=           d7d          }tG          |          r3	  |                    d0          8          }n# tB          $ r d}Y nw xY wt$          $                    dR||                    d0d:          |d"           |r@ %                    dStA          |           dT                    d0d:           dU|            n= %                    dStA          |           dT                    d0d:           dV           	  dW           n# tB          $ r Y nw xY wtO                                           dXtA          |           dY           |                    dD*           "dE         s"dF         k|r6tM          dZtA          |           d[tA          |           dI|           "dE<   n3tM          dZtA          |           d[tA          |           dJ          "dE<   ng j(        rKd'd<   t$          "                    d\           	  d]           n# tB          $ r Y nw xY wtS          d^          |                                "dE         "dE         "dF         tU                      "dF         S )aa=  
    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rA  error)r   	owner_tidr3   r.  Fr  r  r7   c               |    5  | d<   |d<   t          j                    d<   d d d            n# 1 swxY w Y   | S Nr   r3   rF  r<  	get_identr   r  r+  request_client_kindr,  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    !155r'  r0   r   c                0   5                       d          }                     d          }|d uo|d uo|t          j                    k    }|rW                     dd          dk    r                    ||            n                    ||            	 d d d            d S d d<   d d<   d d d            n# 1 swxY w Y   |d S                      dd          dk    r                    ||            d S                     ||            d S )Nr   rF  r3   r.  r   r)  rK   r<  rJ  _abort_request_anthropic_clientr*  _close_request_anthropic_clientr?  )r'  r  rF  stranger_threadrY   r+  rL  r,  s       r%   _close_request_client_oncez:interruptible_api_call.<locals>._close_request_client_once  s    ! 	6 	6266x@@N-11+>>Id* 7T)7!4!6!66 
   '**7H==AUUU99&v :     66~f6UUU-	6 	6 	6 	6 	6 	6 	6 	60 /3!(+15!+.3	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	64 !F""7H559MMM11.1PPPPP..~f.MMMMMs   BB='
B==CCc                 x   	 t          d
fd	          d<   nl# t          $ r_} d         rHt                              dt	          |           j                   Y d } ~  d         dnd           d S | d	<   Y d } ~ nd } ~ ww xY w d         dnd           d S #  d         dnd           w xY w)Nr.  c                     |dk    r                     |           n                    |           |          S )Nr   r)  r0  r  ) _create_request_anthropic_clientr1  )r'  r  rM  rY   r   s     r%   r&   z7interruptible_api_call.<locals>._call.<locals>.<lambda>  sa    :M:M333 ::&:III<<%* =   ; ; ; r'   r4  rA  r3   uh   Non-streaming worker caught %s after request cancellation — exiting without surfacing a network error.r7  r8  rE  r:  )r  r   rl   r   type__name__)erT  _request_cancelledrM  rY   r   results    r%   _callz%interruptible_api_call.<locals>._call  sj   (	 "D      " " "F:  	  	  	 
 "'* AGG$  
  '&*%1 #",      F7OOOOOO	 $ '&*%1 #",    &&*%1 #",   s7    B" 
B5BB" 9B>B" BB" "B9r   !HERMES_CODEX_HARD_TIMEOUT_SECONDSg     p@r   r_   r   r`         ^@rb         N@g      (@!HERMES_CODEX_TTFB_TIMEOUT_SECONDS&HERMES_CODEX_TTFB_DISABLE_ABOVE_TOKENSg     @HERMES_CODEX_TTFB_STRICTrR   >   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)r   r   r   r   r   r   r   r      ⏳ waiting on r   the provider    — z:s with no response yet (provider may be slow or overloaded)zwait-notice construction failedexc_info_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       @rE  rA  z&Codex stream produced no bytes within zs (TTFB threshold: zs). zs)zCodex stream produced no SSE events for %.0fs after first byte (threshold %.0fs, model=%s, context=~%s tokens). Killing connection so the retry loop can reconnect.u'   ⚠️ Codex stream sent no events for zs after first byte (model: codex_stream_idle_killzs with no SSE eventsz(Codex stream produced no SSE events for zs after first byte (threshold: zjNon-streaming API call stale for %.0fs (threshold %.0fs). model=%s context=~%s tokens. Killing connection.%   ⚠️ No response from provider for zs (non-streaming, model: z). z). Aborting call.stale_call_killz&stale non-streaming call killed after r   z'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_abortr6  r  r7   r9  )+r$  rB  r   r<  r=  !_compute_non_stream_stale_timeoutr  r[   rN   rd   r   r   r   r   environrK   ri   rj   rl   inforr  _codex_stream_last_progress_tstimer;  Threadr*   startis_alivern   r   rX   _emit_wait_noticer1   r   r   callablerm   _buffer_statusTimeoutErrorr   r5  r>  r   )#rY   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	_recovery_silent_hint_hint_fn_last_codex_event_ts_event_stale_elapsed_est_ctxrT  r[  rM  r+  rL  r,  r\  s#   ``                          @@@@@@@r%   interruptible_api_callr  u  s   " "%(( 2uj111..F '+$?? #H-#.** "5)3;          ,N ,N ,N ,N ,N ,N ,N ,N ,N\) ) ) ) ) ) ) ) ) )b <<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 6u = =dKKKAGGIIIK
**,, TH	sq !!y{{[0HO7"0!.!.")<d# #  +!4!4$  	 ''1jnnWn&M&M 1 18}}1 1$-1 1 1   
  O O O>NNNNNO 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& & &  
 +*+<====    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  **+<====   "#FGGGi **,, THj g"Wo j%E"""*s   (A&M &M87M8O0 0O?>O?3R? ?
SS(Y4 4
Z Z>] ]-,]-$`0 0
`=<`=.d: :
eeapi_messagesrB   tools_for_apilist | Nonec                  + || 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	                    
          }t!          | |          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# t8          $ r5}t:                              dt	          | dd          |           Y d}~nd}~ww xY w|                    | j        ||| j
        t	          | dd          | j        | 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# t8          $ r d	} d}!Y nw xY wtQ          |           }"d}#	 dd*l)m*}$m+}% | j        pd$                                ,                    d+d,          +t[          +fd-|%D                       r |$| j                  }#n# t8          $ r Y nw xY wd}&|r*| j.        pd.t_          ta          j1                              d/}&	 dd0l2m3}'  |'| j                  }(n# t8          $ r d}(Y nw xY w|(rt	          | dd          })|)d| _        |                     |          }|                    | j        ||| j        |                                 | j	        |)| j4        | j
        | j        t	          | dd          |(| j5        |"pd| j6        |#| 7                                |&1          S t	          | dd          })|)d| _        |                     |          }* |j        dTi d2| j        d3|*d4|d5| j        d6|                                 d7| j	        d8|)d9| j4        d:| j
        d;| j        dt	          | dd          d<| j        pd$                                d=|d>|d?|d@|dA|dB|dC|dD|dE| j        dFk    dG| j5        dH|"pddI| j6        dJ|r| j8        nddK|r| j9        nddL|&dM|!dN| dO| 7                                dP|r|                                  nddQ|r| :                                nddR|#dS| j        S )Uz9Build the keyword arguments dict for the active API mode.Nr   context_compressor_ephemeral_max_output_tokens_anthropic_base_urlspeedfast_oauth_1m_beta_disabledF)r   r;   rF   
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;   rF   r  r  guardrail_configr   zmodels.github.aizgithubcopilot.comrU   rV   rW   >   	xai-oauthxaizapi.x.air   )strip_pattern_and_formatstrip_slash_enumu4   %s⚠️ Failed to sanitize tool schemas for xAI: %s
log_prefixrR   r   _codex_reasoning_replay_enabledT)r   r;   rF   r  r   r  r  rp  request_overridesis_github_responsesis_codex_backendis_xai_responsesgithub_reasoning_extrareplay_encrypted_reasoningr   z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_LIMITSr   r   c              3      K   | ]}|v V  	d S r    r>   )r?   key_model_norms     r%   rA   z#build_api_kwargs.<locals>.<genexpr>  s(      FFcsk!FFFFFFr'   hermes)	sessionIdpromptIdr   )r   r;   rF   r  rp  r  ephemeral_max_output_tokensmax_tokens_param_fnr  r  r   provider_profileollama_num_ctxprovider_preferencesopenrouter_min_coding_scoreanthropic_max_outputsupports_reasoningqwen_session_metadatar   r;   rF   r  rp  r  r  r  r  r  model_loweris_openrouteris_nousis_qwen_portalis_github_modelsis_nvidia_nimis_kimiis_tokenhubis_lmstudiois_custom_providercustomr  r  r  qwen_prepare_fnqwen_prepare_inplace_fnr  fixed_temperatureomit_temperaturer  r  lmstudio_reasoning_optionsr  provider_namer>   );rF   r  _get_transport#_prepare_anthropic_messages_for_apirX   r  r  build_kwargsr   r  r  _is_anthropic_oauth_anthropic_preserve_dotsr  rK   rO   r   r   r  rT   rS   rQ   &_prepare_messages_for_non_vision_modelcopytools.schema_sanitizerr  r  deepcopyr   rl   rm   _resolved_api_call_timeout#_github_models_reasoning_extra_body_is_qwen_portal_is_openrouter_urlri   rj   agent.auxiliary_clientr  r  r   agent.anthropic_adapterr  r  r   anyr   r7   uuiduuid4r   r   _max_tokens_param_ollama_num_ctxr  _supports_reasoning_extra_body_qwen_prepare_chat_messages#_qwen_prepare_chat_messages_inplace"_lmstudio_reasoning_options_cached),rY   r  r  
_transportr   ctx_lenephemeral_outr   _btr  	guardrail_ctr  r  r  _msgs_for_codex_copyr  r  _r   _is_qwen_is_or_is_gh_is_nous
_is_nvidia_is_kimi_is_tokenhub_is_lmstudior  r  _ft
_omit_temp_fixed_temp_prefs_ant_maxr  r  
_qwen_metar   _profile_ephemeral_out_msgs_for_chatr  s,                                              @r%   build_api_kwargsr"  c  s
   ~---))++
"FF|TT%!5t<<,3='(('EtLL$15E.%22+'(5(A}}uGW"3.88::"U$94@@.4"99'BBfL!%ge5NPU&V&V!W!W 3 
 
$ 6e=MNNN ~+++""$$ 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 +JJ%(Q QQ4A"S 
S$#S$T- -T<;T<finish_reasonc                $   t          |dd          }|                     |          }t          |          }|sdt          t          |d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t          t          |d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.
    r   Nr   z<think>(.*?)</think>flags

c              3  f   K   | ],}|                                 |                                 V  -d S r    )ri   )r?   bs     r%   rA   z*build_assistant_message.<locals>.<genexpr>  s7      "P"Paggii"P17799"P"P"P"P"P"Pr'   zCaptured reasoning (z	 chars): r   )redact_sensitive_text	assistant)roler   r   r#  r   model_extra reasoning_details__dict__
model_dumpanthropic_content_blockscodex_reasoning_itemscodex_message_itemsidcall_idr   r   rR   r   {}response_item_idr   r   )r5  r6  r8  rX  r   extra_content)%rX   _extract_reasoningrO   r   r   findallDOTALLrn   verbose_loggingloggingr   r8   reasoning_callbackstream_delta_callback_stream_callbackr   r   r6   r7   _strip_think_blocksri   agent.redactr*  hasattrrJ   _needs_thinking_reasoning_padr/  r   r0  r1  _split_responses_tool_id_deterministic_call_id"_derive_responses_function_call_idrX  r   r   r   )"rY   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_itemsr4  r   	tool_callraw_idr6  embedded_call_idr  _fn_fn_name_fn_argsr8  embedded_response_item_idtc_dictextras"                                     r%   build_assistant_messagerb  o  s    ##4lDII--.?@@NN++
  .&w/@)T'R'RSSz"97")TTT 	.{{"P"Pl"P"P"PPPH%-N ]%/ ][S-@-@[[>[[\\\ %2  * 	53I 	((8888   
 (0A9d(S(STTL'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: :
DDr   rT   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: .*$z: )	rX   r6   r7   rB   r   finditerr  endrd  )rY   r   rT   splabelr3   matcheslasts           r%   rewrite_prompt_model_identityrn  e  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 )NrT   rR   r   r  /)r7   rK   ri   rj   rstrip)ro  s    r%   _fallback_entry_keyrt    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.rT   rR   r   Nr   )get_provider_auth_stateznous_auth_unreadable:access_tokenrefresh_tokennous_token_missing)rK   ri   rj   hermes_cli.authrv  r   rX  rY  r6   r7   rO   )
rY   ro  fb_providerrv  stater   access_valuerefresh_value
has_accesshas_refreshs
             r%   +_fallback_entry_unavailable_without_networkr    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 rt	          t          | dd                    }t          | dd          pd                                                                }| j        pi 	                    d          pd                                                                }|r|rp||k    rjt          | dd          }|dz   | _
        t          dd	|z  z  d
          }t          j                    |z   | _        t          j        d|||dz  |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 r0t2                              d|	           |                     |          S |	                    d          pd                                                                }|	                    d          pd                                }|r|s|                     |          S t9          | |          }|rG|
                    |	           t2                              d|||           |                     |          S ddlm }m!} |"                    t          | dd          t          | dd          tG          t          | dd          pd                    }|"                    |||	                    d          pd          } |||          r>t2                              d|||j$        p|j%                   |                     |          S 	 ddl&m'} ddl(m)} |	                    d          pd                                pd} ||          }|r%tU          |d          r|sddl+m,}  |d          pd} |||d||          \  }}|Et2                              d|           |
                    |	           |                     |          S 	 ddl-m.}  |||          }n4# t^          $ r'}t2                              d|||           Y d}~nd}~ww xY wd }tG          |j$                  }| 0                    |          }|d!k    rd"}n|d#v rdd$l1m2}  ||          }n|d%k    sM|3                    d&                                          4                    d'          stk          |          d(k    rd)}nq|rd }nl| 6                    |          rd"}nT| 7                    ||*          rd"}n:|d+k    s2tk          |          8                    d,          rtU          |d-          rd.}| j9        }| j%        } d| _:        || _9        || _%        || _;        || _$        || _<        t{          | d/          r| j>        ?                                 d| _@        t          | d0d          }!|!jt          |!dd          pd                                                                }"|"r1|"|k    r+t2                              d1|||"           d| _A        d| _B        t          | d0d          	 dd2lCmD}#  |#|          }$|$r7|$E                                r#|$| _A        t2                              d3||           n4# t^          $ r'}%t2                              d4|||%           Y d}%~%nd}%~%ww xY wt          ||          }&|d)k    rdd5lGmH}'mI}(mJ}) |d%k    r|jK        p |(            pdn|jK        pd}*|*| _K        |*| _L        || _M         |'|*| jM        |&6          | _N        |d%k    r |)|*          nd| _O        d| _P        i | _Q        n}|jK        | _K        || _P        t          |d7d          }+|+st          |d8d          }+|jK        |d9|+rd8t          |+          ini | _Q        |& |&| jQ        d:<   | S                    d;<           dd=lTmU},  |,|            | V                    ||||>          \  | _W        | _X        | Y                                 t{          | d?          r| jZ        rdd@l[m\}- t          | jK        tF                    r| jK        nd}. |-| j9        | j$        |.| j%        t          | dAd          t          | dBd          C          }/| jZ        ^                    | j9        |/| j$        t          | dDd          | j%        | j<        E           	 ddFl_m`}0 ddGlamb}1  |1 |0            pi | j9                  | _c        t2                              dH| j9        | jc                   n8# t^          $ r+}2t2                              dI| j9        |2           Y d}2~2nd}2~2ww xY wt          | ||           | e                    dJ| dK|            dL| dK|  dM| dK| | _f        t2                              dN|||           t          |            dS # t^          $ rV}3|dOk    r|
                    |	           t2          h                    dP||3           |                     |          cY d}3~3S d}3~3ww xY w)Qu  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_activatedFrT   rR   _rate_limit_backoff_countr   r   <      i@8  zARate-limit backoff level %d: cooldown %d s (%.1f min, backoff#%d)_rate_limited_until_unavailable_fallback_keysNz/Fallback skip: %s previously marked unavailabler   zMFallback skip: %s/%s is not locally usable (%s); suppressing for this session)BackendIdentityshould_skip_candidater  )rT   r   r  zUFallback skip: chain entry %s/%s resolves to the same backend as the current one (%s))resolve_provider_client)resolve_entry_api_keyz
ollama.com)
get_secret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  rU   r   >   r   r   r   )nous_api_mode	anthropicrr  z
/anthropiczapi.anthropic.comr   )rT   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_tokenro  _custom_headersdefault_headers)api_keyr  rp  fallback_timeout_applyr)  )sync_credential_pool_entry_id)rT   r  r  r   r  )get_model_context_length_config_context_length_custom_providers)r  r  rT   config_context_lengthcustom_providersr  )r   r  r  r  rT   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)ir   
rate_limitbillingupstream_rate_limitrO   rX   ri   rj   _primary_runtimerK   r  r   r  	monotonicr  r?  r  _fallback_indexr8   _fallback_chainr   _FALLBACK_EXHAUSTED_COOLDOWN_Srt  setr  rl   r   _try_activate_fallbackr  addrm   agent.backend_identityr  r  buildr7   r  rT   r  r  hermes_cli.fallback_configr  r   agent.secret_scoper  hermes_cli.model_normalizer  r   _is_azure_openai_urlhermes_cli.providersr  rs  endswithr   _is_direct_openai_url&_provider_model_requires_responses_apir   r   r  requested_providerr  rE  r  clearr  r  _credential_pool_entry_idagent.credential_poolr  has_credentialsr   r  r  r  r  r  _anthropic_api_keyr  _anthropic_clientr  r   _client_kwargsrJ   _replace_primary_openai_clientagent.agent_runtime_helpersr  _anthropic_prompt_cache_policy_use_prompt_caching_use_native_cache_layout_ensure_lmstudio_runtime_loadedr  agent.model_metadatar  r6   update_modelhermes_cli.configr  hermes_constantsr  r  rn  r  _pending_fallback_noticer   rE  )4rY   r'  fallback_already_activecurrent_providerprimary_providerbackoff_countbackoff_seconds_existing_cooldownro  fb_keyunavailabler{  fb_modellocal_skip_reasonr  r  current_identfb_identr  r  fb_base_url_hintfb_api_key_hintr  	fb_client_resolved_fb_modelr  	_norm_errfb_api_modefb_base_url_fb_is_azurer  	old_modelold_provider_existing_pool_pool_providerr  fallback_poolr   _fb_timeoutr  r  r  effective_key
fb_headersr  r  _fb_ctx_api_keyfb_context_lengthr  r  _reasoning_errrZ  s4                                                       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 $E+FJJM.;a.?E+!"](:";UCCO(,(8(8?(JE%LS"0DmVWFW   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 NMMMMMMM#))
B//eWb))WUJ339r:: *  M
 $$&&$$* %  H
 X}55 4&=#9#S]=S	
 	
 	

 ++F333
X4BBBBBB 	EDDDDDFF:..4";;==E//33  	C 56F U U 	C^m 	C555555(j)9::BdO(?(?x4.,). ). ).%	% NN@   OOF###//777	OOOOOO33HkJJHH 	 	 	NNK+y       	 )),--11+>>.((+KKCCC
 ;:::::'-11KK;&&!!#&&,,..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 7.K"?"?Q>  
 *.&26/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MMMMMM%%e,,, 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   Cj0 
S j0 
T'T	j0 	TH
j0 A
]$ #j0 $
^.^j0 ^H"j0 8Ah 
j0 
i !h;6j0 ;i  A.j0 0
l:Alllr;   api_call_countc                `   45 t          d j         d           dt          j                     4d}dI 4fd}d}|                    d	|d
           	                                  }g }|D ]}|                                }	                     ||	           dD ]}
|	                    |
d           dD ]}|	                    |d           t          |	           d |	D             D ]}|	                    |d           |rl j
        } j        dk    rCt           dd          }|0t          |dd          }|r|                    d          r|d         }                     |	|           |                    |	            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# t4          $ 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&<   tY                     }$i }%	 dd'l-m.}&  |& j                  }'|':|'/                    t           d(d          |$pd j
         j         j         )          }%n# t4          $ r Y nw xY w|%r|*                    |%           |$rNd*|%vrJ j        pd                                                                d+k    s 0                                r|$|d*<    j
        d,k    r j        pd                                                                d+k    s 0                                r\ j1        U j1        dk    rJ	 te           j1                  }(n# tf          th          f$ r d}(Y nw xY w|(d-|(cxk    rd.k    rn n	d/|(d0g|d1<   |r||#d2<    j#        d3k    r &                                })|)5                     j
        |d j)         j          j6         7                                t           d4d          5          }*tq           |*          }* ||* j9        d6          }|)'                    | j6        7          }+|+j(        pd                                }"ni :                    d89          5 ||#5fd:d6          } &                                '                    |          }+|+j(        pd                                }"|"rZd;|"v r4tw          j<        d<d|"tv          j=        =                                          }"|"rd>}|                    d?|"d
           nyd@}"nu j#        d"k    r $                    |          }|                    d#d            %                    |          }, &                                }-|-'                    |,          }.|.j(        pd                                }"n j#        d3k    r &                                }/|/5                     j
        |d j6         j)         j          7                                t           d4d          A          }0tq           |0          }0 ||0 j9        d6          },|/'                    |, j6        7          }1|1j(        pd                                }"n j
        |d$}#|||#d%<    j)        -|#*                     +                     j)                             |||#d&<   |r||#d2<    :                    dB9          5 ||#5fdCd6          } &                                '                    |          }1|1j(        pd                                }"|"rXd;|"v r4tw          j<        d<d|"tv          j=        =                                          }"|"rd>}|                    d?|"d
           nd@}"nd@}"nL# t4          $ r?}2t|          ?                    dD|2           dE j         dFt          |2           }"Y d}2~2nd}2~2ww xY wddGlAmB}3 |3C                    4|H           n"# ddGlAmB}3 |3C                    4|H           w xY w|"S )JzSRequest a summary when max iterations are reached. Returns the final response text.u$   ⚠️  Reached maximum iterations (z). Requesting summary...ziteration-summary:failedretry_countr1   c                  ddl m} |                    | |t          t	          dd          pd          t          t	          dd          pd          t          t	          dd          pd          d|d	d
          S )Nr   	relay_llmrT   rR   r   r  r  iteration_summary)r  api_request_id	call_roler  T)r   
model_namemetadatadefer_logical_completion)rY   r  execute_currentr7   rX   )requestr#   r  r  rY   summary_api_request_ids       r%   _managed_summary_callz4handle_max_iterations.<locals>._managed_summary_call+  s    ######((WUJ33AzBB75'266<"==E:r22H6H  #90*  &* ) 
 
 	
r'   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_namer3  r4  	timestampc                f    g | ].}t          |t                    |                    d           ,|/S )r  )r6   r7   r   )r?   ks     r%   
<listcomp>z)handle_max_iterations.<locals>.<listcomp>d  s9     ` ` `qz!S7I7I `all[^N_N_ ` ` ` `r'   r  r   last_aggregator_slotr   rz  rR   r'  systemr   r   r  r   r  r   Tmedium)enabledeffort)nous_portal_tagstagsr   rF   )r   r;   temperaturereasoning_effortr   r   )r   r  r   r  r  rT   
openrouterzopenrouter/pareto-coderc   g      ?zpareto-router)r5  min_coding_scorepluginsr   r   r  )r   r;   rF   r  r  r  r  r  )r  )strip_tool_prefixiteration_limit_summaryr)  c                2     j         j        j        di | S Nr>   r  r  r  r  summary_clients    r%   r&   z'handle_max_iterations.<locals>.<lambda>	  !    $JN$7$C$J$U$UW$U$U r'   z<think>z<think>.*?</think>\s*r%  successr+  z>I reached the iteration limit and couldn't generate a summary.)r   r;   rF   r  r  r  r  r  iteration_limit_summary_retryc                2     j         j        j        di | S r  r  r  s    r%   r&   z'handle_max_iterations.<locals>.<lambda>M	  r  r'   z"Failed to get summary response: %sz"I reached the maximum iterations (z!) but couldn't summarize. Error: r  )outcome)r  r1   )Dprintmax_iterationsr   r  r   _should_sanitize_tool_callsr  _copy_reasoning_content_for_apir  r   r   rT   rX   rK   #_sanitize_tool_calls_for_strict_apird  ephemeral_system_promptri   prefill_messages	enumerateinsert_sanitize_api_messages#_drop_thinking_only_and_merge_usersr  r  r  r   r  rQ   rj   r  *_resolve_lmstudio_summary_reasoning_effortr  agent.portal_tagsr  r  _build_api_kwargsr  r  normalize_responser   r  r   r  r   r   r   r   r  r  r]   r   r   r  r  r  r   r  _ensure_primary_openai_clientr   r   r=  rl   rm   r7   rY   r  complete_logical_call)6rY   r;   r  summary_call_outcomer  summary_request_needs_sanitizer  rR  api_msginternal_fieldschema_foreigninternal_key_sanitize_model_moa_client	_agg_sloteffective_system
sys_offsetidxpfmsummary_extra_bodyr  
_OMIT_TEMP_raw_summary_temp_omit_summary_temperature_summary_temperaturer  _is_lmstudio_summary_lm_reasoning_effort_portal_tagscodex_kwargssummary_response_ct_sum_cnr_sumfinal_responsesummary_kwargsr  profile_extra_bodyr   r  _ps_tsum_ant_kw_summary_resultretry_response	_ct_retry
_cnr_retry_tretry_ant_kw2_retry_resultrZ  r  r   r  s6   `                                                   @@r%   handle_max_iterationsrY  $  s0   	
_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 #7+++ ` `G ` ` ` 0 0L$//// Z #(+>U**")%4"@"@K".$+K9OQU$V$V	$ Aw)?)? A.7.@O99'9YYY(((( 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,,..,,+)$/%*%;"6"'"@"@"B"B$U,A4HH - 	 	 APP#8#84 !$ $ $ 
 #(":":;K_d_x":"y"y"1"9"?R!F!F!H!H!&!D!D4 "E " " $9#8"UUUU !$ $ $ 
 #("6"6"8"8"K"KL\"]"]"1"9"?R!F!F!H!H G	bN**!#(@"n\^\e!f!f!f!l!l!n!n b'0$ 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"//+)"6$/%*%;"'"@"@"B"B$U,A4HH 0 	 	 B%RR!6!64 !" " "
 !( : :>]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!&!D!D: "E " " $9#8"UUUU !$ $ $ 
 !& 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+4(OO[^$T$TUUUU%eNN!a ~ ~ ~;Q???}e>R}}uxyzu{u{}}~ 	$#####''"( 	( 	
 	
 	
 	
 	$#####''"( 	( 	
 	
 	
 	

 s   G,f" I f" If" IG f" AQ1 0f" 1
Q>;f" =Q>>Cf" U  f"  U63f" 5U66P+f" !h "
g+,5g&!h &g++h h+task_idc                   	 t          |          r | j        rt          j        d| d           n!t	                                          |           n:# t          $ r-}| j        rt                              d||           Y d}~nd}~ww xY w	 d}	 ddl	m
}  |            }n<# t          $ r/ t          t          j                            d                    }Y nw xY w|r#| j        rt          j        d	| d           dS dS t	                                          |           dS # t          $ r4}| j        r"t                              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).

    Skips ``cleanup_browser`` in headed mode so the browser window stays
    visible between turns. The inactivity reaper in
    ``browser_tool._cleanup_inactive_browser_sessions`` still handles
    idle sessions.
    z0Skipping per-turn cleanup_vm for persistent env z; idle reaper will handle it.z$Failed to cleanup VM for task %s: %sNFr   )_is_headed_modeAGENT_BROWSER_HEADEDz5Skipping per-turn cleanup_browser for headed session z)Failed to cleanup browser for task %s: %s)r   r>  r?  r   r.   
cleanup_vmr   rl   rm   tools.browser_toolr\  rO   r   r  rK   cleanup_browser)rY   rZ  rZ  headedr\  s        r%   cleanup_task_resourcesrb  m	  s    OW%% 	&$ 3w 3 3 3  
 EEW%%% O O O  	ONNA7ANNNOT	B::::::$_&&FF 	B 	B 	B"*..)?@@AAFFF	B 	+$ 3G 3 3 3      EE!!'***** T T T  	TNNFQRSSSSSSSSS	T 	T 	T 	T 	T 	TTsZ   AA 
B
#BB
D& B" !D& "6CD& C$D& !D& &
E$0#EE$dropped_tool_namesc                   t          | |d|          }t          d|t                    }t          t          ||g||pd          S )a  Build a partial-stream-stub response for mid-stream drop scenarios.

    Used when the SSE stream ends without a ``finish_reason`` after
    delivering content (text-only drops, tool-call-arg drops).  The stub
    is tagged ``PARTIAL_STREAM_STUB_ID`` with ``FINISH_REASON_LENGTH`` so
    the conversation loop enters its continuation/retry path instead of
    silently accepting truncated output as a complete turn (#32086).
    Nr,  r   r   r   r   indexmessager#  r5  r   r   usage_dropped_tool_names)r   r   r
   )r,  full_contentfull_reasoningr  	usage_objrd  mock_messagemock_choices           r%   _build_partial_stream_stubrr  	  sr     #(	  L "*  K
 !.6$   r'   )r   c               H   &'()*+,-./0123456789:;<=>?@ABC  j         rt          d          t                     r                               S  j        dk    r0 _        	                                d _        S # d _        w xY w j        dk    rxdddAddi:ddi9d	t          j                    i&                    d
d          }t                     }t                      :fd.&. 9Afd}t          j        t          |          d          }|                                 |                                r|                    d            j         rt          d          t          j                    &d	         z
  }||k    rt                               d|||                    dd                                          dt'          |           d                    dd           d           t)                      	 ddlm}  ||           n2# t.          $ r%}	t                               d|	           Y d}	~	nd}	~	ww xY wt          j                    &d	<   t                      t3          dt'          |           dt'          |           d          Ad<   n|                                 j         rt          d           Ad         Ad         Ad!         t5                      Ad!         S ddg d"At                      dddd#>d$d%i?t          j                    @d$di0d%d&d|>?@fd)2d* 77>?@fd+3d}7fd/,d}, >?@fd0+ddi:ddi9ddi=d	t          j                    i;d8t          j                    Bdt9                      ddd1Cd2di<d~<fd41d<fd5*d=BCfd74d}BCfd8)dBCfd;5dBCfd<6dBCfd=-:fd>/d*-/123568 9;=>Afd?(*/1 9;>fd@''()*+024 9:=>AfdA}
t;           j         j                  }||}ntA          dBdC          }|dCk    r j!        rtE           j!                  rdD}	 ddEl#m$}  |            }tK          |tL                    r|                    dF          nd}tK          |tL                    r@|                    dG          }tK          |t&          tN          f          rtO          |          }n# t.          $ r Y nw xY wtA          dH|          8t                               dI j!        8           nutQ                    }|dJk    rtS          |dK          8n|dLk    rtS          |dM          8n|8ddNl*m+}  |                    dO                    }|tS          8|          8t          j        t          |
          d          }|                                 t          j                    }dP}|                                r|                    d           t          j                    }||z
  |k    r|}t'          |;d	         z
            }||k    r_8'8tO          dQ          k    rdRt'          8           dS}ndT} ,                    dU                    dOdV           dW| dX| dY           n -                    dZ| d[           t          j                    ;d	         z
  }|8k    r*tQ                    }t                               d\|8                    dOd          |d]                                d^t'          |           d                    dOd           d_|d]d`           	  )da            +da           n# t.          $ r Y nw xY wt)                       j        dbk    rn	 t          j                    ;d	<    ,                    dct'          |           dd            -                    det'          |           df            j         rVd0d$<   t                               dg           	  )dh            +dh           n# t.          $ r Y nw xY wt          di          |                                 j         rt          dj          Ad         39d         r"t]           dkdT          pdT/                                pd}ta          A                    dl          pg           }|rdm                    |ddn                   }tc          |          dnk    r|dotc          |          dnz
   dpz  }dq| dr}|pdT|z   }	  2                    |           n# t.          $ r Y nw xY wt                               ds|tc          |pdT          Ad                    tf          }n8t                               dttc          |pdT          Ad                    tf          }ti          du|ddv          } d}!	 ddwl5m6}"m7}#  |"Ad         tq          t]           dxdT          pdT          tq          t]           dOdT          pdT          y          }$|$j9        |#j:        k    }!n# t.          $ r d}!Y nw xY wti          tv          t]           dOd          ti          d| |z          gd|pd{          }%|!rd|%_<        t5                      |%S Ad         Ad!         t5                      Ad!         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  rD  doneFrf  r  r	  r
  c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S Nrt  Tr   first_delta_firedr   s   r%   _fire_firstz5interruptible_streaming_api_call.<locals>._fire_first	  sq    $V,  ,0!&)"N$$$$$    DD	      
 
,,c                    d } 	 ddl m} ddlmmmmmm g dd id,fd}fd}fd	}fd
}fd}d-fd}d.fd}|	                    t                    |t          t          dd          pd          t          t          dd          pd          t          t          dd          pd          ||j        d |d dt          dd           t          dd          rdn't          t          d d          pd          dk    rd!nd"d#d$%          }  d&| i                                r|nd |j        sj        r|nd fd'fd()          }	| j        p|	d*<   n# t&          $ r}
|
d+<   Y d }
~
nd }
~
ww xY w| |                                  d S d S # | |                                  w w xY w)/Nr   r  )r  r  r   is_streaming_access_denied_errorr  stream_converse_with_callbacksr3   next_api_kwargsdict[str, Any]c                
   t          |           }|                    dd          }|                    dd             |          }	  |j        di |}n# t          $ r} 
|          rdd_                            d           t                              dt          |          j	                     |j
        di |          cY d }~S  	|          r |            d }~ww xY w|                    dg           S )	Nr	  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.streamr>   )rJ   r  converse_streamr   _disable_streaming_safe_printrl   r  rX  rY  r  rK   )r  final_kwargsr  r   r  r  r  rY   r  r  r}  r  s         r%   _open_bedrock_streamzUinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._open_bedrock_stream
  sx   #'#8#8L)--.BKPPF $$%;TBBB88@@F'=v'='M'M'M'M$   
 <;LII 7;E4!--!V  
 #KK!S $\ 2 2 ;  
 $?#> / ? ?, ? ?$ $       54\BB >55f===-. (++Hb999s%   	A 
C,!A)C'
C,C''C,c                P                                       |            dd<   d S )NTrf  )_fire_stream_delta)r   rz  rY   deltas_were_sents    r%   _on_textzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_text4
  s3    KMMM,,T222.2$U+++r'   c                F                                       |            d S r    )_fire_tool_gen_started)r   rz  rY   s    r%   _on_toolzIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_tool9
  s(    KMMM0066666r'   c                F                                       |            d S r    )_fire_reasoning_delta)r   rz  rY   s    r%   _on_reasoningzNinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._on_reasoning=
  s(    KMMM//55555r'   c                 8     dt                     i          S Nr  )rB   )intercepted_eventsr~  s   r%   _finalize_bedrock_streamzYinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._finalize_bedrock_streamA
  s)    99!4(:#;#;<  r'   _streamr   r0   r   c                ,    t                    d<   d S Nr3   )r   )r  rY   writer_tokens    r%   _bedrock_stream_createdzXinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._bedrock_stream_createdF
  s    ,?,F,FL)))r'   _eventrO   c                <    d         }|d u pt          |          S r  )r   )r  tokenrY   r  s     r%   _accept_bedrock_eventzVinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>._accept_bedrock_eventI
  s'    (1E D=R,DUE,R,RRr'   r   rR   rT   r  r   c                    | S r    r>   )r   s    r%   r&   zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>V
  s     r'   c                >    t          t          | dd                     S Nr   )rO   rX   )rA  s    r%   r&   zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>X
  s!    $)T::C C r'   r  _current_api_request_idis_subagentF	delegatedr  fallbackprimaryr  r  r  T)r   r   r  	finalizeron_stream_createdon_chunkchunk_adapteraccept_chunkcompleted_response_predicater  r  r  c                      j         S r    )r5  r   s   r%   r&   zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>o
  s
    u/I r'   c                 R                          dt          j                              S )Nr  )__setitem__r  )_bedrock_last_events   r%   r&   zIinterruptible_streaming_api_call.<locals>._bedrock_call.<locals>.<lambda>p
  s    %8%D%DS$)++%V%V r'   )on_text_deltaon_tool_starton_reasoning_deltaon_interrupt_checkon_eventrA  rE  r  r  )r  r   r0   r   r  r   r0   rO   )rY   r  r  r  r  r  r}  r  r~  r  rJ   r7   rX   r   r1   _has_stream_consumersr@  rA  rL  r   close)r  r  r  r  r  r  r  r  r  streamed_responserZ  r  r  r  r  r}  r  r~  r  r  rz  rY   r   r  r\  s              @@@@@@@@r%   _bedrock_callz7interruptible_streaming_api_call.<locals>._bedrock_call
  s   Fp#++++++                &(" ': : : : : : : : : : :@3 3 3 3 3 3 3
7 7 7 7 7 76 6 6 6 6 6     
G G G G G G GS S S S S S S #))$$("75,#C#C#IrJJWUJ;;HyII"75'2#>#>#D"EE6&=/6"5"5!62 2 %-*1!#<d+ +
  'umUCC+KK  #752CQ#G#G#L1MMPQQQ ",!*  .27 *  : %C$Bv&.3.I.I.K.K"U((QU"*8=8P'yTYTo'y}}uy'I'I'I'IVVVV% % %! &,%:%O>Oz"" $ $ $"#w$ %LLNNNNN &%6%LLNNNN &s0   E5F F9 
FFF9 FF9 9GTrk  rn  ro  z)Agent interrupted during Bedrock API calluk   Bedrock stream stale for %.0fs (threshold %.0fs) — no events received. region=%s model=%s. Aborting call.r   r{  u"   ⚠️ No events from Bedrock for z
s (model: z). Aborting...r   )r  z)bedrock: stale client eviction failed: %sz&Bedrock stream produced no events for zs (threshold uF   s) — aborting stalled stream so the retry/fallback path can recover.rE  z7Agent interrupted during Bedrock API call (post-worker)rA  )rA  rE  partial_tool_names)r   diagrF  r3   r.  r  r  r7   c               |    5  | d<   |d<   t          j                    d<   d d d            n# 1 swxY w Y   | S rH  rI  rK  s     r%   rM  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
 rN  c                    t          | dd           }t          |          r|S t          | dd           }t          |dd           }t          |          r|S d S )Nr  rA  )rX   r  )r  r  rA  s      r%   _stream_close_callablez@interruptible_streaming_api_call.<locals>._stream_close_callable
  s`    ..E?? 	L6:t44'400E?? 	Ltr'   c                     |           | S 5  | d<   dd<   t          j                    d<   d d d            n# 1 swxY w Y   | S )Nr   r  r3   rF  rI  )r  r  r+  rL  r,  s    r%   _set_request_stream_handlezDinterruptible_streaming_api_call.<locals>._set_request_stream_handle
  s     "!&))1M  	G 	G.4!(++3(1:1D1F1F!+.	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G 	G s   !>AAr'  r0   r   c                     |           }|d S 	  |             t                               d|           d S # t          $ r'}t                               d||           Y d }~d S d }~ww xY w)Nz%Streaming response handle closed (%s)z/Streaming response handle close failed (%s): %s)rl   r  r   r   )r  r'  r  r   r  s       r%   _close_request_stream_handlezFinterruptible_streaming_api_call.<locals>._close_request_stream_handle   s    &&v..=F	EGGGKK?HHHHH 	 	 	LLA        	s   %9 
A*A%%A*c                h   	5                       d          }                     dd          }                     d          }|dk    o|d uo|d uo|t          j                    k    }|rW                     dd          dk    r                    ||            n                    ||            	 d d d            d S d d<   d d<   d d d            n# 1 swxY w Y   |d S |dk    r ||            d S |dk    r                    ||            d S                     ||            d S )Nr   r3   r.  rF  r  r   r)  rP  )
r'  r  request_kindrF  rS  r  rY   r+  rL  r,  s
        r%   rT  zDinterruptible_streaming_api_call.<locals>._close_request_client_once  s   
 ! 	6 	6266x@@N.227HEEL-11+>>I ( 7"$.7T)7 !4!6!66	   
 '**7H==AUUU99&v :     66~f6UUU1	6 	6 	6 	6 	6 	6 	6 	62 /3!(+15!+.5	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	6 	66 !F 8##((@@@@@11111.1PPPPP..~f.MMMMMs   B2C
CC C)current	cancelleddiscarded_chunksdiscarded_bytesr  r   c                    | d<   | S r  r>   )r  managed_stream_holders    r%   _set_managed_streamz=interruptible_streaming_api_call.<locals>._set_managed_streamQ  s    *0h'r'   c                                          dd           } | d S t          | dd           }t          |          r:	  |             d S # t          $ r  t                              dd           Y d S w xY wd S )Nr  r  z&Managed provider stream cleanup failedTrw  )r  rX   r  r   rl   r   )r  r  r  s     r%   _close_managed_streamz?interruptible_streaming_api_call.<locals>._close_managed_streamU  s    &**8T::>F..E?? 	VV V V VEPTUUUUUUV	V 	Vs   
A	 	&A32A3r1   c                     5  dxx         dz  cc<   t          d                   } d d d            n# 1 swxY w Y   dd<   | S )Nr  r   Frf  )r1   )
attempt_idprovider_tool_in_flightstream_attempt_lockstream_attempt_states    r%   _start_stream_attemptz?interruptible_streaming_api_call.<locals>._start_stream_attempt`  s      	> 	> +++q0+++1)<==J	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> 	> */&s   &6::c                    5  t                              d          pd          }|rd                             |           d d d            n# 1 swxY w Y   |rt                              d||            d S d S )Nr  r   r  z&Marked stream attempt %s cancelled: %s)r1   rK   r  rl   r   )r'  r  r  r  s     r%   _cancel_current_stream_attemptzHinterruptible_streaming_api_call.<locals>._cancel_current_stream_attemptg  s      	? 	?.229==BCCG ?$[155g>>>	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	?  	LL8    	 	s   AAAAstream_attempt_idrO   c                    5  | t                              d          pd          k    o	| d         v	 cd d d            S # 1 swxY w Y   d S )Nr  r   r  )r1   rK   r  r  r  s    r%   _stream_attempt_is_activezCinterruptible_streaming_api_call.<locals>._stream_attempt_is_actives  s      	 	!S)=)A)A))L)L)QPQ%R%RR O%-A+-NN	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   3AAAc                P    5  | d         v cd d d            S # 1 swxY w Y   d S )Nr  r>   r  s    r%   _stream_attempt_was_cancelledzGinterruptible_streaming_api_call.<locals>._stream_attempt_was_cancelledz  s      	J 	J$(<[(II	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	J 	Js   
c                   	 t          t          |                    }n# t          $ r d}Y nw xY w5  dxx         dz  cc<   dxx         |z  cc<   d         }d         }d d d            n# 1 swxY w Y   |dk    rt                              d| ||           d S t                              d| ||           d S )Nr   r  r   r  z[Discarding chunk from superseded stream attempt %s (discarded_chunks=%s discarded_bytes=%s)zUDiscarded stale stream chunk from attempt %s (discarded_chunks=%s discarded_bytes=%s))r8   reprr   rl   rm   r   )r  r   chunk_bytesr  r  r  r  s        r%   _discard_stale_stream_chunkzEinterruptible_streaming_api_call.<locals>._discard_stale_stream_chunk~  si   	d5kk**KK 	 	 	KKK	  	F 	F !34449444 !2333{B33334FG23DEO		F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F
 q  NN;!      LL;!     s     //1A11A58A5c                 f     d         s%r%d d<   	               d S # t           $ r Y d S w xY wd S d S rv  rw  rx  s   r%   _fire_first_deltaz;interruptible_streaming_api_call.<locals>._fire_first_delta  sq     ( 	^ 	(,f%        		 	 	 	r{  c                   ,-./0123456789 ddl /t          Cj        Cj                  }||nt	          dd          ,||0nt	          dd          00dk    r?Cj        r8t          Cj                  r$,0t                              dCj        0           n>0dk    r8B6Bt          d          k    r#B0k    rB0t                              d	0           |t          ,d
          nd-g 3i 8t                      }i }i }d4d5d7g 6d9C                                ..Hd<   ddi1ddi2dZ,-/>0C2Ffd}d[.1Cfd}d\@1CDFG fd}d]3456789fd}ddlm}	  =|	                    D|t!          t#          Cdd          pd          t!          t#          Cdd          pd          t!          t#          Cdd          pd          |||d  d!t#          Cd"d          t#          Cd#d$          rd%n't%          t#          Cd&d          pd          dk    rd'nd(d)d*+                    }
Cj        d,k    r ?|
           |
D ]}t'          j                    Fd-<   C                    d.           	 t%          .                    d/d                    d0z   .d/<   .                    d1          Fd-         .d1<   	 t%          .                    d2d                    t-          |          z   .d2<   n# t.          $ r Y nw xY wn# t.          $ r Y nw xY wCj        rJ	 |
                                 n1# t.          $ r$ 2d         }|C                    |d34           Y nw xY w n @           s ; |           ;|j        s>t9          |d          r|j        r|j        5t9          |d5          r|j        r|j        9|j        d         j        }t9          |d          r|j        r|j        5t#          |d6d          pt#          |d7d          }|r46                    |            <             C                     |           |r|j!        r3                    |j!                   8s* <             C"                    |j!                   d*Ed8<   nMCj#        rF	 C#                    |j!                   C$                    |j!                   n# t.          $ r Y nw xY w|r*|j%        r"|j%        D ]}|j&        |j&        nd}|j'        pd}||vr|||<   |r)||v r%|||         k    rtQ          8d9:          d0z   }|||<   |r|||<   ||         }|8vr:|j'        }tS          |t$                    rt!          |          }|pdd;ddd<dd=8|<   8|         }|j'        2|j'        }tS          |t$                    rt!          |          }|r||d><   |j*        rM|j*        j+        r|j*        j+        |d;         d?<   |j*        j,        r |d;         d@xx         |j*        j,        z  cc<   t#          |dAd          }|Ft9          |dB          r6tS          |j-        t\                    r|j-        ni                     dA          }|)t9          |dC          r|/                                }||dA<   |d;         d?         }|rS||vrO|0                    |            <             C1                    |           IdD                             |           |j        d         j2        r|j        d         j2        4t9          |d5          r|j        r|j        9 :              A           r/3                    dE  dF          |
j4        |
j4        }t          5                    dGCj        pdHCj        pdH           d*C_6        |j        }tS          |tn          tp          f          r
|r|d         nd}t#          |dId          }|t#          |d6d          pt#          |d7d          }tS          |t                     r!|r <             C                     |           t#          |dJd          }tS          |t                     r!|r <             C"                    |           |S d9                    3          pd}d}d$} 8rg }tu          8          D ]}8|         }!|!d;         d@         }"|!d;         d?         pdK}#|"rZ|";                                rF	 ty          j=        |"           n0# tx          j>        $ r t          |"|#          }$|$dLk    r|$}"nd*} Y nw xY w|                    t          |!d>         |!dM         |!                    dA          t          |!d;         d?         |"<          N                     43s6s8st          dO          | o4du }%|%rb8fdPtu          8          D             }&t          B                    dQ|&           t          7|d9                    6          pd59|&pdR          S 4du o3o8 }'|'rBt          B                    dS           t          7|d9                    6          pd59          S 4pdT}(| rdU}(d9                    6          pd})t          7|||)V          }*t          d|*|(W          }+t          dXt!          t          jE                              z   5|+g9Y          S )^z#Stream a chat completions response.r   NHERMES_API_TIMEOUTg      @HERMES_STREAM_READ_TIMEOUTr_  uD   Local provider detected (%s) — stream read timeout raised to %.0fsinfuV   Cloud reasoning stream — read timeout raised to %.0fs to match stale-stream detectorr`        >@r+  r  r3   r  r  c                H   i | d                               d}t          j                  sddi|d<                        d|                    }|	d<   t	          j                    
d	<                       d
            |j        j        j        di |S )NT)connectreadwritepool)r  rp  include_usagestream_optionschat_completion_stream_requestr0  r3   r  z)waiting for provider response (streaming)r>   )	Timeoutr   r  r1  r  r;  r  r  r  )r  stream_kwargsr  _base_timeout	_conn_cap_httpxrM  _stream_read_timeoutrY   attempt_request_clientlast_chunk_times      r%   _open_streamzVinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>._open_stream  s    	!	!>>%-'"	 *  	 	 	M -U^<< J3BD2I./0033;, 4   N /="7+#'9;;OC !!"MNNN9>&29JJMJJJr'   
raw_streamr   r0   r   c                    t          | dd           }                    |                               |                               |                               |           t                    d<   d S )NrA  r3   )rX   _capture_rate_limits_capture_credits_stream_diag_capture_response_check_openrouter_cache_statusr   )r  rA  _diag_writer_tokenrY   s     r%   _stream_createdzYinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>._stream_created  s~    z:t<<H&&x000""8,,,//x@@@00:::%8%?%?M'"""r'   _chunkrO   c                   	 t          | dd           }|rt          |d         dd           nd }t          |dd           rd	d<   n# t          $ r Y nw xY w 
          sdS d         }|At          |          s1t                              d	                    d
d                     dS t          j                    d<   dS )Nr   r   r   r   Trf  Fr3   zxStreaming attempt superseded by a newer stream; stopping consumption to preserve the single-writer invariant (model=%s).r   r{  r  )rX   r   r   rl   rm   rK   r  )r  r   r   r  r  r  rY   r   r  r  r  s       r%   _accept_stream_chunkz^interruptible_streaming_api_call.<locals>._call_chat_completions.<locals>._accept_stream_chunk  s    !&)T::>EO
GT:::45,55 :59+E2   ,,->?? u!'*E )A%)O)O " NN7I66	   u
 $(9;;OC 4s   AA 
AAc                     fdt                    D             } d                              pd d                              pd | pd dpddgdS )Nc                     g | ]
}|         S r>   r>   )r?   rh  tool_calls_accs     r%   r  zsinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>._relay_final_response.<locals>.<listcomp>'  s    TTTE./TTTr'   rR   )r,  r   r   r   stop)ri  r#  )r   r   rk  )ro   rn   )r   content_partsr#  r  reasoning_partsr,  r	  ro  s    r%   _relay_final_responsez_interruptible_streaming_api_call.<locals>._call_chat_completions.<locals>._relay_final_response&  s    TTTTVN=S=STTTJ# %)')ww}'='='E131I1I1QT*4*<	$ $ *7)@& 
 #  r'   r  r   rR   rT   r   c                "    t          | d          S r  )rE  r9   s    r%   r&   zRinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>.<lambda>D  s    75);T;T r'   r  r  r  Fr  r  r  r  r  T)	r   r   r  r  r  r  r  r  r  r  r  receiving stream responsechunksr   first_chunk_atbytesinterrupt_stream_close_failedr)  rk  r   r   rf  rg  )r   r   r9  )r5  rX  r   r:  r5  r   r   r:  r-  r1  r  zstream attempt z was supersededz}Streaming request returned a final response object instead of an iterator; switching %s/%s to non-streaming for this session.r{  ri  r   ?r7  rX  )r5  rX  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   r   r  r>   )r?   r>  r	  s     r%   r  zTinterruptible_streaming_api_call.<locals>._call_chat_completions.<locals>.<listcomp>x  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.rc  zkStream ended with no finish_reason after delivering text with no tool calls; treating as a mid-stream drop.r
  lengthrf  rg  zstream-)r5  r   r   rk  r  r  r   r0   r   )r  r   r0   rO   )r0   r  )Fhttpxr   rT   r   r   r  r   rl   r   r]   r   r  _stream_diag_initrY   r  r  r7   rX   r1   r  r;  rK   r   r   r5  r  r*  r   rE  rk  r   r   r  r   r  rA  _record_streamed_assistant_textr   rh  r5  r   r6   r   r   r   r-  rJ   r1  r  r  r#  RemoteProtocolErrorrL  r  r  rB   tuplern   ro   ri   jsonloadsJSONDecodeErrorr   r   r   rm   rr  r   r  )Jr  _provider_timeout_cfgtool_gen_notified_last_id_at_idx_active_slot_by_idxr  r  r  r  r  r  r   r  r   rL  tc_deltaraw_idxdelta_idnew_slotr>  _tc_identry_new_idra  r   rL  r   first_choiceri  r   rm  mock_tool_callshas_truncated_tool_argsr   r   r  repaired_tool_args_dropped_no_finish_dropped_names_text_only_dropped_no_finisheffective_finish_reasonrn  rp  rq  r  r  r  r  r  r  r  r  r#  r  r  r,  r	  ro  r  r  r  r  rM  r  r  r  _stream_stale_timeoutrY   r   r  r  r  r+  r\  sJ   `                                           @@@@@@@@@@@@@@r%   _call_chat_completionsz@interruptible_streaming_api_call.<locals>._call_chat_completions  sB    !=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[	 !!$
 !#$&
 "	''))(-f% $")4	K 	K 	K 	K 	K 	K 	K 	K 	K 	K 	K 	K 	K2	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@	 	 	 	 	 	 	 	 	 	 	 	>	 	 	 	 	 	 	 	 	 	 	 	$ 	$#####$$wulB??E2FF
B77E:FFwugr::@bAA/"11-T-T 2&-e5NPT&U&U #5-??' wu.?CCHqIIAMM (Z&
 
 *.+   
 
2 >U"" '&v... m	( m	(E#'9;;OC !!"=>>>
"%eii!&<&<"="="Ah99-..6.=c.BE*+%(7A)>)>%?%?BWX]B^B^%^E'NN    D    ) LLNNNN  
 
 

 &<G%DN%1::*#B ;   
 ,,->?? ++,=uEEE= 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	(():;; 	,,D"3DDD    ,#2NKKR+)(y	   (,E$$,G ge}55:A

 
 lIt<<G"G%8$?? ;wT::  nc22 @~ @%%'''//???!'9d;;gs++ 6 6%%''',,W555!! 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 	   .l((0DI#1#9T	    T! ##"" 	%
 ( 		NNE   .l((0DI   #0"96" 	/&.#119T& &,	
 
 
 & 1
 
 

 3tz||,,, M	
 
 
 	
sm   :A	L6K;:L;
LLLL
LL$L99+M'&M'*4S
S,+S,d33*e e c                	    d}d}t          j                     d<                                    d<   ddidddd}ddlm} dd	lm |                                }d; fd}d<fd}d=fd} |                    |t          t          dd          pd          t          t          dd          pd          t          t          dd          pd          |j
        ||j        |dt          dd          t          dd          rdn't          t          dd          pd          dk    rdnd d!d"#                    }		 |	D ]}
d"}t          j                     d<                       d$           	 t                              d%d                    d&z   d%<                       d'          d         d'<   t                              d(d                    t          |
          z   d(<   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          }|d0k    r;t          |d1d          }|r&|s$                                  |           d"d2<   |d3k    r2t          |d4d          }|r                                  |           j        sAd5         }|7	 |                                }n!# t,          $ r |st/          d6          d w xY w	               d7         }||                    ddd           n# d7         }||                    ddd           w w xY w# 	               d7         }||                    ddd           w w # d7         }||                    ddd           w w xY wxY wj        rdS |1t          |d8d          s t          |d9d          t/          d:          |	|	j        s|S |                    |          }t          |d8d          s t          |d9d          t/          d:          |S )>aV  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.

        Uses ``request_client`` (a per-request Anthropic client registered with
        the stranger-thread abort machinery) rather than the shared
        ``_anthropic_client``, so the stale/interrupt watchdog can abort this
        stream's socket without closing the shared client mid-flight (#67142).
        Fr  r  r3   N)managerr  r   r  )sanitize_anthropic_kwargsr  r  c                    t          |           } |t          dd                      j        j        di |}|d<   |                                S )Nr  rR   )r  r6  r>   )rJ   rX   r;   r  	__enter__)r  r  r6  _stream_contextrY   r  r7  s      r%   _open_anthropic_streamzYinterruptible_streaming_api_call.<locals>._call_anthropic.<locals>._open_anthropic_stream  su    00L%%"5,;;    5n-4DD|DDG)0OI&$$&&&r'   r  r   r0   r   c                    | d<   	                      t          | dd                      n# t          $ r Y nw xY wt                    d<   d S )Nr  rA  r3   )r  rX   r   r   )r  r  r:  r  rY   s    r%   _anthropic_stream_createdz\interruptible_streaming_api_call.<locals>._call_anthropic.<locals>._anthropic_stream_created  s{    (2OH%33J
D99       %8%?%?M'"""s   %. 
;;r  rO   c                    d         }|t          |          rdS t                              d                    dd                     dS )Nr3   TzAnthropic streaming attempt superseded by a newer stream; stopping consumption to preserve the single-writer invariant (model=%s).r   r{  F)r   rl   rm   rK   )r  r  r  rY   r   s     r%   _accept_anthropic_eventzZinterruptible_streaming_api_call.<locals>._call_anthropic.<locals>._accept_anthropic_event  s[    !'*E} 8 F F}tNN( w	22	   5r'   r   rR   rT   r  r   r   r  r  r  r  r  r  r  T)	r   r   r  r  r  r  r  r  r  r  r  r   r  r  rX  content_block_startcontent_blocktool_user   content_block_deltar   
text_deltar   rf  thinking_deltathinkingr  zeProvider returned an empty stream with no events (possible upstream error or malformed event stream).r6  r   stop_reasonzjProvider returned an empty stream with no stop_reason (possible upstream error or malformed event stream).r  r  r  )r  r  rY   r  r  r7  AnthropicStreamAccumulatorr  r7   rX   finalizeobserver1   r;  rK   r   r   r5  r  r  r  get_final_messageAssertionErrorr   __exit__output_modifiedrA  )!r  has_tool_usesaw_stream_eventbase_final_messager  accumulatorr;  r=  r?  r  event
event_typeblockr  r   
delta_typer   thinking_textr  r6  final_messager  r:  r  r7  r  r  r  rY   r   r  r  r+  s!   `                    @@@@r%   _call_anthropicz9interruptible_streaming_api_call.<locals>._call_anthropic  s     !#y{{''))(-f% $&*d;;!######EEEEEE::<<	' 	' 	' 	' 	' 	' 	' 	' 	'	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@
	 
	 
	 
	 
	 
	 
	 
	 %$&wulB??E2FF
B77F;GGwugr::@bAA%.";$,4 4&-e5NPT&U&U #5-??' wu.?CCHqIIAMM (Z&
 
 *.+   
 
29	7 %K %K#' '+y{{$%%&ABBB&)%))Ha*@*@&A&AA&EE(Oyy!122:2A#2F./%(7A)>)>%?%?BWX]B^B^%^E'NN    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- ,X6
)-7-I-I-K-K**)   / ("2!W# # $(( 7%%'''))4&$$T4666 *)4&$$T46666 '	7%%'''))4&$$T46666 ' *)4&$$T46666 ' % 	4*.	4@@ +*M4@@H"G   )&2H)%%#,,-?@@y$77	}d;;C"G   sn   2O A?HO 
HO HD8O M' &O 'NO 	
N5 5$OP2
P(#P2$P//P2c                 d   dd l } t          dd          }	 t          |dz             D ]}              }!j        r d           t	          d          	 !j        dk    r0 !                    d	          d
          } |          &d<   n |          &d<                   &d         dnd           d S # t          $ r\}              d         rSt          	                    dt          |          j                   Y d }~                &d         dnd           d S t          || j        | j        | j        f          }t          || j        | j        t$          f          }!                    |          }t          |t(                    }	"d         rt+          &                    d                    p$d         }
d}|sg|seddlm} t          ||          rOt3          |dd           s>t5          |                                          d}t9          fd|D                       }|p|p|p|}|
o|o||k     }|sFt                              d|           |&d<   Y d }~                &d         dnd           d S 	 !                    d           n# t          $ r Y nw xY w	 !                                 n# t          $ r Y nw xY wg &d<   d"d<   d#d<   !                     ||dz   |dz   d%                    d                      d            d           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     rO!                     ||dz   |dz   d%                    d                      d             d            Y d }~!!                    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nd           d S d }~ww xY wn<# t          $ r/}|&d<   Y d }~               &d         dnd           d S d }~ww xY w	                &d         dnd           d S #                &d         dnd           w xY w).Nr   HERMES_STREAM_RETRIESr  r   interrupt_before_stream_retryz%Agent interrupted before stream retryr   anthropic_stream_requestr)  r  rA  stream_request_completestream_error_cleanupr3   uP   Streaming worker caught %s after request cancellation — exiting without retry.rf  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>   )r?   phrase_err_lower_previews     r%   rA   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>  s=       ?" ?"(. %+.@$@?" ?" ?" ?" ?" ?"r'   z9Streaming failed after partial delivery, not retrying: %srE  u9   

⚠ Connection dropped mid tool-call; reconnecting…

rt  Tr  )rE  attemptmax_attemptsmid_tool_callr  stream_mid_tool_retry_cleanupc              3      K   | ]}|v V  	d S r    r>   )r?   rd  _err_lower_sses     r%   rA   zBinterruptible_streaming_api_call.<locals>._call.<locals>.<genexpr>(  s<       3 3$* !'. 83 3 3 3 3 3r'   stream_retry_cleanup	exhausted)r  rE  rf  rg  rh  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   ranger5  r>  r  rW  r   rl   r   rX  rY  r6   ReadTimeoutConnectTimeoutPoolTimeoutConnectErrorr  ConnectionError_is_provider_stream_parse_errorr   rO   rK   r.  r`  rX   r7   rj   r  rm   r  _reset_stream_delivery_tracking_emit_stream_drop_log_stream_retryr  r  r}  r  r  	exception)'r  _max_stream_retries_stream_attemptr  r  rZ  _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}  re  rk  rY  r4  r  r  rT  r[  rM  r  rY   r  ry  r  r+  r\  s'                          @@r%   r]  z/interruptible_streaming_api_call.<locals>._callk  s	   %&=qAAE	#()<q)@#A#A t t$9$9$;$;! - T223RSSS*+RSSSi~)=== *=)<!BB'A C   "6	* * * .=_^-L-Lz**-C-CDU-V-Vz*F	 "!### '&*%1 *)+    M	 ! Z Z Z))+++ *'2 F GG,  
 d "!### '&*%1 *)+    k #-F.0EvGYZ# #K $.F/1K_]$ $L ,1+P+PQR+S+S('1!5E'F'F$ (. \!26"JJ';<<3 3 3<4U; 0 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"FFFFZ "!### '&*%1 *)+    S!!44!6     ) ! ! ! D!!!AACCCC( ! ! ! D!
 8:3427(/49)&1//"#$3a$7)<q)@*.!6!:!:6!B!B 0    767VWWW223RSSS ! (-$& | @@@@@@%a33 GA}VZ<[<[ -0VV\\^^N1- 03 3 3 3 3.?3 3 3 0 0, $p'p ,p 0	p
 ,p +-@@@!33&'(7!(;-@1-D.3%:%>%>v%F%F 4    ;:;QRRR667MNNN %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 "!### '&*%1 *)+    M	Z5tj	   	 	 	  F7OFFF!!### '&*%1 *)+    	k	tx	 "!### '&*%1 *)+    	 "!### '&*%1 *)+   s   A T0 A	C#T0 T,?T'T0 5E T'5T0 J21T'2
J?<T'>J??T'KT'
K%"T'$K%%AT' T0 CT'
T0 C1T'T0 'T,,T0 /V 0
U):U$?V $U))V !V/r   r   ra   )load_config_readonlyrY   local_stream_stale_timeout!HERMES_LOCAL_STREAM_STALE_TIMEOUTuB   Local provider detected (%s) — stale stream timeout set to %.0fsr_   r   r`   r   r   r   r  r  r   r   rR   rs  rt  ru  zRs with no output yet (provider may be slow or overloaded, or the model is thinkingrv  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.rh  r  z, context: ~z tokens). Reconnecting...stale_stream_killr   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  rh      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+  rf  )classify_api_errorr   rT   )rT   r   rg  rj  r  r9  )r  r   r0   r   r0   r   r0   r1   )r  r1   r0   rO   )r  r1   r0   r   )r  r1   )=r5  r>  r$  _interruptible_api_callr  r   r  rK   r   r   r<  r  r*   r  r  rn   rl   rm   r  r1   r   r  r  r   r   r  r   r=  r  r	   rT   r   r   r  r   r  r  r6   rJ   r]   rN   r   r   r   r  r;  rX   ri   rB   r8   r  r   r   agent.error_classifierr  r   r7   r'  content_policy_blockedr
   _content_filter_terminated)DrY   r   r   r  _bedrock_stale_timeoutr  r  _stale_elapsedr  
_inval_excr]  r   _stream_stale_timeout_base_local_defaultr  _cfg
_agent_cfg_vr   r   r   _last_heartbeat_HEARTBEAT_INTERVAL_hb_now_waiting_secsr  r  _partial_text_partial_names	_name_str_warn_stub_finish_reason	_stub_msgr  r  r   _cls_stubr  rY  r4  r  r  rT  r  r  rz  r  r[  r  rM  r  r  r  r  r  r3  r  ry  r  r  r  r+  rL  r,  r\  r  r  sD   ```                                   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r%    interruptible_streaming_api_callr  	  s     ! NLMMM "%(( 9,,Z888~***
 '5#	/00<<*.E''$E'.... ~+++"T22#UO!5>  #DIKK0 %..)={KK!=eZ!P!P
 	E"""	 	 	 	 	 	r	# r	# r	# r	# r	# r	# r	# r	# r	# r	#h )-88
 
 
 	
			jjll 5	FF3F) T&'RSSS
 "Y[[+>s+CCN 666C"$:#Z^^Iy%I%I	   $$T^9L9L T T)~~iCCT T T   #5)))OOOOOO--o>>>>    LLCZ        ,09;;#C( $E***
 #/FS=P=P F F"%&<"="=F F F# #w
 k jjll 5	| % 	^"#\]]]'?&/! *)&&&j!!RHHF
 '+TMM #H-#.** "5)3;                        )N )N )N )N )N )N )N )N )N )NV  u~$en DIKK(O !#.**UU	  &t,     	V 	V 	V 	V 	V 	V       
 
 
 
 
 
 
      J J J J J J J      6     R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
 R
ht t t t t t t t t t t tlJ J J J J J J J J J J J J J J J J JZ
 ,ENEKHHJ%/""%./Le%T%T" "U**u~*BSTYTbBcBc* 
	>>>>>>''))D.8t.D.DN'***$J*d++ /^^$@AAb3,// /%*2YYN 	 	 	D	 )*M~ ^ ^PN1	
 	
 	
 	
 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! 6u = =dKKKAGGIIIikkO
**,, s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# # #  ../BCCC**+>????    u%%% ~!555   $(9;;OC ###3~3F3F # # #   !!Ss>/B/BSSS   % 	R
 +/w'LL)  ../GHHH +*+CDDDD   "#PQQQg **,, sRr ! \Z[[[g"E" a	 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"""*s   /B 	B$H6 6
I% I  I% BT 
TT^3 3
_ ?_ (a? ?
bb?f 
f"!f"-A(j j%$j%)r  r"  rb  r  rY  rb  r  )r/   r   r0   r1   )r0   rO   )r\   r1   r0   r]   )re   r   r0   rf   )r0   rr   )r   rJ   r0   rJ   )r   r7   r   r]   r0   r]   )r   r   r0   r1   )r   r]   r   rO   r   r]   r   r   r   r]   r   rO   r   r]   r   r]   r0   r7   r  r  )r   rJ   r0   r]   )r   r   r0   r   )r   rJ   r    )r  rB   r  r  r0   rJ   )r#  r7   r0   rJ   )r   r7   rT   r7   r0   r   )ro  rJ   r0   rp  )ro  rJ   r0   rf   )r'  r  r0   rO   )r;   rB   r  r1   r0   r7   )rZ  r7   r0   r   )V__doc__
__future__r   r(   r  r?  r   r   r   r<  r  r   typesr   typingr   r   r   hermes_cli.timeoutsr   r	   r  r
   r   r  r   agent.errorsr   agent.turn_contextr   agent.gemini_native_adapterr   r  r   agent.message_contentr   agent.message_sanitizationr   r   agent.stream_single_writerr   r   tools.terminal_toolr   utilsr   r   r   r   	getLoggerrY  rl   rk   r  r*   r.   rN   r[   rd   rq   r   r   r   r   r   r   r   r   r   r   r   r  r$  rB  r  r"  rb  rn  rt  r  r  rY  rb  rr  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 ) ) ) ) ) ) 5 5 5 5 5 5 A A A A A A 2 2 2 2 2 2 6 6 6 6 6 6        U T T T T T T T 1 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	 	 	 	   &   "   &   2   , , , ,^9 9 9 9H         
 
 
 
# # # #L> > > >B<@ <@ <@ <@~): ): ): ):XD D D DNj j j j\H H H H HXr r r rl% % % %:      *A4 A4 A4 A4 A4JE E E ER
-T -T -T -Td     @ QU ] ] ] ] ] ]F9  r'   