
    `gj+                     l    d Z ddlmZmZmZmZ ddlmZ ddlm	Z	  G d de      Z
ddlmZ  ede
       y	)
u   Anthropic Messages API transport.

Delegates to the existing adapter functions in agent/anthropic_adapter.py.
This transport owns format conversion and normalization — NOT client lifecycle.
    )AnyDictListOptional)ProviderTransport)NormalizedResponsec                      e Zd ZdZedefd       Zdeeee	f      de	fdZ
deeee	f      de	fdZ	 dd	edeeee	f      deeeee	f         deee	f   fd
Zde	defdZde	defdZde	deeeef      fdZdddddddZdedefdZy)AnthropicTransportu   Transport for api_mode='anthropic_messages'.

    Wraps the existing functions in anthropic_adapter.py behind the
    ProviderTransport ABC.  Each method delegates — no logic is duplicated.
    returnc                      y)Nanthropic_messages )selfs    M/root/.hermes/venv/lib/python3.12/site-packages/agent/transports/anthropic.pyapi_modezAnthropicTransport.api_mode   s    #    messagesc                 D    ddl m} |j                  d      } |||      S )u   Convert OpenAI messages to Anthropic (system, messages) tuple.

        kwargs:
            base_url: Optional[str] — affects thinking signature handling.
        r   )convert_messages_to_anthropicbase_url)r   )agent.anthropic_adapterr   get)r   r   kwargsr   r   s        r   convert_messagesz#AnthropicTransport.convert_messages   s#     	J::j),XIIr   toolsc                     ddl m}  ||      S )z=Convert OpenAI tool schemas to Anthropic input_schema format.r   )convert_tools_to_anthropic)r   r   )r   r   r   s      r   convert_toolsz AnthropicTransport.convert_tools#   s    F)%00r   Nmodelc                 N   ddl m}  |||||j                  dd      |j                  d      |j                  d      |j                  dd      |j                  d	d      |j                  d
      |j                  d      |j                  dd      |j                  dd            S )a  Build Anthropic messages.create() kwargs.

        Calls convert_messages and convert_tools internally.

        params (all optional):
            max_tokens: int
            reasoning_config: dict | None
            tool_choice: str | None
            is_oauth: bool
            preserve_dots: bool
            context_length: int | None
            base_url: str | None
            fast_mode: bool
            drop_context_1m_beta: bool
        r   )build_anthropic_kwargs
max_tokensi @  reasoning_configtool_choiceis_oauthFpreserve_dotscontext_lengthr   	fast_modedrop_context_1m_beta)r   r   r   r"   r#   r$   r%   r&   r'   r   r(   r)   )r   r!   r   )r   r   r   r   paramsr!   s         r   build_kwargszAnthropicTransport.build_kwargs)   s    , 	C%zz,6#ZZ(:;

=1ZZ
E2 **_e<!::&67ZZ
+jje4!',BE!J
 	
r   responsec           
         ddl }ddlm}m} ddlm} |j                  dd      }d}g }	g }
g }g }g }|j                  D ]  } ||      }d}t        |t              r ||      }||j                  |       |j                  dk(  r|	j                  |j                         d|j                  d	v ro|j                  d
k(  r|
j                  |j                         t        |t              r|j                  |       t        |t              s|j                  |       |j                  dk(  s|j                  }|rb|j                  |      rQddlm} |j%                  |      s:|t'        |      d }d|z   }|j%                  |      r|}n|j%                  |      r|}|j                   ||j(                  ||j+                  |j,                                      | j.                  j                  |j0                  d      }i }|r||d<   t3        d |D              }t3        d |D              }|r|r||d<   t5        |	rdj7                  |	      nd|xs d||
rdj7                  |
      ndd|xs d      S )zNormalize Anthropic response to NormalizedResponse.

        Parses content blocks (text, thinking, tool_use), maps stop_reason
        to OpenAI finish_reason, and collects reasoning_details in provider_data.
        r   N)_to_plain_data_sanitize_replay_block)ToolCallstrip_tool_prefixFmcp__textthinkingredacted_thinkingr5   tool_use)registrymcp_)idname	argumentsstopreasoning_detailsc              3      K   | ]O  }t        |t              xr9 |j                  d       dv xr$ |j                  d      xs |j                  d       Q yw)typer4   	signaturedataN
isinstancedictr   .0bs     r   	<genexpr>z8AnthropicTransport.normalize_response.<locals>.<genexpr>   sZ      #
  q$ 6f!BB6{#4quuV}6#
s   AAc              3   h   K   | ]*  }t        |t              xr |j                  d       dk(   , yw)r@   r7   NrC   rF   s     r   rI   z8AnthropicTransport.normalize_response.<locals>.<genexpr>   s4      
 q$?AEE&MZ$??
s   02anthropic_content_blocks
z

)content
tool_callsfinish_reason	reasoningusageprovider_data)jsonr   r.   r/   agent.transports.typesr0   r   rM   rD   rE   appendr@   r3   r5   r;   
startswithtools.registryr8   	get_entrylenr:   dumpsinput_STOP_REASON_MAPstop_reasonanyr   join)r   r,   r   rS   r.   r/   r0   r1   _MCP_PREFIX
text_partsreasoning_partsr>   rN   ordered_blocksblock
block_dictclean_blockr;   _tool_registrybaresinglerO   rR   _has_signed_thinking_has_tool_uses                            r   normalize_responsez%AnthropicTransport.normalize_responseP   sp    	R3"JJ':EB

 %% 3	E'.JK*d+
 5Z@*"))+6zzV#!!%**-@@::+#**5>>: k40%,,[9
D1%,,Z8z)zz$)E J)33D9#C$4$56!'$)33F;#)D+55d;#'D!! 88!"&**U[["9[3	j --11(2F2FO1BM-.  # #
 $	#
  
  
#
 
  M8FM45!-7DIIj)T!)T'6Efkk/24'/4
 	
r   c                 h    |yt        |dd      }t        |t              sy|st        |dd      dv S y)u  Check Anthropic response structure is valid.

        An empty content list is legitimate for terminal stop reasons that
        carry no text payload:

        - ``end_turn`` — the model's canonical "nothing more to add" after a
          tool turn that already delivered the user-facing text.
        - ``refusal`` — the model declined to respond (Claude 4.5+). The
          Messages API returns an empty ``content`` list with this stop
          reason. Treating it as invalid sends a deterministic refusal into
          the invalid-response retry loop, which reproduces the refusal on
          every attempt and surfaces a misleading "rate limited / invalid
          response" error instead of the refusal. ``normalize_response`` maps
          ``refusal`` → ``content_filter`` so the agent loop's refusal handler
          can surface it.

        Treating either as invalid falsely retries a completed response.
        NFrM   r]   >   refusalend_turnT)getattrrD   list)r   r,   content_blockss      r   validate_responsez$AnthropicTransport.validate_response   sC    &  9d;.$/8]D9=TTTr   c                 z    t        |dd      }|yt        |dd      xs d}t        |dd      xs d}|s|r||dS y)z=Extract Anthropic cache_read and cache_creation token counts.rQ   Ncache_read_input_tokensr   cache_creation_input_tokens)cached_tokenscreation_tokens)rp   )r   r,   rQ   cachedwrittens        r   extract_cache_statsz&AnthropicTransport.extract_cache_stats   sS    '40= 91=B%!>BGaW%+HHr   r=   rN   lengthcontent_filter)ro   r7   r"   stop_sequencern   model_context_window_exceeded
raw_reasonc                 :    | j                   j                  |d      S )z2Map Anthropic stop_reason to OpenAI finish_reason.r=   )r\   r   )r   r   s     r   map_finish_reasonz$AnthropicTransport.map_finish_reason   s    $$((V<<r   )N)__name__
__module____qualname____doc__propertystrr   r   r   r   r   r   r   r+   r   rl   boolrs   intr{   r\   r   r   r   r   r
   r
      s7    $# $ $	Jd38n)= 	JC 	J14S#X#7 1C 1 15	%
%
 tCH~&%
 T#s(^,-	%
 
c3h%
Np
3 p
=O p
d# $ 8	C 	HT#s(^4L 	  #)1=C =C =r   r
   )register_transportr   N)r   typingr   r   r   r   agent.transports.baser   rT   r   r
   agent.transportsr   r   r   r   <module>r      s9    - , 3 5h=* h=X 0 '); <r   