
    *3j+                     z    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
           d	S )
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                   d   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dS )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                     dS )Nanthropic_messages )selfs    @/home/rurouni/.hermes/hermes-agent/agent/transports/anthropic.pyapi_modezAnthropicTransport.api_mode   s    ##    messagesc                 R    ddl m} |                    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IIIII::j)),,XII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FFFFF))%000r   Nmodelc                    ddl m}  |||||                    dd          |                    d          |                    d          |                    dd          |                    d	d          |                    d
          |                    d          |                    dd          |                    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BBBBB%%zz,66#ZZ(:;;

=11ZZ
E22 **_e<<!::&677ZZ
++jje44!',BE!J!J
 
 
 	
r   responsec           
      N   ddl }ddlm}m} ddlm} |                    dd          }d}g }	g }
g }g }g }|j        D ]} ||          }d}t          |t                    r" ||          }||
                    |           |j        dk    r|	
                    |j                   m|j        d	v r{|j        d
k    r|

                    |j                   t          |t                    r|
                    |           t          |t                    r|
                    |           |j        dk    r|j        }|r{|                    |          rfddlm} |                    |          sK|t'          |          d         }d|z   }|                    |          r|}n|                    |          r|}|
                     ||j        ||                    |j                                       | j                            |j        d          }i }|r||d<   t3          d |D                       }t3          d |D                       }|r|r||d<   t5          |	rd                    |	          nd|pd||
rd                    |
          ndd|p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   | ]Z}t          |t                    o@|                    d           dv o)|                    d          p|                    d          V  [dS )typer4   	signaturedataN
isinstancedictr   .0bs     r   	<genexpr>z8AnthropicTransport.normalize_response.<locals>.<genexpr>   s}       #
 #
  q$ 6f!BB6{##4quuV}}#
 #
 #
 #
 #
 #
r   c              3   r   K   | ]2}t          |t                    o|                    d           dk    V  3dS )r@   r7   NrC   rF   s     r   rI   z8AnthropicTransport.normalize_response.<locals>.<genexpr>   sT       
 
 q$?AEE&MMZ$?
 
 
 
 
 
r   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   s    	RRRRRRRR333333"JJ':EBB

 % 3	 3	E'..JK*d++ 7
 54Z@@*"))+666zV##!!%*----@@@:++#**5>::: k400 9%,,[9999
D11 9%,,Z888z))z$ ()E)E ( JIIIII)33D99 (#C$4$4$5$56!'$)33F;; (#)DD+55d;; (#'D!!H 8!"&**U["9"9     -11(2FOO 	C1BM-.  # #
 #
 $	#
 #
 #
  
  
  
 
#
 
 
 
 
   	GM 	G8FM45!-7ADIIj)))T!)T'6EOfkk/2224'/4
 
 
 	
r   c                     |dS t          |dd          }t          |t                    sdS |st          |dd          dv S dS )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   s]    & 5 9d;;.$// 	5 	U8]D99=TTTtr   c                     t          |dd          }|dS t          |dd          pd}t          |dd          pd}|s|r||dS dS )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   so    '400=4 91==B%!>BBGa 	IW 	I%+HHHtr   r=   rN   lengthcontent_filter)ro   r7   r"   stop_sequencern   model_context_window_exceeded
raw_reasonc                 8    | 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
      s         $# $ $ $ X$	Jd38n)= 	JC 	J 	J 	J 	J14S#X#7 1C 1 1 1 1 15	%
 %
%
 tCH~&%
 T#s(^,-	%
 
c3h%
 %
 %
 %
Np
3 p
=O p
 p
 p
 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      s     - , , , , , , , , , , , 3 3 3 3 3 3 5 5 5 5 5 5h= h= h= h= h=* h= h= h=X 0 / / / / /  '); < < < < <r   