
    `gj[                       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j8                        Zd	Zd
Z d9dZ!d:dZ"efddd	 	 	 	 	 	 	 	 	 d;dZ#d<dZ$dZ% G d de      Z&d=dZ'd>dZ(d?dZ)d@dZ*	 dA	 	 	 	 	 dBdZ+dCdZ,dDdZ-dEdZ.dFdZ/dddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dGdZ0dHd Z1dId!Z2dJd"Z3dKd#Z4 G d$ d%e
      Z5d&ddd&d'	 	 	 	 	 	 	 	 	 	 	 dLd(Z6dMd)Z7dNd*Z8dd+	 	 	 	 	 dOd,Z9 G d- d.      Z: G d/ d0      Z; G d1 d2      Z< G d3 d4      Z= G d5 d6      Z> G d7 d8      Z?y# e$ r dZY w xY w)Pa  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  c                    | xs dj                         }|j                         }dD ]5  }|j                  |      s|t        |      d j                         xs |c S  |S )zEStrip Gemini's own provider prefix from an aggregator-style model id. )zgoogle/zgemini/N)striplower
startswithlen)modelnameloweredprefixs       N/root/.hermes/venv/lib/python3.12/site-packages/agent/gemini_native_adapter.pybare_gemini_model_idr   4   sb    KR DjjlG( 6f%F%++-556 K    c                    t        | xs d      j                         j                  d      j                         }|syd|vry|j	                  d       S )z>Return True when the endpoint speaks Gemini's native REST API.r   /Fz!generativelanguage.googleapis.com/openai)strr   rstripr   endswith)base_url
normalizeds     r   is_native_gemini_base_urlr!   >   sR    X^$**,33C8>>@J**<""9---r   gemini-2.5-flashg      $@)r   timeoutc          	        | xs dj                         }|syt        |xs t              j                         j                  d      }|st        }|j	                         j                  d      r|dt        d        }| d| d}dd	d
igdgddid}	 t        j                  |      5 }|j                  |d|i|ddt         d      }	ddd       	j                  j                         D ci c]  \  }}|j	                         | }}}|j!                  d      }|r	 t#        |      }||dk  ry||dkD  ry|	j(                  dk(  r'd}	 |	j*                  xs d}d|j	                         v ryyd|	j(                  cxk  rdk  ry yy# 1 sw Y   xY w# t        $ r }
t        j                  d|
       Y d}
~
yd}
~
ww xY wc c}}w # t$        t&        f$ r d}Y w xY w# t        $ r d}Y w xY w)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: %sz"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)   )api_keyr   r   r#   r3   normalized_baseurlpayloadclientrespexckvheaders_lower
rpd_headerrpd_val	body_texts                    r   probe_gemini_tierr[   H   s)    =b


!C(=&=>DDFMMcRO1''	2)*;S^O<XeW,<
=C$/?@A.2G
\\'* 		f;;s|$6+88I)J	  D		 /3ll.@.@.BCdaQWWY\CMC""#GHJ	*oG 7d?7T>3				RI )//++
d$$ % U		 		  ;SA D
 :& 	G	  	I	sZ   F +"FF 2G$G G# FF 	G#F>>GG G #G10G1c                ,    | syd| j                         v S )zEReturn True when a Gemini 429 message indicates free-tier exhaustion.Fr>   )r   )error_messages    r   is_free_tier_quota_errorr^      s    ---///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                  L     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coderM   responseretry_afterdetailsc               r    t         |   |       || _        || _        || _        || _        |xs i | _        y N)super__init__rc   rM   rd   re   rf   )selfmessagerc   rM   rd   re   rf   	__class__s          r   rj   zGeminiAPIError.__init__   s;     	!	& &}"r   )rl   r   rc   r   rM   Optional[int]rd   zOptional[httpx.Response]re   Optional[float]rf   Optional[Dict[str, Any]]returnNone)__name__
__module____qualname____doc__rj   __classcell__)rm   s   @r   r`   r`      se    H '%)-1'+,0%% 	%
 #% +% %% *% 
% %r   r`   c                   | yt        | t              r| S t        | t              rg }| D ]}  }t        |t              r|j                  |       %t        |t              s6|j                  d      dk(  sK|j                  d      }t        |t              sm|j                  |        dj                  |      S t        |       S )Nr   typer)   
)
isinstancer   listappenddictrI   join)contentpiecespartr)   s       r   _coerce_content_to_textr      s    '3'4  	(D$$d#D$'DHHV,<,Fxx'dC(MM$'	( yy  w<r   c                B   t        | t              st        |       }|rd|igS g S g }| D ]b  }t        |t              r|j	                  d|i       (t        |t
              s9|j                  d      }|dk(  r9|j                  d      }t        |t              sq|st|j	                  d|i       |dk(  s|j                  d      xs i j                  d      xs d}t        |t              r|j                  d      s	 |j                  dd      \  }}|j                  d	d      d   j                  d
d      d   }t        j                  |      }	|j	                  d|t        j                  |	      j                  d      di       e |S # t        $ r Y tw xY w)Nr)   ry   	image_urlrP   r   zdata:,r/   :;r   
inlineDataascii)mimeTypedata)r{   r|   r   r   r}   r~   rI   r   splitbase64	b64decoderE   	b64encodedecode)
r   r)   r-   itemptyperP   headerencodedmimeraws
             r   _extract_multimodal_partsr      s   gt$&w/#'/R/"$E dC LL&$($% F?88F#D$$fd^,k!HH[)/R44U;ArCc3's~~g/F"%))C"3||C+A.44S!<Q?&&w/ LL $( & 0 0 5 < <W E#+: L  s   AF	FFc                f   | j                  d      xs i }t        |t              sy |j                  d      xs |j                  d      }t        |t              rC|j                  d      xs |j                  d      }t        |t              r|rt        |      S d S t        |t              r|r|S y )Nextra_contentgooglethought_signaturethoughtSignature)rI   r{   r~   r   )	tool_callextrar   sigs       r   _tool_call_extra_signaturer      s    MM/*0bEeT"YYx BEII.A$BF&$jj,-O<N1O%c3/Cs3xATA&#6r   c                t   | j                  d      xs i }|j                  dd      }	 t        |t              r|rt        j                  |      ni }t        |t              sd|i}dt        |j                  d      xs d      |di}t        |       }|r||d	<   |S # t        j
                  $ r d|i}Y dw xY w)
Nfunction	argumentsr   _raw_valuefunctionCallr   )r   argsr   )rI   r{   r   r9   loadsJSONDecodeErrorr~   r   )r   fnargs_rawr   r   r   s         r   _translate_tool_call_to_geminir      s    	z	"	(bBvvk2&H"'1(C'@Xtzz(#SU dD!$ 	v,"-
D 39=#4 K  "!"s   )B B76B7c                   |xs i }t        | j                  d      xs d      }t        | j                  d      xs |j                  |      xs |xs d      }t        | j                  d            }	 |j                         j	                  d      rt        j                  |      nd }t        |t              r|nd|i}d||d	iS # t
        j                  $ r d }Y 4w xY w)
Ntool_call_idr   r   toolr   ){[outputfunctionResponse)r   rd   )
r   rI   r   r   r   r9   r   r   r{   r~   )rl   tool_name_by_call_idr   r   r   parsedrd   s          r    _translate_tool_result_to_geminir     s     052w{{>28b9LF 	##L1		 	D &gkk)&<=G(/(B(B:(NG$TX $FD1v'7JH 
   s   56C C C c                @   g }g }i }| D ]  }t        |t              st        |j                  d      xs d      }|dk(  r*|j	                  t        |j                  d                   b|dv r!|j	                  dt        ||      gd       |dk(  rd	nd}g }t        |j                  d            }|j                  |       |j                  d
      xs g }	t        |	t              r|	D ]  }
t        |
t              st        |
j                  d      xs |
j                  d      xs d      }t        |
j                  d      xs i j                  d      xs d      }|r|r|||<   |j	                  t        |
              |s|j	                  ||d        g }|D ]>  }|r)|d   d   |d   k(  r|d   d   j                  |d          .|j	                  |       @ |}d }dj                  d |D              j                         }|rdd|igd}||fS )Nr,   r(   systemr   >   r   r   )r   r+   	assistantr   
tool_callsidcall_idr   r   r   r-   rz   c              3  &   K   | ]	  }|s|  y wrh    ).0r   s     r   	<genexpr>z)_build_gemini_contents.<locals>.<genexpr>p  s     ItDdIs   r)   )r{   r~   r   rI   r}   r   r   r   extendr|   r   r   r   )messagessystem_text_partsr0   r   msgr,   gemini_roler-   content_partsr   r   r   	tool_namemerged_contentsr   system_instructionjoined_systems                    r   _build_gemini_contentsr   0  s?   #%%'H+- (C#t$3776?,f-8$$%<SWWY=O%PQ''OO"81E
 !%!4g&&(1#'')2DE]#WW\*0b
j$'' L	i.#&y}}T':'\immI>V'\Z\#]L #immJ&?&E2%J%J6%R%XVX ZI#	=F,\:LL!?	!JKL OO[5ABQ(Cd -/O ,r26:gfoMB(//0@A""7+	,
 HIII/@IIOOQM&.6=:Q9RS'''r   c                   t        | t              sg S g }| D ]  }t        |t              s|j                  d      xs i }t        |t              s:|j                  d      }t        |t              r|s^d|i}|j                  d      }t        |t              r|r||d<   |j                  d      }t        |t              rt        |      |d<   |j                  |        |rd|igS g S )Nr   r   description
parametersfunctionDeclarations)r{   r|   r~   rI   r   r   r}   )toolsdeclarationsr   r   r   declr   r   s           r   _translate_tools_to_geminir   v  s    eT"	)+L "$%XXj!'R"d#vvf~$$D &~ff]+k3'K"-DVVL)
j$'!@!LDD!!"" 8D#\23KKr   c                   | y 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              r@| j                  d	      xs i }|j                  d
      }t        |t              r
|rdd|gdiS y )NautofunctionCallingConfigmodeAUTOrequiredANYnoneNONEr   r   )r   allowedFunctionNames)r{   r   r~   rI   )tool_choicer   r   s      r    _translate_tool_choice_to_geminir     s    +s#& +ff-=>>*$+fe_==& +ff-=>>+t$__Z(.Bvvf~dC T+eVZU[-\]]r   c                   t        | t              r| sy | j                  d| j                  d            }| j                  d| j                  d            }| j                  d| j                  d            }i }t        |t        t        f      rt        |      |d<   t        |t
              r||d<   t        |t              r1|j                         r!|j                         j                         |d<   |xs d S )NthinkingBudgetthinking_budgetincludeThoughtsinclude_thoughtsthinkingLevelthinking_level)	r{   r~   rI   rJ   floatboolr   r   r   )configbudgetincludelevelr    s        r   _normalize_thinking_configr     s    fd#6ZZ(&**5F*GHFjj*FJJ7I,JKGJJ

3C(DEE!#J&3,''*6{
#$'4 (/
$%%%++-&+kkm&9&9&;
?#r   )r   r   temperature
max_tokenstop_pstopthinking_configc                :   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 )Nr0   systemInstructionr   
toolConfigr   r.   topPstopSequencesthinkingConfigr1   )r   r   r    GEMINI_DEFAULT_MAX_OUTPUT_TOKENSr{   r|   r   r   )r   r   r   r   r   r   r   r   r0   r   requestgemini_toolstool_configgeneration_confignormalized_thinkings                  r   build_gemini_requestr    s     $:(#C H )84G'9#$-e4L'2;?K +(*+6-(/9+, 0P+,$)&!5?d5KTRUVZR[Q\/*4_E.A*+&7"#Nr   c                l    dddddd}|j                  t        | xs d      j                         d      S )Nr   lengthcontent_filter)STOP
MAX_TOKENSSAFETY
RECITATIONOTHERr   )rI   r   upper)reasonmappings     r   _map_gemini_finish_reasonr    s=    "&G ;;s6<R(..0&99r   c                V    | j                  d      }t        |t              r|rdd|iiS y )Nr   r   r   )rI   r{   r   )r   r   s     r   _tool_call_extra_from_partr    s1    
((%
&C#s.455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,   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hexrJ   time)r   rl   choicer&  s       r   _empty_responser,    s    G 1gVLF-A>	E tzz|'',-. DIIK  r   c                
   | j                  d      xs g }t        |t              r|st        |      S t        |d   t              r|d   ni }t        |t              r|j                  d      ni }t        |t              r|j                  d      ng }g }g }g }t        |xs g       D ]^  \  }	}
t        |
t              s|
j                  d      du r4t        |
j                  d      t              r|j                  |
d          _t        |
j                  d      t              r|j                  |
d          |
j                  d      }t        |t              s|j                  d	      s	 t        j                  |j                  d
      xs i d      }t        dt        j                         j                  d d  d|	t        t        |d	         |            }t!        |
      }|r||_        |j                  |       a |rdn&t%        t        |j                  d      xs d            }| j                  d      xs i }t        t'        |j                  d      xs d      t'        |j                  d      xs d      t'        |j                  d      xs d      t        t'        |j                  d      xs d                  }dj)                  |      xs d }t        d|rdj)                  |      nd |xs d ||d       }t        d||      }t        d t        j                         j                  d d  d!t'        t+        j*                               ||g|"      S # t        t        f$ r d}Y w xY w)#N
candidatesr   r   r-   thoughtTr)   r   r   r   F)ensure_ascii{}call_r   r   r   r   )r   ry   r  r   r   finishReasonr   usageMetadatapromptTokenCountcandidatesTokenCounttotalTokenCountcachedContentTokenCountr  r  r   r  r  r  r!  r"  )rI   r{   r|   r,  r~   	enumerater   r}   r9   dumpsrK   rL   r   r'  r(  r)  r  r   r  rJ   r   r*  )rS   r   r.  candcontent_objr-   text_piecesreasoning_piecesr   r  r   fcargs_strr   r   r  
usage_metar&  r  rl   r+  s                        r   translate_gemini_responserC    s   ,'-2Jj$'zu%%&z!}d;:a=D)3D$)?$((9%RK(2;(EKOOG$2EK"$(*J "- )t$%88I$&:dhhv6F+L##DL1dhhv&,tF|,XXn%b$BFF6N ::bffVn&:O (4::<++CR012(c"V*oR	I 7t<M*7	'i(1)4 %/L4McRVRZRZ[iRjRpnpNq4rM/*0bJ*..);<ABjnn-CDIJ(9:?a@-jnn-FGL1M
	E ()1TI(3$%#G 1g]SFtzz|'',-. DIIK  C z*   s   0*M--NNc                      e Zd Zy)_GeminiStreamChunkN)rs   rt   ru   r   r   r   rE  rE  W  s    r   rE  r   )r   tool_call_deltar  r  c                r   dd d d d d}|r||d<   |t        |j                  dd      |j                  d      xs$ dt        j                         j                  d d  d	t        |j                  d
      xs d|j                  d      xs d            }|j                  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,   r   r   r  r  r   r  r   r   r2  r   r   r   r   r   r3  )r  r   ry   r   r   r   r  r  )r  deltar  r  zchat.completion.chunkr"  r   )r   rI   r'  r(  r)  r{   r~   r   rE  rJ   r*  )
r   r   rF  r  r  delta_kwargs
tool_deltar   rH  r+  s
             r   _make_stream_chunkrK  [  sR    !$L ")Y"$!%%gq1""4(KeDJJL4D4DSb4I3J,K$$((06B)--k:@b	

 (++O<mT*'4J$&0\\"$-[!,5()+l+E1EOFtzz|'',-.&DIIK  r   c              #    K   d}| j                         D ]  }|s||z  }d|v s|j                  dd      \  }}|j                  d      }|s.|j                  d      s@|dd  }|dk(  r y 	 t	        j
                  |      }t        |t              r| d|v rv y # t        j                  $ r t        j                  d|d d	        Y w xY ww)
Nr   rz   r/   zdata:    z[DONE]zNon-JSON Gemini SSE line: %sr?   )	iter_textr   r   r   r9   r   r   rF   rG   r{   r~   )rd   bufferchunkliner   rQ   s         r   _iter_sse_eventsrS    s     F##% %fn!<<a0LD&;;t$D??8,8Dx**T* '4(! fn	  '' ;T$3ZHs5   "CAC-BCC,C
CCCc                t   | j                  d      xs g }|sg S t        |d   t              r|d   ni }t        |t              r(|j                  d      xs i j                  d      xs g ng }g }t        |      D ]/  \  }}t        |t              s|j                  d      du r?t        |j                  d      t              r |j                  t        ||d                jt        |j                  d      t              r$|d   r|j                  t        ||d   	             |j                  d
      }	t        |	t              s|	j                  d      st	        |	d         }
	 t        j                  |	j                  d      xs i dd      }t        |j                  d      t              r|j                  d      nd}t        j                  ||
|dd      }|j                  |      }|6t        |      dt        j                         j                  d d  dd}|||<   |}t	        |j                  d      xs d      }|r'||k(  rd}n|j                  |      r|t        |      d  }||d<   |j                  t        ||d   |d   |
|t!        |      d             2 t	        |j                  d      xs d      }|r|rdn
t#        |      }t        ||      }| j                  d      xs i }|rt%        t'        |j                  d       xs d      t'        |j                  d!      xs d      t'        |j                  d"      xs d      t%        t'        |j                  d#      xs d      $      %      |_        |j                  |       |S # t        t        f$ r d}Y  w xY w)&Nr.  r   r   r-   r/  Tr)   )r   r  )r   r   r   r   r   F)r0  	sort_keysr1  r   r   )
part_indexr   r   )rU  r2  r   )r  r   last_argumentsrW  r  r   )r  r   r   r   r   )r   rF  r4  r   )r   r  r5  r6  r7  r8  r9  r  r  )rI   r{   r~   r:  r   r}   rK  r9   r;  rK   rL   r   r'  r(  r)  r   r  r  r   rJ   r&  )eventr   tool_call_indicesr.  r<  r-   chunksrV  r   r@  r   rA  r   call_keyslotemitted_argumentsrW  finish_reason_rawmappedfinish_chunkrB  s                        r   translate_stream_eventra    s~   <(.BJ	&z!}d;:a=D@J4QU@Vdhhy!'R,,W5;\^E')F%e, 3
D$%88I$&:dhhv6F+LMM,5DLQRdhhv&,fMM,5$v,OPXXn%b$BFF6Nr&z?D ::bffVn&:Z^_ AK488TfKgil@m); <suzz", ):
 H %((2D| !23!$**,"2"23B"7!89&(
 /3!(+ ( *:!;!ArBN~-(*%((8(0^1D1E(F%%-D!"MM"!%g"4j $%6)CD)I%	Q3j DHH^4:;!28QRc8d)VL YY/52
!0!*..1C"D"IJ"%jnn5K&L&QPQ"R 0A!B!GaH&5"%jnn5N&O&TST"U'	"L 	l#Mu z*   s   ++N""N76N7rZ   c                  | j                   }i }|	 | j                  }|xs d}|r(	 t        j                  |      }t        |t              r|}t        |t              r|j                  d      nd }t        |t              si }t        |j                  d      xs d      j                         }t        |j                  d      xs d      j                         }|j                  d      }t        |t              r|ng }	d}
d }i }|	D ]  }t        |t              st        |j                  d      xs d      }|
r5|j                  d      sG|j                  d      }t        |t              r|}
|j                  d	      }t        |t              s|} | j                  j                  d
      xs | j                  j                  d      }|r	 t        |      }d| }|dk(  rd}n|dk(  rd}n|dk(  rd}|rd| d|xs d d| }nd| d|d d  }|dk(  rt!        |xs |      r	|t"        z   }t%        |||| |||
||d      S # t        $ r d}Y :w xY w# t        t        f$ r i }Y "w xY w# t        t        f$ r d }Y w xY w)Nr   errorstatusrl   rf   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  rl   rb   )rM   r)   rE   r9   r   r{   r~   rL   rK   rI   r   r   r|   r   r:   r   r^   _FREE_TIER_GUIDANCEr`   )rd   rZ   re  	body_jsonr   err_obj
err_statuserr_message_raw_detailsdetails_listr  re   rf  detailtype_urlreason_valuemdheader_retryrc   rl   s                       r   gemini_http_errorrw    s    !!F "I	 I RI	ZZ	*F&$'"	 )39d(CimmG$Ggt$W[[*0b1779Jgkk),2399;K;;y)L#-lD#A<rLF#'K!H 
&$'vzz'*0b1(++,CD!::h/L,,%J'B"d#
 ##''6](:J:J:N:N}:]L	-K &"D}$	3$	3' :+@*A[MR)&IdsO3DE
 }1+2JK//  "	
 w  	I	 I& 	I	: :& 	K	s4   I
 'I I4 
III10I14JJc                      e Zd ZddZddZy)_GeminiChatCompletionsc                    || _         y rh   _clientrk   rR   s     r   rj   z_GeminiChatCompletions.__init__G  	    r   c                :     | j                   j                  di |S Nr   r|  _create_chat_completionrk   kwargss     r   createz_GeminiChatCompletions.createJ  s    3t||33=f==r   NrR   z'GeminiNativeClient'r  r   rq   r   rs   rt   ru   rj   r  r   r   r   ry  ry  F  s    >r   ry  c                      e Zd ZddZddZy)_AsyncGeminiChatCompletionsc                    || _         y rh   r{  r}  s     r   rj   z$_AsyncGeminiChatCompletions.__init__O  r~  r   c                V   K    | j                   j                  di | d {   S 7 wr  r  r  s     r   r  z"_AsyncGeminiChatCompletions.createR  s&     9T\\99CFCCCCs    )')NrR   z'AsyncGeminiNativeClient'r  r  r   r   r   r  r  N  s    Dr   r  c                      e Zd ZddZy)_GeminiChatNamespacec                $    t        |      | _        y rh   )ry  completionsr}  s     r   rj   z_GeminiChatNamespace.__init__W  s    1&9r   Nr  rs   rt   ru   rj   r   r   r   r  r  V  s    :r   r  c                      e Zd ZddZy)_AsyncGeminiChatNamespacec                $    t        |      | _        y rh   )r  r  r}  s     r   rj   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	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZd Zd ZddZe	dd	       Z
d
ddddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddddZy)GeminiNativeClientzCMinimal OpenAI-SDK-compatible facade over Gemini's native REST API.N)r   default_headersr#   http_clientc                  |xs dj                         st        d      || _        |xs t        j	                  d      }|j                  d      r|d t        d        }|| _        t        |xs i       | _	        t        |       | _        d| _        |xs1 t        j                  |xs t        j                  dddd	      
      | _        y )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poolr2   )r   RuntimeErrorrN   r@   r   r   r   r   r~   _default_headersr  chat	is_closedrA   rB   Timeout_http)rk   rN   r   r  r#   r  _rO   s           r   rj   zGeminiNativeClient.__init__c  s     2$$&4  #>'>FFsK##I.-.?Y@O' $_%: ;(.	  
ELL]u}}TTX\]%

r   c                f    d| _         	 | j                  j                          y # t        $ r Y y w xY w)NT)r  r  closerE   rk   s    r   r  zGeminiNativeClient.close  s0    	JJ 		s   $ 	00c                    | S rh   r   r  s    r   	__enter__zGeminiNativeClient.__enter__  s    r   c                $    | j                          y rh   )r  )rk   exc_typeexc_valexc_tbs       r   __exit__zGeminiNativeClient.__exit__  s    

r   c                ~    dd| j                   dt         ddt         d}|j                  | j                         |S )Nr4   r5   z (gemini-native))r6   Acceptzx-goog-api-keyz
User-Agentr7   )rN   rD   updater  )rk   r:   s     r   _headerszGeminiNativeClient._headers  sJ    .("ll */)::JK#00A!B	
 	t,,-r   c                <    	 dt        |       fS # t        $ r Y yw xY w)NF)TN)nextStopIteration)iterators    r   _advance_stream_iteratorz+GeminiNativeClient._advance_stream_iterator  s(    	$x.(( 		s    	r"   F)r   r   streamr   r   r   r   r   r   
extra_bodyr#   c          
     (   d }t        |
t              r$|
j                  d      xs |
j                  d      }t        |xs g ||||||	|      }t	        |      }|r| j                  |||      S | j                   d| d}| j                  j                  ||| j                         |      }|j                  dk7  rt        |      	 |j                         }t        ||      S # t        $ r"}t        d	| d
|j                  |      |d }~ww xY w)Nr   r   )r   r   r   r   r   r   r   r   )r   r   r#   r&   r'   r9   r:   r#   r?   z%Invalid JSON from Gemini native API: gemini_invalid_json)rc   rM   rd   )r   )r{   r~   rI   r  r   _stream_completionr   r  rC   r  rM   rw  r9   rL   r`   rC  )rk   r   r   r  r   r   r   r   r   r   r  r#   r  r   r   rP   rd   rQ   rT   s                      r   r  z*GeminiNativeClient._create_chat_completion  s,     j$'(nn->?c:>>RbCcO&^##!+	
 %U+**QX*YYxw.>?::??3WdmmoW^?_3&#H--	mmoG )>>  	 7u=*$00!	
 	s   	C& &	D/DDr2   c                     j                    d dt         j                               dd<   d fd} |       S )Nr&   z:streamGenerateContent?alt=sseztext/event-streamr  c               3  r  K   	 j                   j                  d	
      5 } | j                  dk7  rt        |       }t	        | |      i }t        |       D ]  }t        ||      D ]  }|   	 d d d        y # 1 sw Y   y xY w# t        j                  $ r}t        d| d      |d }~ww xY ww)NPOSTr  r?   rb  z!Gemini streaming request failed: gemini_stream_error)rc   )
r  r  rM   r
   rw  rS  ra  rA   	HTTPErrorr`   )rd   rZ   rY  rX  rQ  rT   r   r   rk   stream_headersr#   rP   s         r   
_generatorz9GeminiNativeClient._stream_completion.<locals>._generator  s     ZZ&&vs.bi&j (nv++s2$=h$G	/INNCE%!1(!; (%;E5J[%\ (E"'K((( ( ( ?? $7u=. sL   B7 B AA?6B >B7?BB B7B B4B//B44B7)rq   Iterator[_GeminiStreamChunk])r   r~   r  )rk   r   r   r#   r  r  rP   s   ```` @@r   r  z%GeminiNativeClient._stream_completion  sH    xw.LMdmmo.#6x 	 	  |r   )rN   r   r   Optional[str]r  Optional[Dict[str, str]]r#   r   r  zOptional[httpx.Client]r  r   rq   rr   rq   rr   )rq   zDict[str, str])r  r  rq   z)tuple[bool, Optional[_GeminiStreamChunk]])r   r   r   zOptional[List[Dict[str, Any]]]r  r   r   r   r   r   r   ro   r   rn   r   ro   r   r   r  rp   r#   r   r  r   rq   r   )r   r   r   Dict[str, Any]r#   r   rq   r  )rs   rt   ru   rv   rj   r  r  r  r  staticmethodr  r  r  r   r   r   r  r  `  s=   M #'48.2
 
  	

 2
 
 ,
 
 

:   (37'+$(!%/30? 0? 1	0?
 0? 0? 0? %0? "0? 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y)	AsyncGeminiNativeClientz?Async wrapper used by auxiliary_client for native Gemini calls.c                    || _         |j                  | _        |j                  | _        t        |       | _        || _        y rh   )_syncrN   r   r  r  _real_client)rk   sync_clients     r   rj   z AsyncGeminiNativeClient.__init__  s9     
"**#,,-d3	 (r   c                    K   t        |j                  d            }t        j                   j                  j
                  j                  j                  fi | d {   |sS d fd} |       S 7 w)Nr  c                   K   	 t        j                  j                  j                         d {   \  } }| ry | >7 wrh   )asyncio	to_threadr  r  )donerQ  resultrk   s     r   _async_streamzFAsyncGeminiNativeClient._create_chat_completion.<locals>._async_stream  sA     $+$5$5djj6Y6Y[a$bbe	 bs   /AAA)rq   r   )r   rI   r  r  r  r  r  r  )rk   r  r  r  r  s   `   @r   r  z/AsyncGeminiNativeClient._create_chat_completion  sc     fjj*+(()D)D)K)KVvVVM	  Ws   AA9 A7!A9c                r   K   t        j                  | j                  j                         d {    y 7 wrh   )r  r  r  r  r  s    r   r  zAsyncGeminiNativeClient.close
  s$     

 0 0111s   -757N)r  r  r  r  )rs   rt   ru   rv   rj   r  r  r   r   r   r  r    s    I
(2r   r  )r   r   rq   r   )r   r   rq   r   )
rN   r   r   r   r   r   r#   r   rq   r   )r]   r   rq   r   )r   r   rq   r   )r   r   rq   List[Dict[str, Any]])r   r  rq   r  )r   r  rq   r  rh   )rl   r  r   r  rq   r  )r   r  rq   z5tuple[List[Dict[str, Any]], Optional[Dict[str, Any]]])r   r   rq   r  )r   r   rq   rp   )r   r   rq   rp   )r   r  r   r   r   r   r   ro   r   rn   r   ro   r   r   r   r   rq   r  )r  r   rq   r   )r   r  rq   rp   )r   r   rq   r   )rS   r  r   r   rq   r   )r   r   r   r   rF  rp   r  r  r  r   rq   rE  )rd   httpx.Responserq   zIterator[Dict[str, Any]])rX  r  r   r   rY  zDict[str, Dict[str, Any]]rq   zList[_GeminiStreamChunk])rd   r  rZ   r  rq   r`   )@rv   
__future__r   r  r   r9   loggingr*  r'  typesr   typingr   r   r   r   r	   rA   agent.bounded_responser
   agent.gemini_schemar   	getLoggerrs   rF   
hermes_cli_hermes_clir   __version__rD   rE   r@   r   r   r!   r[   r^   rk  r`   r   r   r   r   r   r   r   r   r   r  r  r  r,  rC  rE  rK  rS  ra  rw  ry  r  r  r  r  r  r   r   r   <module>r     s    #       ! 6 6  < ?			8	$$+112O M  $)  . ,J $JJJ 	J
 J 	JZ0) %Y %*$#L
0 6:2 4C(LL0$& #' $!3"3 3 	3
 !3 3 3 3 3 3l:4BJ	 	 04#'++ + .	+
 !+ + +\2Of =AOO,9OOd> >D D: :
? ?
I IX2 2K  Os   E( (E32E3