
    .cjÖ                       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dlZ eej                  Zn# e$ r dZY nw xY wd	Zd
Z dgdZ!dhdZ"efddddidZ#djdZ$dZ% G d de          Z&dkd Z'dld"Z(dmd&Z)dnd'Z*	 dodpd+Z+dqd.Z,drd0Z-dsd3Z.dtd5Z/dddddddd6dud>Z0dvd@Z1dwdBZ2dxdDZ3dydFZ4 G dG dHe
          Z5dIdddIdJdzdNZ6d{dRZ7d|dWZ8ddXd}dZZ9 G d[ d\          Z: G d] d^          Z; G d_ d`          Z< G da db          Z= G dc dd          Z> G de df          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_parametersz0.0.0z0https://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       =/home/ice/.hermes/hermes-agent/agent/gemini_native_adapter.pybare_gemini_model_idr   4   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#   >   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t           d          }	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application/jsonhermes-agent/)Content-TypeX-Goog-Api-Client)paramsjsonheadersz$probe_gemini_tier: network error: %sc                >    i | ]\  }}|                                 |S  r   ).0kvs      r   
<dictcomp>z%probe_gemini_tier.<locals>.<dictcomp>v   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_HERMES_VERSION	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_tierrc   H   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|$6)J)J)J 	   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	 
'C=1D	 =DD	 DD	 	
D9D44D97F FF	G GGerror_messagec                6    | sdS d|                                  v S )zEReturn True when a Gemini 429 message indicates free-tier exhaustion.FrI   rA   )rd   s    r   is_free_tier_quota_errorrf      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coderX   responseretry_afterdetailsmessager   rk   rX   Optional[int]rl   Optional[httpx.Response]rm   Optional[float]rn   Optional[Dict[str, Any]]r   Nonec                   t                                          |           || _        || _        || _        || _        |pi | _        d S N)super__init__rk   rX   rl   rm   rn   )selfro   rk   rX   rl   rm   rn   	__class__s          r   rx   zGeminiAPIError.__init__   sJ     	!!!	& &}"r   )ro   r   rk   r   rX   rp   rl   rq   rm   rr   rn   rs   r   rt   )__name__
__module____qualname____doc__rx   __classcell__)rz   s   @r   rh   rh      s^        HH '%)-1'+,0% % % % % % % % % % % %r   rh   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dictrT   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_urlrZ   r   zdata:,r3   :;r   
inlineDataascii)mimeTypedata)r   r   r   r   r   r   rT   r   splitbase64	b64decoderP   	b64encodedecode)
r   r-   r1   itemptyperZ   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)rT   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          |           }|pd	|d
<   |S )Nfunction	argumentsr   _raw_valuefunctionCallr   )r   args skip_thought_signature_validatorr   )rT   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==  1V4VD	Ks   -A A32A3ro   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   rl   )
r   rT   r   r   r   r=   r   r   r   r   )ro   r   r   r   r   parsedrl   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 rv   r@   )rB   r   s     r   	<genexpr>z)_build_gemini_contents.<locals>.<genexpr>t  s'      IItDIdIIIIIIr   r-   )r   r   r   rT   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   4  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   rT   r   r   r   )r   declarationsr   r   r   declr   r   s           r   _translate_tools_to_geminir   z  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_choicers   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   rT   )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   rT   rU   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   rr   r   rp   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   )rT   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   )rT   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   indexro   finish_reasoncached_tokensprompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details	chatcmpl-   chat.completionr   objectcreatedr   choicesusage)r   uuiduuid4hexrU   time)r   ro   choicer0  s       r   _empty_responser6    s      G 1gVLLLF-A>>>	  E .tz||',.. DIKK     r   r]   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,  )rT   r   r   r6  r   	enumerater   r   r=   dumpsrV   rW   r   r1  r2  r3  r  r   r  rU   r   r4  )r]   r   r8  candcontent_objr1   text_piecesreasoning_piecesr   r   r   fcargs_strr   r   r!  
usage_metar0  r  ro   r5  s                        r   translate_gemini_responserM    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)r{   r|   r}   r@   r   r   rO  rO  [  s        Dr   rO  r   )r   tool_call_deltar!  r  rP  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   r<  r*  r   r   r   r   r=  )r   r   r   r   r   r   r  r  )r   deltar!  r)  zchat.completion.chunkr,  r@   )r   rT   r1  r2  r3  r   r   r   rO  rU   r4  )
r   r   rP  r!  r  delta_kwargs
tool_deltar   rR  r5  s
             r   _make_stream_chunkrU  _  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   rl   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: %srJ   )	iter_textr   r    r   r=   r   r   rQ   rR   r   r   )rl   bufferchunkliner   r[   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 )&Nr8  r   r   r1   r9  Tr-   )r   r  )r   r   r   r   r   F)r:  	sort_keysr;  r   r   )
part_indexr   r   )re  r<  r*  )r   r   last_argumentsrg  r   r   )r   r   r   r   r   )r   rP  r>  r   )r   r!  r?  r@  rA  rB  rC  r"  r$  )rT   r   r   rD  r   r   rU  r=   rE  rV   rW   r   r1  r2  r3  r   r  r  r   rU   r0  )r`  r   ra  r8  rF  r1   chunksrf  r   rJ  r   rK  r   call_keyslotemitted_argumentsrg  finish_reason_rawmappedfinish_chunkrL  s                        r   translate_stream_eventro    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rb   rb   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statusro   rn   z@typez/google.rpc.ErrorInfor  metadatazRetry-Afterzretry-aftergemini_http_i  gemini_unauthorizedrH   gemini_rate_limitedi  gemini_model_not_foundzGemini HTTP z (z): zGemini returned HTTP z: i  )rs  r  rt  ro   rj   )rX   r-   rP   r=   r   r   r   rW   rV   rT   r   r   r   r!   r>   r'   rf   _FREE_TIER_GUIDANCErh   )rl   rb   rs  	body_jsonr   err_obj
err_statuserr_message_raw_detailsdetails_listr  rm   rt  detailtype_urlreason_valuemdheader_retryrk   ro   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 )_GeminiChatCompletionsr\   'GeminiNativeClient'c                    || _         d S rv   _clientry   r\   s     r   rx   z_GeminiChatCompletions.__init__K      r   kwargsr   r   c                &     | j         j        di |S Nr@   r  _create_chat_completionry   r  s     r   createz_GeminiChatCompletions.createN  s    3t|3==f===r   Nr\   r  r  r   r   r   r{   r|   r}   rx   r  r@   r   r   r  r  J  s<           > > > > > >r   r  c                      e Zd Zd	dZd
dZdS )_AsyncGeminiChatCompletionsr\   'AsyncGeminiNativeClient'c                    || _         d S rv   r  r  s     r   rx   z$_AsyncGeminiChatCompletions.__init__S  r  r   r  r   r   c                6   K    | j         j        di | d {V S r  r  r  s     r   r  z"_AsyncGeminiChatCompletions.createV  s3      9T\9CCFCCCCCCCCCr   Nr\   r  r  r  r@   r   r   r  r  R  sB           D D D D D Dr   r  c                      e Zd ZddZdS )_GeminiChatNamespacer\   r  c                .    t          |          | _        d S rv   )r  completionsr  s     r   rx   z_GeminiChatNamespace.__init__[  s    1&99r   Nr  r{   r|   r}   rx   r@   r   r   r  r  Z  s(        : : : : : :r   r  c                      e Zd ZddZdS )_AsyncGeminiChatNamespacer\   r  c                .    t          |          | _        d S rv   )r  r  r  s     r   rx   z"_AsyncGeminiChatNamespace.__init__`  s    6v>>r   Nr  r  r@   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   rt   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&   rK   r    r!   r   r   r   _default_headersr  chat	is_closedrL   rM   Timeout_http)ry   r&   r   r  r%   r  r  rY   s           r   rx   zGeminiNativeClient.__init__g  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  closerP   ry   s    r   r  zGeminiNativeClient.close  sJ    	J 	 	 	DD	s   $ 
22c                    | S rv   r@   r  s    r   	__enter__zGeminiNativeClient.__enter__  s    r   c                .    |                                   d S rv   )r  )ry   exc_typeexc_valexc_tbs       r   __exit__zGeminiNativeClient.__exit__  s    

r   Dict[str, str]c                v    dd| j         dt           ddt           d}|                    | j                   |S )Nr8   r9   z (gemini-native))r:   Acceptzx-goog-api-keyz
User-Agentr;   )r&   rO   updater  )ry   r>   s     r   _headerszGeminiNativeClient._headers  sQ    .("l L/KKK!B!B!B	
 	
 	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   rr   r   rp   r   r   r  rs   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%   rJ   z%Invalid JSON from Gemini native API: gemini_invalid_json)rk   rX   rl   )r   )r   r   rT   r  r   _stream_completionr   r  rN   r  rX   r  r=   rW   rh   rM  )ry   r   r   r  r   r   r   r   r   r   r  r%   r  r   r  rZ   rl   r[   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  rJ   rp  z!Gemini streaming request failed: gemini_stream_error)rk   )
r  r  rX   r
   r  r_  ro  rL   	HTTPErrorrh   )rl   rb   ra  r`  r]  r^   r   r  ry   stream_headersr%   rZ   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  )ry   r   r  r%   r  r  rZ   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   rt   r   rt   )r   r  )r  r  r   r  )r   r   r   r  r  r   r   r   r   r   r   rr   r   rp   r   rr   r   r   r  rs   r%   r   r  r   r   r   )r   r   r  r   r%   r   r   r  )r{   r|   r}   r~   rx   r  r  r  r  staticmethodr  r  r  r@   r   r   r  r  d  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 rv   )_syncr&   r   r  r  _real_client)ry   r  s     r   rx   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  2rv   )asyncio	to_threadr  r  )doner]  resultry   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   rT   r  r  r  r  r  r  )ry   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   rt   c                R   K   t          j        | j        j                   d {V  d S rv   )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  )r{   r|   r}   r~   rx   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   )rd   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   rv   )ro   r   r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   rs   )r   r   r   rs   )r   r   r   r   r   r   r   rr   r   rp   r   rr   r   r   r   r   r   r   )r  r   r   r   )r   r   r   rs   )r   r   r   r   )r]   r   r   r   r   r   )r   r   r   r   rP  rs   r!  r   r  r   r   rO  )rl   rV  r   rW  )r`  r   r   r   ra  rb  r   rc  )rl   rV  rb   r   r   rh   )@r~   
__future__r   r  r   r=   loggingr4  r1  typesr   typingr   r   r   r   r	   rL   agent.bounded_responser
   agent.gemini_schemar   	getLoggerr{   rQ   
hermes_cli_hermes_clir   __version__rO   rP   rK   r  r   r#   rc   rf   ry  rh   r   r   r   r   r   r   r   r   r   r  r  r  r6  rM  rO  rU  r_  ro  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	$	$$$$$c+122OO   OOO M  $)     . . . . ,J $J J J J J JZ0 0 0 0) % % % % %Y % % %*   $# # # #L
 
 
 
   8 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: : : : : : : :
? ? ? ? ? ? ? ?
I I I I I I I IX2 2 2 2 2 2 2 2 2 2s   A+ +A54A5