
    i                    T   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	m
Z
 ddlmZmZmZmZmZ ddlZddlmZ  ej        e          ZdZdadZefddddbdZdcdZdZ G d de          ZdddZdedZdfd"Z dgd#Z!	 dhdid'Z"djd*Z#dkd,Z$dld/Z%dmd1Z&dddddddd2dnd:Z'dod<Z(dpd>Z)dqd@Z*drdBZ+ G dC dDe
          Z,dEdddEdFdsdJZ-dtdNZ.dudSZ/dvdTZ0 G dU dV          Z1 G dW dX          Z2 G dY dZ          Z3 G d[ d\          Z4 G d] d^          Z5 G d_ d`          Z6dS )wa  OpenAI-compatible facade over Google AI Studio's native Gemini API.

Hermes keeps ``api_mode='chat_completions'`` for the ``gemini`` provider so the
main agent loop can keep using its existing OpenAI-shaped message flow.
This adapter is the transport shim that converts those OpenAI-style
``messages[]`` / ``tools[]`` requests into Gemini's native
``models/{model}:generateContent`` schema and converts the responses back.

Why this exists
---------------
Google's OpenAI-compatible endpoint has been brittle for Hermes's multi-turn
agent/tool loop (auth churn, tool-call replay quirks, thought-signature
requirements).  The native Gemini API is the canonical path and avoids the
OpenAI-compat layer entirely.
    )annotationsN)SimpleNamespace)AnyDictIteratorListOptional)sanitize_gemini_tool_parametersz0https://generativelanguage.googleapis.com/v1betabase_urlstrreturnboolc                    t          | pd                                                              d                                          }|sdS d|vrdS |                    d           S )z>Return True when the endpoint speaks Gemini's native REST API. /Fz!generativelanguage.googleapis.com/openai)r   striprstriplowerendswith)r   
normalizeds     @/home/ubuntu/.hermes/hermes-agent/agent/gemini_native_adapter.pyis_native_gemini_base_urlr   %   sm    X^$$**,,33C88>>@@J u**<<u""9----    gemini-2.5-flashg      $@)modeltimeoutapi_keyr   r   floatc                  | pd                                 }|sdS t          |pt                                                                         d          }|st          }|                                                    d          r|dt          d                    }| d| d}dd	d
igdgddid}	 t          j        |          5 }|	                    |d|i|ddi          }	ddd           n# 1 swxY w Y   n3# t          $ r&}
t                              d|
           Y d}
~
dS d}
~
ww xY wd |	j                                        D             }|                    d          }|r>	 t!          |          }n# t"          t$          f$ r d}Y nw xY w||dk    rdS ||dk    rdS |	j        dk    r9d}	 |	j        pd}n# t          $ r d}Y nw xY wd|                                v rdS dS d|	j        cxk    rdk     rn ndS dS )a  Probe a Google AI Studio API key and return its tier.

    Returns one of:

    - ``"free"``    -- key is on the free tier (unusable with Hermes)
    - ``"paid"``    -- key is on a paid tier
    - ``"unknown"`` -- probe failed; callers should proceed without blocking.
    r   unknownr   r   N/models/:generateContentusertexthirolepartsmaxOutputTokens   )contentsgenerationConfigr   keyContent-Typeapplication/json)paramsjsonheadersz$probe_gemini_tier: network error: %sc                >    i | ]\  }}|                                 |S  r   ).0kvs      r   
<dictcomp>z%probe_gemini_tier.<locals>.<dictcomp>Z   s&    CCCdaQWWYYCCCr   z"x-ratelimit-limit-requests-per-dayi  freepaid  	free_tier   i,  )r   r   DEFAULT_GEMINI_BASE_URLr   r   r   lenhttpxClientpost	Exceptionloggerdebugr4   itemsgetint	TypeError
ValueErrorstatus_coder%   )r   r   r   r   r/   normalized_baseurlpayloadclientrespexcheaders_lower
rpd_headerrpd_val	body_texts                  r   probe_gemini_tierrY   /   s    =b


!
!C y(=&=>>DDFFMMcRRO 21''	22 =)*;S^^O*;<
=
=e
=
=
=C$/?@@A.2 G

\'*** 	f;;s|');<	   D	 	 	 	 	 	 	 	 	 	 	 	 	 	 	    ;SAAAyyyyy DCdl.@.@.B.BCCCM""#GHHJ 	*ooGG:& 	 	 	GGG	
 7d??67T>>63			RII 	 	 	III	)//++++6v
d$$$$$$$$$v9s`   5D  
C4(D  4C88D  ;C8<D   
D0
D++D0.E> >FF9	G GGerror_messagec                6    | sdS d|                                  v S )zEReturn True when a Gemini 429 message indicates free-tier exhaustion.Fr?   r7   )rZ   s    r   is_free_tier_quota_errorr\   y   s&     u---////r   aj  

Your Google API key is on the free tier (<= 250 requests/day for gemini-2.5-flash). Hermes typically makes 3-10 API calls per user turn, so the free tier is exhausted in a handful of messages and cannot sustain an agent session. Enable billing on your Google Cloud project and regenerate the key in a billing-enabled project: https://aistudio.google.com/apikeyc                  2     e Zd ZdZddddddd fdZ xZS )GeminiAPIErrorz>Error shape compatible with Hermes retry/error classification.gemini_api_errorNcoderN   responseretry_afterdetailsmessager   ra   rN   Optional[int]rb   Optional[httpx.Response]rc   Optional[float]rd   Optional[Dict[str, Any]]r   Nonec                   t                                          |           || _        || _        || _        || _        |pi | _        d S N)super__init__ra   rN   rb   rc   rd   )selfre   ra   rN   rb   rc   rd   	__class__s          r   rn   zGeminiAPIError.__init__   sJ     	!!!	& &}"r   )re   r   ra   r   rN   rf   rb   rg   rc   rh   rd   ri   r   rj   )__name__
__module____qualname____doc__rn   __classcell__)rp   s   @r   r^   r^      s^        HH '%)-1'+,0% % % % % % % % % % % %r   r^   contentr   c                   | dS t          | t                    r| S t          | t                    rg }| D ]}t          |t                    r|                    |           -t          |t                    rX|                    d          dk    r?|                    d          }t          |t                    r|                    |           d                    |          S t          |           S )Nr   typer%   
)
isinstancer   listappenddictrJ   join)rv   piecespartr%   s       r   _coerce_content_to_textr      s    r'3 '4   	! 	( 	(D$$$ (d####D$'' (DHHV,<,<,F,Fxx''dC(( (MM$'''yy   w<<r   List[Dict[str, Any]]c                   t          | t                    st          |           }|rd|igng S g }| D ]}t          |t                    r|                    d|i           0t          |t
                    sF|                    d          }|dk    rD|                    d          }t          |t                    r|r|                    d|i           |dk    r|                    d          pi                     d          pd}t          |t                    r|                    d          s	 |                    dd          \  }}|                    d	d          d                             d
d          d         }t          j
        |          }	n# t          $ r Y vw xY w|                    d|t          j        |	                              d          di           |S )Nr%   rx   	image_urlrP   r   zdata:,r+   :;r   
inlineDataascii)mimeTypedata)rz   r{   r   r   r|   r}   rJ   
startswithsplitbase64	b64decoderF   	b64encodedecode)
rv   r%   r)   itemptyperP   headerencodedmimeraws
             r   _extract_multimodal_partsr      s   gt$$ 0&w//#'/R/"$E  dC   	LL&$((($%% 	  F??88F##D$$$ - -fd^,,,k!!HH[))/R44U;;ArCc3'' s~~g/F/F "%))C"3"3||C++A.44S!<<Q?&w//   LL $( & 0 5 5 < <W E E# #   Ls   7A#F
F)(F)	tool_callDict[str, Any]Optional[str]c                   |                      d          pi }t          |t                    sd S |                     d          p|                     d          }t          |t                    rR|                     d          p|                     d          }t          |t                    r|rt          |          nd S t          |t                    r|r|S d S )Nextra_contentgooglethought_signaturethoughtSignature)rJ   rz   r}   r   )r   extrar   sigs       r   _tool_call_extra_signaturer      s    MM/**0bEeT"" tYYx  BEII.A$B$BF&$ Bjj,--O<N1O1O%c3//ACAs3xxxTA&# 6 4r   c                   |                      d          pi }|                     dd          }	 t          |t                    r|rt          j        |          ni }n# t          j        $ r d|i}Y nw xY wt          |t                    sd|i}dt          |                     d          pd          |di}t          |           }|r||d	<   |S )
Nfunction	argumentsr   _raw_valuefunctionCallname)r   argsr   )rJ   rz   r   r3   loadsJSONDecodeErrorr}   r   )r   fnargs_rawr   r   r   s         r   _translate_tool_call_to_geminir      s    	z	"	"	(bBvvk2&&H"'1(C'@'@UXUtz(###SU " " "!"dD!!  $ 	v,"--
 
D 39== 5#4 Ks   -A A32A3re   tool_name_by_call_idOptional[Dict[str, str]]c                   |pi }t          |                     d          pd          }t          |                     d          p|                    |          p|pd          }t          |                     d                    }	 |                                                    d          rt          j        |          nd }n# t
          j        $ r d }Y nw xY wt          |t                    r|nd|i}d||d	iS )
Ntool_call_idr   r   toolrv   ){[outputfunctionResponse)r   rb   )
r   rJ   r   r   r   r3   r   r   rz   r}   )re   r   r   r   rv   parsedrb   s          r    _translate_tool_result_to_geminir      s&    052w{{>228b99LF 	##L11		 	 D &gkk)&<&<==G(/(B(B:(N(NXG$$$TX   #FD11Jvv'7JH 
 
 s   =C CCmessages5tuple[List[Dict[str, Any]], Optional[Dict[str, Any]]]c                b   g }g }i }| D ]}t          |t                    st          |                    d          pd          }|dk    r6|                    t          |                    d                               y|dv r)|                    dt          ||          gd           |dk    rd	nd}g }t          |                    d                    }|                    |           |                    d
          pg }	t          |	t                    r|	D ]}
t          |
t                    rt          |
                    d          p|
                    d          pd          }t          |
                    d          pi                     d          pd          }|r|r|||<   |                    t          |
                     |r|                    ||d           d }d                    d |D                                                       }|rdd|igi}||fS )Nr(   r$   systemrv   >   r   r   )r   r'   	assistantr   
tool_callsidcall_idr   r   r   ry   c              3     K   | ]}||V  	d S rl   r6   )r8   r   s     r   	<genexpr>z)_build_gemini_contents.<locals>.<genexpr>D  s'      IItDIdIIIIIIr   r)   r%   )rz   r}   r   rJ   r|   r   r   r   extendr{   r   r~   r   )r   system_text_partsr,   r   msgr(   gemini_roler)   content_partsr   r   r   	tool_namesystem_instructionjoined_systems                  r   _build_gemini_contentsr     s   #%%'H+- (C (C#t$$ 	3776??,f--8$$%<SWWY=O=O%P%PQQQ'''OO"81E   
 
 
 !%!4!4gg&&(1#'')2D2DEE]###WW\**0b
j$'' 	L' L L	i.. L#&y}}T':':'\immI>V>V'\Z\#]#]L #immJ&?&?&E2%J%J6%R%R%XVX Z ZI# G	 G=F,\:LL!?	!J!JKKK 	COO[5AABBBIIII/@IIIIIOOQQM B%(?'@A'''r   toolsc                <   t          | t                    sg S g }| D ]}t          |t                    s|                    d          pi }t          |t                    sE|                    d          }t          |t                    r|srd|i}|                    d          }t          |t                    r|r||d<   |                    d          }t          |t                    rt          |          |d<   |                    |           |rd|igng S )Nr   r   description
parametersfunctionDeclarations)rz   r{   r}   rJ   r   r
   r|   )r   declarationsr   r   r   declr   r   s           r   _translate_tools_to_geminir   J  s;   eT"" 	)+L " "$%% 	XXj!!'R"d## 	vvf~~$$$ 	D 	 &~ff]++k3'' 	.K 	."-DVVL))
j$'' 	M!@!L!LDD!!!!7CK#\233Kr   tool_choiceri   c                @   | d S t          | t                    r$| dk    rdddiiS | dk    rdddiiS | dk    rdddiiS t          | t                    rK|                     d	          pi }|                    d
          }t          |t                    r
|rdd|gdiS d S )NautofunctionCallingConfigmodeAUTOrequiredANYnoneNONEr   r   )r   allowedFunctionNames)rz   r   r}   rJ   )r   r   r   s      r    _translate_tool_choice_to_geminir   b  s    t+s## ?&  +ff-=>>*$$+fe_==&  +ff-=>>+t$$ ^__Z((.Bvvf~~dC   	^T 	^+eVZU[-\-\]]4r   configc                j   t          | t                    r| sd S |                     d|                     d                    }|                     d|                     d                    }|                     d|                     d                    }i }t          |t          t          f          rt          |          |d<   t          |t
                    r||d<   t          |t                    r=|                                r)|                                                                |d<   |pd S )NthinkingBudgetthinking_budgetincludeThoughtsinclude_thoughtsthinkingLevelthinking_level)	rz   r}   rJ   rK   r   r   r   r   r   )r   budgetincludelevelr   s        r   _normalize_thinking_configr   t  s   fd## 6 tZZ(&**5F*G*GHHFjj*FJJ7I,J,JKKGJJ

3C(D(DEEE!#J&3,'' 3'*6{{
#$'4   0(/
$%% <%++-- <&+kkmm&9&9&;&;
?#r   )r   r   temperature
max_tokenstop_pstopthinking_configr   rh   r   rf   r   r   r   c                X   t          |           \  }}	d|i}
|	r|	|
d<   t          |          }|r||
d<   t          |          }|r||
d<   i }|||d<   |||d<   |||d<   |r*t          |t                    r|nt          |          g|d<   t          |          }|r||d	<   |r||
d
<   |
S )Nr,   systemInstructionr   
toolConfigr   r*   topPstopSequencesthinkingConfigr-   )r   r   r   rz   r{   r   r   )r   r   r   r   r   r   r   r   r,   r   requestgemini_toolstool_configgeneration_confignormalized_thinkings                  r   build_gemini_requestr     s    $:(#C#C H )84G :'9#$-e44L ('2;??K , +(*+6-(/9+,$)&! ]5?d5K5K-\TTRUVZR[R[Q\/*4_EE B.A*+ 8&7"#Nr   reasonc                    dddddd}|                     t          | pd                                          d          S )Nr   lengthcontent_filter)STOP
MAX_TOKENSSAFETY
RECITATIONOTHERr   )rJ   r   upper)r   mappings     r   _map_gemini_finish_reasonr    sK    "& G ;;s6<R((..00&999r   r   c                j    |                      d          }t          |t                    r|rdd|iiS d S )Nr   r   r   )rJ   rz   r   )r   r   s     r   _tool_call_extra_from_partr    sC    
((%
&
&C#s 6 6.4554r   r   c                <   t          ddd d d d           }t          d|d          }t          dddt          d                    }t          d	t          j                    j        d d
          dt	          t          j                              | |g|          S )Nr   r   r(   rv   r   	reasoningreasoning_contentreasoning_detailsr   r   indexre   finish_reasoncached_tokensprompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details	chatcmpl-   chat.completionr   objectcreatedr   choicesusage)r   uuiduuid4hexrK   time)r   re   choicer$  s       r   _empty_responser*    s      G 1gVLLLF-A>>>	  E .tz||',.. DIKK     r   rS   c                p   |                      d          pg }t          |t                    r|st          |          S t          |d         t                    r|d         ni }t          |t                    r|                     d          ni }t          |t                    r|                     d          ng }g }g }g }t          |pg           D ]\  }	}
t          |
t                    s|
                     d          du rDt          |
                     d          t                    r|                    |
d                    wt          |
                     d          t                    r|                    |
d                    |
                     d          }t          |t                    r|                     d	          r	 t          j	        |                     d
          pi d          }n# t          t          f$ r d}Y nw xY wt          dt          j                    j        d d          d|	t          t          |d	                   |                    }t!          |
          }|r||_        |                    |           |rdn0t%          t          |                     d          pd                    }|                      d          pi }t          t'          |                     d          pd          t'          |                     d          pd          t'          |                     d          pd          t          t'          |                     d          pd                              }d                    |          pd }t          d|rd                    |          nd |pd ||d           }t          d||          }t          d t          j                    j        d d          d!t'          t+          j                              ||g|"          S )#N
candidatesr   rv   r)   thoughtTr%   r   r   r   F)ensure_ascii{}call_r  r   r   r   )r   rx   r  r   r   finishReasonr   usageMetadatapromptTokenCountcandidatesTokenCounttotalTokenCountcachedContentTokenCountr  r  r   r  r  r  r  r   )rJ   rz   r{   r*  r}   	enumerater   r|   r3   dumpsrL   rM   r   r%  r&  r'  r  r   r  rK   r~   r(  )rS   r   r,  candcontent_objr)   text_piecesreasoning_piecesr   r  r   fcargs_strr   r   r  
usage_metar$  r  re   r)  s                        r   translate_gemini_responserA    s'   ,''-2Jj$'' &z &u%%%&z!}d;;C:a==D)3D$)?)?G$((9%%%RK(2;(E(EMKOOG$$$2EK"$(*J "-- ) )t$%% 	88I$&&:dhhv6F6F+L+L&##DL111dhhv&&,, 	tF|,,,XXn%%b$ 	)BFF6NN 	) :bffVnn&:OOOz*       '24:<<+CRC022(c"V*ooRRR	  I 7t<<M 8*7	'i((($.rLL4McRVRZRZ[iRjRjRpnpNqNq4r4rM/**0bJ*..);<<ABBjnn-CDDIJJ(9::?a@@-jnn-FGGL1MM
 
 
	  E ())1TI(3=$$$%#  G 1g]SSSF.tz||',.. DIKK     s   +G99HHc                      e Zd ZdS )_GeminiStreamChunkN)rq   rr   rs   r6   r   r   rC  rC    s        Dr   rC  r   )rv   tool_call_deltar  r  rD  r  r  c                   dd d d d d}|r||d<   |t          |                    dd          |                    d          p"dt          j                    j        d d          d	t          |                    d
          pd|                    d          pd                    }|                    d          }t          |t                    r||_        |g|d<   |r
||d<   ||d<   t          di |}t          d||          }	t          dt          j                    j        d d          dt          t          j
                              | |	gd           S )Nr   )r(   rv   r   r  r  rv   r  r   r   r0  r  r   r   r   r   r1  )r  r   rx   r   r   r   r  r  )r  deltar  r  zchat.completion.chunkr   r6   )r   rJ   r%  r&  r'  rz   r}   r   rC  rK   r(  )
r   rv   rD  r  r  delta_kwargs
tool_deltar   rF  r)  s
             r   _make_stream_chunkrI  #  s    !$ $L  *")Y"$!%%gq11""4((K,KDJLL4DSbS4I,K,K$$((006B)--k::@b  	
 
 

 (++O<<mT** 	5'4J$&0\\" 6$-[!,5()++l++E1EOOOF.tz||',..&DIKK     r   rb   httpx.ResponseIterator[Dict[str, Any]]c              #    K   d}|                                  D ]}|s||z  }d|v r|                    dd          \  }}|                    d          }|s5|                    d          sK|dd          }|dk    r d S 	 t	          j        |          }n8# t          j        $ r& t                              d|d d	                    Y w xY wt          |t                    r|V  d|v Ōd S )
Nr   ry   r+   zdata:    z[DONE]zNon-JSON Gemini SSE line: %sr@   )	iter_textr   r   r   r3   r   r   rG   rH   rz   r}   )rb   bufferchunkliner   rQ   s         r   _iter_sse_eventsrS  Q  s5     F##%%   	%fnn!<<a00LD&;;t$$D ??8,, 8Dx*T**'   ;T$3$ZHHH '4(( ! fnn	 s   B2CCeventtool_call_indicesDict[str, Dict[str, Any]]List[_GeminiStreamChunk]c                   |                      d          pg }|sg S t          |d         t                    r|d         ni }t          |t                    r,|                     d          pi                      d          pg ng }g }t          |          D ]\  }}t          |t                    s|                     d          du rSt          |                     d          t                    r+|                    t          ||d                              t          |                     d          t                    r2|d         r*|                    t          ||d         	                     |                     d
          }	t          |	t                    r|	                     d          rt	          |	d                   }
	 t          j        |	                     d          pi dd          }n# t          t          f$ r d}Y nw xY wt          |                     d          t                    r|                     d          nd}t          j        ||
|dd          }|                     |          }|9t          |          dt          j                    j        d d          dd}|||<   |}t	          |                     d          pd          }|r5||k    rd}n,|                    |          r|t          |          d          }||d<   |                    t          ||d         |d         |
|t!          |          d                     t	          |                     d          pd          }|r7|rdnt#          |          }|                    t          ||                     |S )Nr,  r   rv   r)   r-  Tr%   )r   r  )r   rv   r   r   r   F)r.  	sort_keysr/  r   r   )
part_indexr   r   )rY  r0  r  )r  r   last_argumentsr[  r  r   )r  r   r   r   r   )r   rD  r2  r   )r   r  )rJ   rz   r}   r8  r   r|   rI  r3   r9  rL   rM   rB   r%  r&  r'  r   r  r  )rT  r   rU  r,  r:  r)   chunksrZ  r   r>  r   r?  r   call_keyslotemitted_argumentsr[  finish_reason_rawmappeds                      r   translate_stream_eventrb  j  s   <((.BJ 	&z!}d;;C:a==D@J4QU@V@V^dhhy!!'R,,W55;\^E')F%e,, 3 3
D$%% 	88I$&&:dhhv6F6F+L+L&MM,5DLQQQRRRdhhv&&,, 	Qf 	QMM,5$v,OOOPPPXXn%%b$ *	BFF6NN *	r&z??D :bffVnn&:Z^___z*       @J488TfKgKgil@m@m u); < < <suz", ): 
   H %((22D| !2339$*,,"23B3"799&( 
 /3!(+ ( *:!;!;!ArBBN G~--(*%%((88 G(0^1D1D1E1E(F%%-D!"MM"!%g"4j $%6)CD)I)I% %	 	 	   DHH^44:;; M!2d8QRc8d8d(uFKKKLLLMs   ,G99HHc                   | j         }d}i }	 | j        }n# t          $ r d}Y nw xY w|rF	 t          j        |          }t          |t                    r|}n# t          t          f$ r i }Y nw xY wt          |t                    r|	                    d          nd }t          |t                    si }t          |	                    d          pd                                          }t          |	                    d          pd                                          }|	                    d          }t          |t                    r|ng }	d}
d }i }|	D ]}t          |t                    st          |	                    d          pd          }|
sm|                    d          rX|	                    d          }t          |t                    r|}
|	                    d	          }t          |t                    r|}| j        	                    d
          p| j        	                    d          }|r*	 t          |          }n# t          t          f$ r d }Y nw xY wd| }|dk    rd}n|dk    rd}n|dk    rd}|rd| d|pd d| }nd| d|d d          }|dk    rt!          |p|          r
|t"          z   }t%          |||| |||
||d          S )Nr   errorstatusre   rd   z@typez/google.rpc.ErrorInfor   metadatazRetry-Afterzretry-aftergemini_http_i  gemini_unauthorizedr>   gemini_rate_limitedi  gemini_model_not_foundzGemini HTTP z (z): zGemini returned HTTP z: i  )re  r   rf  re   r`   )rN   r%   rF   r3   r   rz   r}   rM   rL   rJ   r   r   r{   r   r4   r   r\   _FREE_TIER_GUIDANCEr^   )rb   re  rX   	body_jsonr   err_obj
err_statuserr_message_raw_detailsdetails_listr   rc   rf  detailtype_urlreason_valuemdheader_retryra   re   s                       r   gemini_http_errorrw    sz   !FI "IM		   			 	Z	**F&$'' #"	I& 	 	 	III	 )39d(C(CMimmG$$$Ggt$$ W[[**0b117799Jgkk),,23399;;K;;y))L#-lD#A#AI<<rLF#'K!H 
 
&$'' 	vzz'**0b11 	(++,CDD 	!::h//L,,, &%J''B"d## #''66](:J:N:N}:]:]L 	--KK:& 	 	 	KKK	 #&""D}}$	3$	3' FRRR:+@RR[RRE&EEIdsdOEE
 }}1+2JKK}//  "	
 
   s/    $$+A A,+A,7I IIc                      e Zd Zd	dZd
dZdS )_GeminiChatCompletionsrR   'GeminiNativeClient'c                    || _         d S rl   _clientro   rR   s     r   rn   z_GeminiChatCompletions.__init__      r   kwargsr   r   c                &     | j         j        di |S Nr6   r}  _create_chat_completionro   r  s     r   createz_GeminiChatCompletions.create  s    3t|3==f===r   NrR   rz  r  r   r   r   rq   rr   rs   rn   r  r6   r   r   ry  ry    s<           > > > > > >r   ry  c                      e Zd Zd	dZd
dZdS )_AsyncGeminiChatCompletionsrR   'AsyncGeminiNativeClient'c                    || _         d S rl   r|  r~  s     r   rn   z$_AsyncGeminiChatCompletions.__init__  r  r   r  r   r   c                6   K    | j         j        di | d {V S r  r  r  s     r   r  z"_AsyncGeminiChatCompletions.create	  s3      9T\9CCFCCCCCCCCCr   NrR   r  r  r  r6   r   r   r  r    sB           D D D D D Dr   r  c                      e Zd ZddZdS )_GeminiChatNamespacerR   rz  c                .    t          |          | _        d S rl   )ry  completionsr~  s     r   rn   z_GeminiChatNamespace.__init__  s    1&99r   Nr  rq   rr   rs   rn   r6   r   r   r  r    s(        : : : : : :r   r  c                      e Zd ZddZdS )_AsyncGeminiChatNamespacerR   r  c                .    t          |          | _        d S rl   )r  r  r~  s     r   rn   z"_AsyncGeminiChatNamespace.__init__  s    6v>>r   Nr  r  r6   r   r   r  r    s(        ? ? ? ? ? ?r   r  c                      e Zd ZdZdddddd2dZd3dZd Zd Zd4dZe	d5d            Z
ddddddddddddd6d-Zdd.d7d1ZdS )8GeminiNativeClientzCMinimal OpenAI-SDK-compatible facade over Gemini's native REST API.N)r   default_headersr   http_clientr   r   r   r   r  r   r   r   r  Optional[httpx.Client]_r   rj   c                  |pd                                 st          d          || _        |pt                              d          }|                    d          r|d t          d                    }|| _        t          |pi           | _	        t          |           | _        d| _        |p,t          j        |pt          j        dddd	          
          | _        d S )Nr   zGemini native client requires an API key, but none was provided. Set GOOGLE_API_KEY or GEMINI_API_KEY in your environment / ~/.hermes/.env (get one at https://aistudio.google.com/app/apikey), or run `hermes setup` to configure the Google provider.r   r   Fg      .@g     @g      >@)connectreadwritepoolr.   )r   RuntimeErrorr   rA   r   r   rB   r   r}   _default_headersr  chat	is_closedrC   rD   Timeout_http)ro   r   r   r  r   r  r  rO   s           r   rn   zGeminiNativeClient.__init__  s     2$$&& 	4   #>'>FFsKK##I.. 	A-.?Y.?@O' $_%: ; ;(..	  
EL]u}TTX\]]]%
 %
 %



r   c                j    d| _         	 | j                                         d S # t          $ r Y d S w xY w)NT)r  r  closerF   ro   s    r   r  zGeminiNativeClient.close7  sJ    	J 	 	 	DD	s   $ 
22c                    | S rl   r6   r  s    r   	__enter__zGeminiNativeClient.__enter__>  s    r   c                .    |                                   d S rl   )r  )ro   exc_typeexc_valexc_tbs       r   __exit__zGeminiNativeClient.__exit__A  s    

r   Dict[str, str]c                R    dd| j         dd}|                    | j                   |S )Nr1   zhermes-agent (gemini-native))r0   Acceptzx-goog-api-keyz
User-Agent)r   updater  )ro   r4   s     r   _headerszGeminiNativeClient._headersD  s8    .("l8	
 
 	t,---r   iteratorIterator[_GeminiStreamChunk])tuple[bool, Optional[_GeminiStreamChunk]]c                H    	 dt          |           fS # t          $ r Y dS w xY w)NF)TN)nextStopIteration)r  s    r   _advance_stream_iteratorz+GeminiNativeClient._advance_stream_iteratorN  s:    	$x..(( 	 	 	::	s    
!!r   F)r   r   streamr   r   r   r   r   r   
extra_bodyr   r   r   Optional[List[Dict[str, Any]]]r  r   r   r   r   rh   r   rf   r   r   r  ri   c          
     B   d }t          |
t                    r*|
                    d          p|
                    d          }t          |pg ||||||	|          }|r|                     |||          S | j         d| d}| j                            |||                                 |          }|j	        dk    rt          |          	 |                                }n.# t          $ r!}t          d	| d
|j	        |          |d }~ww xY wt          ||          S )Nr   r   )r   r   r   r   r   r   r   r   )r   r   r   r"   r#   r3   r4   r   r@   z%Invalid JSON from Gemini native API: gemini_invalid_json)ra   rN   rb   )r   )rz   r}   rJ   r   _stream_completionr   r  rE   r  rN   rw  r3   rM   r^   rA  )ro   r   r   r  r   r   r   r   r   r   r  r   r  r   r   rP   rb   rQ   rT   s                      r   r  z*GeminiNativeClient._create_chat_completionU  sj     j$'' 	d(nn->??c:>>RbCcCcO&^##!+	
 	
 	
  	Z**QX*YYY?????:??3WdmmooW^?__3&&#H---	mmooGG 	 	 	 ===*$0!	  
 	 )>>>>s   C" "
D,DDr.   r   r   c                     j          d dt                                                     dd<   d fd} |            S )	Nr"   z:streamGenerateContent?alt=sseztext/event-streamr  r   r  c               3    K   	 j                             d
	          5 } | j        dk    r#|                                  t	          |           i }t          |           D ]}t          ||          D ]}|V  	 d d d            d S # 1 swxY w Y   d S # t          j        $ r}t          d| d          |d }~ww xY w)NPOSTr  r@   z!Gemini streaming request failed: gemini_stream_error)ra   )
r  r  rN   r  rw  rS  rb  rC   	HTTPErrorr^   )rb   rU  rT  rQ  rT   r   r   ro   stream_headersr   rP   s        r   
_generatorz9GeminiNativeClient._stream_completion.<locals>._generator  sT     Z&&vs.bi&jj (nv+s22 /999CE%!1(!;!; ( (%;E5J[%\%\ ( (E"'KKKK((( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ?   $===.   s;   B AB B BB BB C)B>>C)r   r  )r   r}   r  )ro   r   r   r   r  r  rP   s   ```` @@r   r  z%GeminiNativeClient._stream_completion  s    MMMMMdmmoo..#6x 	 	 	 	 	 	 	 	 	 	 	  z||r   )r   r   r   r   r  r   r   r   r  r  r  r   r   rj   r   rj   )r   r  )r  r  r   r  )r   r   r   r  r  r   r   r   r   r   r   rh   r   rf   r   rh   r   r   r  ri   r   r   r  r   r   r   )r   r   r   r   r   r   r   r  )rq   rr   rs   rt   rn   r  r  r  r  staticmethodr  r  r  r6   r   r   r  r    s       MM #'48.2
 
 
 
 
 
:              \ (37'+$(!%/3/? /? /? /? /? /?b Y]        r   r  c                  *    e Zd ZdZddZddZdd
ZdS )AsyncGeminiNativeClientz?Async wrapper used by auxiliary_client for native Gemini calls.sync_clientr  c                l    || _         |j        | _        |j        | _        t          |           | _        d S rl   )_syncr   r   r  r  )ro   r  s     r   rn   z AsyncGeminiNativeClient.__init__  s0     
"*#,-d33			r   r  r   r   c                    K   t          |                    d                    }t          j         j        j        j        j        fi | d {V |sS d fd} |            S )Nr  r   r   c                n   K   	 t          j        j        j                   d {V \  } }| rd S |W V  2rl   )asyncio	to_threadr  r  )donerQ  resultro   s     r   _async_streamzFAsyncGeminiNativeClient._create_chat_completion.<locals>._async_stream  sW      $+$5dj6Y[a$b$bbbbbbbe E	r   )r   r   )r   rJ   r  r  r  r  r  r  )ro   r  r  r  r  s   `   @r   r  z/AsyncGeminiNativeClient._create_chat_completion  s      fjj**++()D)KVVvVVVVVVVV 	M	 	 	 	 	 	 	 }r   rj   c                R   K   t          j        | j        j                   d {V  d S rl   )r  r  r  r  r  s    r   r  zAsyncGeminiNativeClient.close  s4      
 011111111111r   N)r  r  r  r  )rq   rr   rs   rt   rn   r  r  r6   r   r   r  r    sV        II4 4 4 4   2 2 2 2 2 2r   r  )r   r   r   r   )
r   r   r   r   r   r   r   r   r   r   )rZ   r   r   r   )rv   r   r   r   )rv   r   r   r   )r   r   r   r   )r   r   r   r   rl   )re   r   r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   ri   )r   r   r   ri   )r   r   r   r   r   r   r   rh   r   rf   r   rh   r   r   r   r   r   r   )r   r   r   r   )r   r   r   ri   )r   r   r   r   )rS   r   r   r   r   r   )r   r   rv   r   rD  ri   r  r   r  r   r   rC  )rb   rJ  r   rK  )rT  r   r   r   rU  rV  r   rW  )rb   rJ  r   r^   )7rt   
__future__r   r  r   r3   loggingr(  r%  typesr   typingr   r   r   r   r	   rC   agent.gemini_schemar
   	getLoggerrq   rG   rA   r   rY   r\   rk  rF   r^   r   r   r   r   r   r   r   r   r   r   r  r  r*  rA  rC  rI  rS  rb  rw  ry  r  r  r  r  r  r6   r   r   <module>r     sS     # " " " " "       ! ! ! ! ! ! 6 6 6 6 6 6 6 6 6 6 6 6 6 6  ? ? ? ? ? ?		8	$	$L . . . . ,G $G G G G G GT0 0 0 0) % % % % %Y % % %*   $# # # #L
 
 
 
   0 6:    43( 3( 3( 3(lL L L L0   $   & #' $!' ' ' ' ' 'T: : : :      4B B B BJ	 	 	 	 	 	 	 	 04#'+ + + + + +\   2A A A AHL L L L^> > > > > > > >D D D D D D D D: : : : : : : :
? ? ? ? ? ? ? ?
D D D D D D D DN2 2 2 2 2 2 2 2 2 2r   