
    JjK                    r   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 ddlmZ  ej        e          ZdZd	ZdfdZdgdZefddddhdZdidZdZ G d de           Z!djdZ"dkd!Z#dld%Z$dmd&Z%	 dndod*Z&dpd-Z'dqd/Z(drd2Z)dsd4Z*dddddddd5dtd=Z+dud?Z,dvdAZ-dwdCZ.dxdEZ/ G dF dGe
          Z0dHdddHdIdydMZ1dzdQZ2d{dVZ3ddWd|dYZ4 G dZ d[          Z5 G d\ d]          Z6 G d^ d_          Z7 G d` da          Z8 G db dc          Z9 G dd de          Z:dS )}a  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)read_streaming_error_body)sanitize_gemini_tool_parametersz0https://generativelanguage.googleapis.com/v1betai  modelstrreturnc                    | pd                                 }|                                }dD ]D}|                    |          r-|t          |          d                                          p|c S E|S )zEStrip Gemini's own provider prefix from an aggregator-style model id. )zgoogle/zgemini/N)striplower
startswithlen)r   nameloweredprefixs       A/home/rurouni/.hermes/hermes-agent/agent/gemini_native_adapter.pybare_gemini_model_idr   -   s    KR  DjjllG( 6 6f%% 	6F%++--5555	6K    base_url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.r   /Fz!generativelanguage.googleapis.com/openai)r   r   rstripr   endswith)r   
normalizeds     r   is_native_gemini_base_urlr#   7   sm    X^$$**,,33C88>>@@J u**<<u""9----r   gemini-2.5-flashg      $@)r   timeoutapi_keyr%   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>l   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!   r   httpxClientpost	Exceptionloggerdebugr<   itemsgetint	TypeError
ValueErrorstatus_coder-   )r&   r   r   r%   r7   normalized_baseurlpayloadclientrespexcheaders_lower
rpd_headerrpd_val	body_texts                  r   probe_gemini_tierr`   A   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.FrG   r?   )ra   s    r   is_free_tier_quota_errorrc      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coderU   responseretry_afterdetailsmessager   rh   rU   Optional[int]ri   Optional[httpx.Response]rj   Optional[float]rk   Optional[Dict[str, Any]]r   Nonec                   t                                          |           || _        || _        || _        || _        |pi | _        d S N)super__init__rh   rU   ri   rj   rk   )selfrl   rh   rU   ri   rj   rk   	__class__s          r   ru   zGeminiAPIError.__init__   sJ     	!!!	& &}"r   )rl   r   rh   r   rU   rm   ri   rn   rj   ro   rk   rp   r   rq   )__name__
__module____qualname____doc__ru   __classcell__)rw   s   @r   re   re      s^        HH '%)-1'+,0% % % % % % % % % % % %r   re   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dictrQ   join)r}   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-   r   	image_urlrW   r   zdata:,r3   :;r   
inlineDataascii)mimeTypedata)r   r   r   r   r   r   rQ   r   splitbase64	b64decoderM   	b64encodedecode)
r}   r-   r1   itemptyperW   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)rQ   r   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functionCallr   )r   argsr   )rQ   r   r   r;   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rl   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   toolr}   ){[outputfunctionResponse)r   ri   )
r   rQ   r   r   r   r;   r   r   r   r   )rl   r   r   r   r}   parsedri   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                $   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           g }|D ]Y}|r@|d         d         |d         k    r(|d         d                             |d                    D|                    |           Z|}d }d                    d |D                                                       }|rdd|igd}||fS )Nr0   r,   systemr}   >   r   r   )r   r/   	assistantr   
tool_callsidcall_idr   r   r   r1   r   c              3     K   | ]}||V  	d S rs   r>   )r@   r   s     r   	<genexpr>z)_build_gemini_contents.<locals>.<genexpr>f  s'      IItDIdIIIIIIr   r-   )r   r   r   rQ   r   r   r   r   extendr   r   r   r   )r   system_text_partsr4   r   msgr0   gemini_roler1   content_partsr   r   r   	tool_namemerged_contentsr}   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 -/O , , 	,r26:gfoMMB(//0@AAAA""7++++HIIII/@IIIIIOOQQM T&.6=:Q9RSS'''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)r   r   r   rQ   r   r   r   )r   declarationsr   r   r   declr   r   s           r   _translate_tools_to_geminir   l  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_choicerp   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)r   r   r   rQ   )r   r   r   s      r    _translate_tool_choice_to_geminir     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)	r   r   rQ   rR   r'   r   r   r   r   )r   budgetincludelevelr"   s        r   _normalize_thinking_configr     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   ro   r   rm   r   r   r   c                n   t          |           \  }}	d|i}
|	r|	|
d<   t          |          }|r||
d<   t          |          }|r||
d<   i }|||d<   |||d<   n
t          |d<   |||d<   |r*t	          |t
                    r|nt          |          g|d<   t          |          }|r||d	<   |r||
d
<   |
S )Nr4   systemInstructionr   
toolConfigr   r2   topPstopSequencesthinkingConfigr5   )r   r   r    GEMINI_DEFAULT_MAX_OUTPUT_TOKENSr   r   r   r   )r   r   r   r   r   r   r   r   r4   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+,, 0P+,$)&! ]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   )rQ   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   )rQ   r   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   r0   r}   r   	reasoningreasoning_contentreasoning_detailsr   r   indexrl   finish_reasoncached_tokensprompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details	chatcmpl-   chat.completionr   objectcreatedr   choicesusage)r   uuiduuid4hexrR   time)r   rl   choicer,  s       r   _empty_responser2    s      G 1gVLLLF-A>>>	  E .tz||',.. DIKK     r   rZ   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   r}   r1   thoughtTr-   r   r   r   F)ensure_ascii{}call_r&  r   r   r   )r   r   r  r   r   finishReasonr   usageMetadatapromptTokenCountcandidatesTokenCounttotalTokenCountcachedContentTokenCountr  r   r   r  r  r%  r'  r(  )rQ   r   r   r2  r   	enumerater   r   r;   dumpsrS   rT   r   r-  r.  r/  r  r   r  rR   r   r0  )rZ   r   r4  candcontent_objr1   text_piecesreasoning_piecesr   r  r   fcargs_strr   r   r  
usage_metar,  r  rl   r1  s                        r   translate_gemini_responserI    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)rx   ry   rz   r>   r   r   rK  rK  M  s        Dr   rK  r   )r}   tool_call_deltar  r  rL  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   )r0   r}   r   r  r  r}   r  r   r   r8  r&  r   r   r   r   r9  )r  r   r   r   r   r   r  r  )r  deltar  r%  zchat.completion.chunkr(  r>   )r   rQ   r-  r.  r/  r   r   r   rK  rR   r0  )
r   r}   rL  r  r  delta_kwargs
tool_deltar   rN  r1  s
             r   _make_stream_chunkrQ  Q  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   ri   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   r   r3   zdata:    z[DONE]zNon-JSON Gemini SSE line: %srH   )	iter_textr   r    r   r;   r   r   rN   rO   r   r   )ri   bufferchunkliner   rX   s         r   _iter_sse_eventsr[    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          }|r |rdnt#          |          }t          ||          }|                      d          pi }|rt%          t'          |                     d           pd          t'          |                     d!          pd          t'          |                     d"          pd          t%          t'          |                     d#          pd          $          %          |_        |                    |           |S )&Nr4  r   r}   r1   r5  Tr-   )r   r  )r   r}   r   r   r   F)r6  	sort_keysr7  r   r   )
part_indexr   r   )ra  r8  r&  )r  r   last_argumentsrc  r  r   )r  r   r   r   r   )r   rL  r:  r   )r   r  r;  r<  r=  r>  r?  r  r   )rQ   r   r   r@  r   r   rQ  r;   rA  rS   rT   r   r-  r.  r/  r   r  r  r   rR   r,  )r\  r   r]  r4  rB  r1   chunksrb  r   rF  r   rG  r   call_keyslotemitted_argumentsrc  finish_reason_rawmappedfinish_chunkrH  s                        r   translate_stream_eventrk    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:;; $!2d8QRc8d8d)VLLL YY//52
 	!0!*..1C"D"D"IJJ"%jnn5K&L&L&QPQ"R"R 0A!B!B!GaHH&5"%jnn5N&O&O&TST"U"U' ' '	" " "L 	l###Ms   ,G99HHr_   r_   c                  | j         }i }|	 | j        }n# t          $ r d}Y nw xY w|pd}|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statusrl   rk   z@typez/google.rpc.ErrorInfor  metadatazRetry-Afterzretry-aftergemini_http_i  gemini_unauthorizedrF   gemini_rate_limitedi  gemini_model_not_foundzGemini HTTP z (z): zGemini returned HTTP z: i  )ro  r  rp  rl   rg   )rU   r-   rM   r;   r   r   r   rT   rS   rQ   r   r   r   r!   r<   r'   rc   _FREE_TIER_GUIDANCEre   )ri   r_   ro  	body_jsonr   err_obj
err_statuserr_message_raw_detailsdetails_listr  rj   rp  detailtype_urlreason_valuemdheader_retryrh   rl   s                       r   gemini_http_errorr    s    !F "I	 II 	 	 	III	RI 	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 A0/A0;I I! I!c                      e Zd Zd	dZd
dZdS )_GeminiChatCompletionsrY   'GeminiNativeClient'c                    || _         d S rs   _clientrv   rY   s     r   ru   z_GeminiChatCompletions.__init__=      r   kwargsr   r   c                &     | j         j        di |S Nr>   r  _create_chat_completionrv   r  s     r   createz_GeminiChatCompletions.create@  s    3t|3==f===r   NrY   r  r  r   r   r   rx   ry   rz   ru   r  r>   r   r   r  r  <  s<           > > > > > >r   r  c                      e Zd Zd	dZd
dZdS )_AsyncGeminiChatCompletionsrY   'AsyncGeminiNativeClient'c                    || _         d S rs   r  r  s     r   ru   z$_AsyncGeminiChatCompletions.__init__E  r  r   r  r   r   c                6   K    | j         j        di | d {V S r  r  r  s     r   r  z"_AsyncGeminiChatCompletions.createH  s3      9T\9CCFCCCCCCCCCr   NrY   r  r  r  r>   r   r   r  r  D  sB           D D D D D Dr   r  c                      e Zd ZddZdS )_GeminiChatNamespacerY   r  c                .    t          |          | _        d S rs   )r  completionsr  s     r   ru   z_GeminiChatNamespace.__init__M  s    1&99r   Nr  rx   ry   rz   ru   r>   r   r   r  r  L  s(        : : : : : :r   r  c                      e Zd ZddZdS )_AsyncGeminiChatNamespacerY   r  c                .    t          |          | _        d S rs   )r  r  r  s     r   ru   z"_AsyncGeminiChatNamespace.__init__R  s    6v>>r   Nr  r  r>   r   r   r  r  Q  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   rq   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poolr6   )r   RuntimeErrorr&   rI   r    r!   r   r   r   _default_headersr  chat	is_closedrJ   rK   Timeout_http)rv   r&   r   r  r%   r  r  rV   s           r   ru   zGeminiNativeClient.__init__Y  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  closerM   rv   s    r   r  zGeminiNativeClient.closev  sJ    	J 	 	 	DD	s   $ 
22c                    | S rs   r>   r  s    r   	__enter__zGeminiNativeClient.__enter__}  s    r   c                .    |                                   d S rs   )r  )rv   exc_typeexc_valexc_tbs       r   __exit__zGeminiNativeClient.__exit__  s    

r   Dict[str, str]c                R    dd| j         dd}|                    | j                   |S )Nr9   zhermes-agent (gemini-native))r8   Acceptzx-goog-api-keyz
User-Agent)r&   updater  )rv   r<   s     r   _headerszGeminiNativeClient._headers  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_iterator  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   ro   r   rm   r   r   r  rp   c          
     `   d }t          |
t                    r*|
                    d          p|
                    d          }t          |pg ||||||	|          }t	          |          }|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+   r;   r<   r%   rH   z%Invalid JSON from Gemini native API: gemini_invalid_json)rh   rU   ri   )r   )r   r   rQ   r  r   _stream_completionr   r  rL   r  rU   r  r;   rT   re   rI  )rv   r   r   r  r   r   r   r   r   r   r  r%   r  r   r  rW   ri   rX   r[   s                      r   r  z*GeminiNativeClient._create_chat_completion  sw     j$'' 	d(nn->??c:>>RbCcCcO&^##!+	
 	
 	
 %U++ 	Z**QX*YYY?????:??3WdmmooW^?__3&&#H---	mmooGG 	 	 	 ===*$0!	  
 	 )>>>>s   C1 1
D;DDr6   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          |           }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  rH   rl  z!Gemini streaming request failed: gemini_stream_error)rh   )
r  r  rU   r
   r  r[  rk  rJ   	HTTPErrorre   )ri   r_   r]  r\  rY  r[   r   r  rv   stream_headersr%   rW   s         r   
_generatorz9GeminiNativeClient._stream_completion.<locals>._generator  sY     Z&&vs.bi&jj (nv+s22$=h$G$G	/INNNNCE%!1(!;!; ( (%;E5J[%\%\ ( (E"'KKKK((( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ?   $===.   s;   B AB
=B 
BB BB C &B;;C )r   r  )r   r   r  )rv   r   r  r%   r  r  rW   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   rq   r   rq   )r   r  )r  r  r   r  )r   r   r   r  r  r   r   r   r   r   r   ro   r   rm   r   ro   r   r   r  rp   r%   r   r  r   r   r   )r   r   r  r   r%   r   r   r  )rx   ry   rz   r{   ru   r  r  r  r  staticmethodr  r  r  r>   r   r   r  r  V  s       MM #'48.2
 
 
 
 
 
:              \ (37'+$(!%/30? 0? 0? 0? 0? 0?d 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                z    || _         |j        | _        |j        | _        t          |           | _        || _        d S rs   )_syncr&   r   r  r  _real_client)rv   r  s     r   ru   z AsyncGeminiNativeClient.__init__  s<     
"*#,-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  2rs   )asyncio	to_threadr  r  )donerY  resultrv   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   rQ   r  r  r  r  r  r  )rv   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   rq   c                R   K   t          j        | j        j                   d {V  d S rs   )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  )rx   ry   rz   r{   ru   r  r  r>   r   r   r  r    sV        II
( 
( 
( 
(   2 2 2 2 2 2r   r  )r   r   r   r   )r   r   r   r   )
r&   r   r   r   r   r   r%   r'   r   r   )ra   r   r   r   )r}   r   r   r   )r}   r   r   r   )r   r   r   r   )r   r   r   r   rs   )rl   r   r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   rp   )r   r   r   rp   )r   r   r   r   r   r   r   ro   r   rm   r   ro   r   r   r   r   r   r   )r  r   r   r   )r   r   r   rp   )r   r   r   r   )rZ   r   r   r   r   r   )r   r   r}   r   rL  rp   r  r   r  r   r   rK  )ri   rR  r   rS  )r\  r   r   r   r]  r^  r   r_  )ri   rR  r_   r   r   re   );r{   
__future__r   r  r   r;   loggingr0  r-  typesr   typingr   r   r   r   r	   rJ   agent.bounded_responser
   agent.gemini_schemar   	getLoggerrx   rN   rI   r  r   r#   r`   rc   ru  rM   re   r   r   r   r   r   r   r   r   r   r  r  r  r2  rI  rK  rQ  r[  rk  r  r  r  r  r  r  r  r>   r   r   <module>r     s     # " " " " "       ! ! ! ! ! ! 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:    4C( C( C( C(LL L L L0   $   & #' $!3 3 3 3 3 3l: : : :      4B B B BJ	 	 	 	 	 	 	 	 04#'+ + + + + +\   2O O O Of =AO O O O O Od> > > > > > > >D D D D D D D D: : : : : : : :
? ? ? ? ? ? ? ?
E E E E E E E EP2 2 2 2 2 2 2 2 2 2r   