
    +j^                        % S r SSKrSSKrSSKJr  SSKJr  SSKJr  SSKJ	r	J
r
  SSKrSSKJr  SSKrSSKJrJrJrJr  SS	KJrJrJrJrJrJrJrJrJrJrJrJ r J!r!J"r"J#r#J$r$  SS
K%J&r&J'r'J(r(J)r)J*r*J+r+J,r,J-r-J.r.J/r/J0r0J1r1J2r2  Sr3Sr4Sr5Sr6Sr7\Rp                  " \Rr                  " SS/S9SS9r: " S S\;\5      r< SOS\=\R|                     S\R~                  \@\R~                     -  S\AS\@\   4S jjrBS\S-  S\;S\C4S jrDS\S \
S!   \;-  S\@\   4S" jrES\S\;4S# jrFSPS\S$\CS\R~                  4S% jjrGS\S\HS-  4S& jrIS'\R                  S\@\   4S( jrKS)\R                  S\@\   4S* jrMS\@\R~                     S\@\R                     4S+ jrOS,\@\R                     S\@\R                     4S- jrPS\=\R|                     S.\;S/\	S\4S0 jrQS.\;S/\	S\R\\A4   4S1 jrS\5\6S2.S\=\R|                     S\@\R~                     S,\@\R                     S3\@\R                     S4\AS5\AS\@\   4S6 jjrT " S7 S8\R|                  5      rUS9S:S;.rV\W\;\;4   \XS<'   S=\;S\@\   4S> jrY " S? S@\R|                  5      rZ " SA SB\R|                  5      r[ " SC SD\R|                  5      r\ " SE SF\R|                  5      r] " SG SH\R|                  5      r^SI r_ " SJ SK\R|                  5      r` " SL SM\5      raS\a4SN jrbg)Qz
API Nodes for Gemini Multimodal LLM Usage via Remote API
See: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference
    N)Enum)fnmatch)BytesIO)AnyLiteral)override)IOComfyExtensionInputTypes)GeminiContentGeminiFileDataGeminiGenerateContentRequestGeminiGenerationConfigGeminiGenerateContentResponseGeminiImageConfig!GeminiImageGenerateContentRequestGeminiImageGenerationConfigGeminiInlineDataGeminiMimeType
GeminiPart
GeminiRoleGeminiSystemInstructionContentGeminiTextPartGeminiThinkingConfigModality)ApiEndpointaudio_to_base64_stringbytesio_to_image_tensordownload_url_to_image_tensorget_number_of_imagessync_optensor_to_base64_stringupload_audio_to_comfyapiupload_image_to_comfyapiupload_images_to_comfyapiupload_video_to_comfyapivalidate_stringvideo_to_base64_stringz/proxy/vertexai/geminii  @
   i   u  You are an expert image-generation engine. You must ALWAYS produce an image.
Interpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.
If a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.
Prioritize generating the visual representation above any text, formatting, or conversational requests.model
resolutionwidgetsa  
    (
      $m := widgets.model;
      $r := widgets.resolution;
      $isFlash := $contains($m, "nano banana 2");
      $flashPrices := {"1k": 0.0696, "2k": 0.1014, "4k": 0.154};
      $proPrices := {"1k": 0.134, "2k": 0.134, "4k": 0.24};
      $prices := $isFlash ? $flashPrices : $proPrices;
      {"type":"usd","usd": $lookup($prices, $r), "format":{"suffix":"/Image","approximate":true}}
    )
    
depends_onexprc                        \ rS rSrSrSrSrSrg)GeminiImageModelQ   z/
Gemini Image Model Names allowed by comfy-api
gemini-2.5-flash-image-previewgemini-2.5-flash-image N)__name__
__module____qualname____firstlineno____doc__gemini_2_5_flash_image_previewgemini_2_5_flash_image__static_attributes__r7       </home/wildlama/comfy/ComfyUI/comfy_api_nodes/nodes_gemini.pyr3   r3   Q   s     &F"5r@   r3   clsimagesimage_limitreturnc                 "  ^#    / nUS:  a  [        S5      e[        U[        5      (       a  UOU/n[        S U 5       5      nUS::  a  [        S5      eUS:X  a  UO
[	        XR5      n[	        US5      nSS0nXg:  a	  SU S	3S
S.n[        U U4SU0UD6I S h  vN n	U	 H1  n
UR                  [        [        [        R                  U
S9S95        M3     Xg:  a  / nU H`  m[        TR                  5      S:X  a3  UR                  U4S j[        TR                  S   5       5       5        MO  UR                  T5        Mb     [        Xv5       H<  nUR                  [        [        [        R                  [!        X   5      S9S95        M>     U$  N7f)Nr   zPimage_limit must be greater than or equal to 0 when creating Gemini image parts.c              3   8   #    U  H  n[        U5      v   M     g 7fNr!   ).0imgs     rA   	<genexpr>%create_image_parts.<locals>.<genexpr>e   s     HKS+C00K   zINo images provided to create_image_parts; at least one image is required.r*   
wait_labelzUploading reference imageszUploading reference images (z+)F)rO   show_batch_index
max_imagesmimeTypefileUrifileData   c              3   .   >#    U  H
  nTU   v   M     g 7frH   r7   )rJ   itensors     rA   rL   rM      s     F/E!F1I/E   rS   data
inlineData)
ValueError
isinstancelistsumminr&   appendr   r   r   	image_pnglenshapeextendranger   r#   )rB   rC   rD   image_partsimages_listtotal_imageseffective_maxnum_url_imagesupload_kwargsreference_images_urlsreference_image_urlflatidxrZ   s                @rA   create_image_partsru   Z   s    
 %'KQkll 0:&$/G/GVfXKHKHHLqdee %01$4L#l:XM +N')EFM% 98HK %
 #<# "# 	#   5'+55/	
  5 %#%!F6<< A%FuV\\!_/EFFF#	 "
 7C/!/!9!94TY?  8 ?s   BFFC6Fmimepatternc                 6    U c  g[        U R                  U5      $ )zPCheck if a MIME type matches a pattern. Supports fnmatch globs (e.g. 'image/*').F)r   value)rv   rw   s     rA   _mime_matchesrz      s    |4::w''r@   response	part_typetextc                    U R                   (       di  U R                  (       aM  U R                  R                  (       a2  U R                  n[        SUR                   SUR                   S35      e[        S5      e/ n/ nU R                    GHQ  nUR
                  (       a;  UR
                  R                  5       S:X  a  UR                  UR
                  5        MP  UR                  b  UR                  R                  c  Mv  UR                  R                   H  nUS:X  a$  UR                  (       a  UR                  U5        M-  UR                  (       a8  [        UR                  R                  U5      (       a  UR                  U5        Mv  UR                  (       d  M  [        UR                  R                  U5      (       d  M  UR                  U5        M     GMT     U(       d  U(       a  [        SU 35      eU$ )z
Filter response parts by their type.

Args:
    response: The API response from Gemini.
    part_type: Type of parts to extract ("text" or a MIME type).

Returns:
    List of response parts matching the requested type.
z(Gemini API blocked the request. Reason: z ()zGemini API returned no response candidates. If you are using the `IMAGE` modality, try changing it to `IMAGE+TEXT` to view the model's reasoning and understand why image generation failed.IMAGE_PROHIBITED_CONTENTr}   z)Gemini API blocked the request. Reasons: )
candidatespromptFeedbackblockReasonr`   blockReasonMessagefinishReasonupperre   contentpartsr}   r_   rz   rS   rV   )r{   r|   feedbackr   blocked_reasons	candidateparts          rA   get_parts_by_typer      s    ""x'>'>'J'J..H:8;O;O:PPRS[SnSnRoopq  x
 	
 EO((	!!i&<&<&B&B&DHb&b""9#9#9:$	(9(9(?(?(G%%++DF"tyyT"]4??3K3KY%W%WT"=1G1G#S#ST" , ) _D_DUVWWLr@   c                 z    [        U S5      nSR                  U Vs/ s H  o"R                  PM     sn5      $ s  snf )z
Extract and concatenate all text parts from the response.

Args:
    response: The API response from Gemini.

Returns:
    Combined text from all text parts in the response.
r}   
)r   joinr}   )r{   r   r   s      rA   get_text_from_responser      s3     h/E99E2EDiiE2332s   8thoughtc                 h  #    / n[        U S5      nU H  nUR                  SL U:w  a  M  UR                  (       a?  [        R                  " UR                  R
                  5      n[        [        U5      5      nO'[        UR                  R                  5      I S h  vN nUR                  U5        M     [        U5      S:X  aV  U(       d9  [        U 5      R                  5       nU(       a  [        SU 35      e[        S5      e[         R"                  " S5      $ [         R$                  " USS9$  N7f)Nzimage/*Tr   z2Gemini did not generate an image. Model response: zGemini did not generate an image. Try rephrasing your prompt or changing the response modality to 'IMAGE+TEXT' to see the model's reasoning.)      r   rW   )dim)r   r   r_   base64	b64decoder]   r   r   r    rV   rT   re   rg   r   stripr`   torchzeroscat)r{   r   image_tensorsr   r   
image_datareturned_imagemodel_messages           rA   get_image_from_responser      s    ')Mh	2ELLD W,??))$//*>*>?J4WZ5HIN#?@U@U#VVN^,  =Q28<BBDM #UVcUd!eff0 
 {{-..99]** Ws   BD2D0BD2c                    U R                   (       d  g U R                   S;   a  SnSnSnOU R                   S;   a  SnSnSnOtU R                   S;   a  SnSnS	nO]U R                   S
;   a  SnSnSnOFU R                   S:X  a  SnSnSnO/U R                   S:X  a  SnSnSnOU R                   S:X  a  SnSnSnOg U R                  R                  U-  nU R                  R                  (       a_  U R                  R                   HE  nUR                  [
        R                  :X  a  XCUR                  -  -  nM4  XBUR                  -  -  nMG     U R                  R                  (       a  XBU R                  R                  -  -  nUS-  $ )N)gemini-2.5-pro-preview-05-06gemini-2.5-prog      ?g      $@        )gemini-2.5-flash-preview-04-17gemini-2.5-flashg333333?g      @)r5   r6   g      >@)gemini-3-pro-previewgemini-3.1-pro-preview   g      (@gemini-3.1-flash-lite-previewg      ?g      ?gemini-3-pro-image-previewg      ^@gemini-3.1-flash-image-previewg      ?g      @g      N@g    .A)	modelVersionusageMetadatapromptTokenCountcandidatesTokensDetailsmodalityr   IMAGE
tokenCountthoughtsTokenCount)r{   input_tokens_priceoutput_text_tokens_priceoutput_image_tokens_pricefinal_pricerY   s         rA   calculate_tokens_pricer      s      RR!#' $'!			 # 
 "#' $'!			 # 
 "#' $(!			"T	T#' $'!			"A	A!#' $'!			">	>#' $)!			"B	B #& $(!((99<NNK55''??AzzX^^+1<<GG!,,FF	 @
 00(2H2H2[2[[[$$r@   video_inputc                     [        U [        R                  R                  [        R                  R
                  S9n[        [        [        R                  US9S9/$ )zOConvert a single video input to Gemini API compatible parts (inline MP4/H.264).container_formatcodecr\   r^   )
r)   r   VideoContainerMP4
VideoCodecH264r   r   r   	video_mp4)r   base_64_strings     rA   create_video_partsr   &  sS    +e&:&:&>&>eFVFVF[F[N 	''11#	
 r@   audio_inputc           
         / n[        U S   R                  S   5       Hi  n[        R                  " U S   U   R	                  S5      U S   S9n[        USSS9nUR                  [        [        [        R                  US9S	95        Mk     U$ )
z[Convert an audio input to Gemini API compatible parts (one inline MP3 part per batch item).waveformr   sample_rater   r   mp3
libmp3lamer   
codec_namer\   r^   )rj   rh   r   Audio	unsqueezer   re   r   r   r   	audio_mp3)r   audio_partsbatch_indexaudio_at_indexaudio_bytess        rA   create_audio_partsr   5  s    $&K[4::1=> ,[9CCAF#M2

 -"#

 	++55$	
 ?( r@   c                    ^ / nU  H`  m[        TR                  5      S:X  a3  UR                  U4S j[        TR                  S   5       5       5        MO  UR	                  T5        Mb     U$ )zTExpand any batched image tensors into individual (H, W, C) frames, preserving order.rW   c              3   .   >#    U  H
  nTU   v   M     g 7frH   r7   )rJ   rY   rK   s     rA   rL   "_flatten_images.<locals>.<genexpr>T  s     >*=Q#a&*=r[   r   )rg   rh   ri   rj   re   )rC   framesrK   s     @rA   _flatten_imagesr   O  sT    !#Fsyy>QMM>%		!*=>>MM#	 
 Mr@   audiosc           	          / nU  H_  nUS   n[        UR                  S   5       H;  nUR                  [        R                  " X4   R                  S5      US   S95        M=     Ma     U$ )z[Expand any batched audio inputs into individual single-clip audio inputs, preserving order.r   r   r   r   )rj   rh   re   r   r   r   )r   clipsaudior   rY   s        rA   _flatten_audior   Z  se    !E$x~~a()ALLhk.C.CA.FTYZgThij *  Lr@   kindpayloadc                 Z  #    US:X  a2  [        XSSS9I Sh  vN n[        [        [        R                  US9S9$ US:X  a3  [        XS	S
SS9I Sh  vN n[        [        [        R                  US9S9$ [        XSS9I Sh  vN n[        [        [        R                  US9S9$  N NV N'7f)zPUpload a single media unit to ComfyAPI storage and return a fileData (URL) part.imagez	image/pngzUploading image)	mime_typerO   NrR   rU   r   r   r   z	audio/mp3)r   r   r   zUploading video)rO   )	r%   r   r   r   rf   r$   r   r'   r   )rB   r   r   urls       rA   _media_url_partr   d  s     w,S[]noo>>;S;S]`#abbw,5\U`
 
 >>;S;S]`#abb(BST
TC~~7O7OY\]^^ p
 Us3   B+B%8B+B'0B+B)$B+'B+)B+c                 T   U S:X  a  [        USS9n[        R                  nOmU S:X  a  [        USSS9n[        R                  nOK[        U[        R                  R                  [        R                  R                  S9n[        R                  n[        [        X2S	9S
9[        U5      4$ )zSEncode a single media unit as an inline base64 part; returns (part, base64_length).r   z
image/webp)r   r   r   r   r   r   r\   r^   )r#   r   
image_webpr   r   r)   r   r   r   r   r   r   r   r   rg   )r   r   r]   rv   s       rA   _media_inline_partr   r  s    w&w,G((	%gR^_''%e&:&:&>&>eFVFVF[F[
 ''!14!KLcRViWWr@   )
url_budgetmax_inline_bytesvideosr   r   c                  #    U Vs/ s H  nSU4PM	     sn[        U5       Vs/ s H  nSU4PM	     sn-   [        U5       Vs/ s H  nSU4PM	     sn-   n	/ n
SnSnU	 Hr  u  pX:  a*  U
R                  [        XU5      I Sh  vN 5        US-  nM4  [	        X5      u  nnUU-  nX:  a  [        SUS-   S	U S
35      eU
R                  U5        Mt     U
$ s  snf s  snf s  snf  Nb7f)a  Build Gemini parts for multimodal inputs (images, audio, video).

fileData URLs are preferred for every media type: the upload is fetched directly by the
model, keeping the request body tiny regardless of media size. The URL budget is shared
across all media and assigned largest-first (video, then audio, then images), so that if it
is ever exhausted the inline-base64 overflow is limited to the smallest items. Total inline
payload is capped by `max_inline_bytes`.
videor   r   r   Nr   z$Too much media to send inline (over i   zMB after the first zK inputs are uploaded as URLs). Reduce the number or size of attached media.)r   r   re   r   r   r`   )rB   rC   r   r   r   r   vafunitsr   url_usedinline_bytesr   r   r   nbytess                    rA   build_gemini_media_partsr     s    $  &&v!'1v&!/!7
8!7AGQ<!7
8	9!0!8
9!8AGQ<!8
9	: 
 !EHL LLs'BBCMH)$8f*67GK7X6YYl,ik  	T  L+ 	'
8
9 Cs2   C'CC'CC'C 1C'C%
A#C'c                       \ rS rSrSr\S 5       r\     SS\S\S\S\	R                  S-  S	\	R                  S-  S
\	R                  S-  S\\   S-  S\S\R                   4S jj5       rSrg)
GeminiNodei  aB  
Node to generate text responses from a Gemini model.

This node allows users to interact with Google's Gemini AI models, providing
multimodal inputs (text, images, audio, video, files) to generate coherent
text responses. The node works with the latest Gemini models, handling the
API communication and response parsing.
c                 X   [         R                  " SSSS[         R                  R                  SSSSS	9[         R                  R                  S
/ SQSSS9[         R
                  R                  SSSSSSS9[         R                  R                  SSSS9[         R                  R                  SSSS9[         R                  R                  SSSS9[         R                  " S5      R                  SSSS9[         R                  R                  SSSSS SS!9/[         R                  R                  5       /[         R                  R                  [         R                  R                  [         R                  R                  /S[         R                  " [         R                   " S
/S"9S#S$9SS%9
$ )&Nr   Google Geminipartner/text/GeminizGenerate text responses with Google's Gemini AI model. You can provide multiple types of inputs (text, images, audio, video) as context for generating more relevant and meaningful responses.promptT zText inputs to the model, used to generate a response. You can include detailed instructions, questions, or context for the model.	multilinedefaulttooltipr+   )r   r   r   r   r   gemini-3-1-progemini-3-1-flash-liter  1The Gemini model to use for generating responses.optionsr  r  seed*   r       ^  When seed is fixed to a specific value, the model makes a best effort to provide the same response for repeated requests. Deterministic output isn't guaranteed. Also, changing the model or parameter settings, such as the temperature, can cause variations in the response even when you use the same seed value. By default, a random seed value is used.r  rd   maxcontrol_after_generater  rC   qOptional image(s) to use as context for the model. To include multiple images, you can use the Batch Images node.optionalr  r   z/Optional audio to use as context for the model.r   z/Optional video to use as context for the model.GEMINI_INPUT_FILESfilessOptional file(s) to use as context for the model. Accepts inputs from the Gemini Generate Content Input Files node.system_prompt8Foundational instructions that dictate an AI's behavior.r  r  r  r  advancedr-   a  
                (
                  $m := widgets.model;
                  $contains($m, "gemini-2.5-flash") ? {
                    "type": "list_usd",
                    "usd": [0.0003, 0.0025],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens"}
                  }
                  : $contains($m, "gemini-2.5-pro") ? {
                    "type": "list_usd",
                    "usd": [0.00125, 0.01],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
                  }
                  : ($contains($m, "gemini-3-pro-preview") or $contains($m, "gemini-3-1-pro")) ? {
                    "type": "list_usd",
                    "usd": [0.002, 0.012],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
                  }
                  : $contains($m, "gemini-3-1-flash-lite") ? {
                    "type": "list_usd",
                    "usd": [0.00025, 0.0015],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
                  }
                  : {"type":"text", "text":"Token-based"}
                )
                r/   
node_iddisplay_namecategorydescriptioninputsoutputshiddenis_api_nodeprice_badgeis_deprecated)r	   SchemaStringr   ComboIntImager   VideoCustomOutputHiddenauth_token_comfy_orgapi_key_comfy_org	unique_id
PriceBadgePriceBadgeDependsrB   s    rA   define_schemaGeminiNode.define_schema  s   yy (*P 		"b	     -O   *+/?   !U   !M  
 !M  
 		./55!X 6  		#"!V!   q@D 		  " 		..		++		##
 //	B: ]o
 o	
r@   Nr   r+   r	  rC   r   r   r  r  rE   c	                 d  #    US:X  a  SnOUS:X  a  SnOUS:X  a  Sn[        US9/n	Ub"  U	R                  [        X5      I S h  vN 5        Ub  U	R                  [        U5      5        Ub  U	R                  [	        U5      5        Ub  U	R                  U5        S n
U(       a  [        [        US9/S S9n
[        U [        [         SU 3S	S
9[        [        [        R                  U	S9/U
S9[        [        S9I S h  vN n[!        U5      n["        R$                  " U=(       d    S5      $  N N07f)Nr   r   r  r  r   r}   r   role/POSTpathmethodr9  r   )contentssystemInstructionendpointr]   response_modelprice_extractor#Empty response from Gemini model...)r   ri   ru   r   r   r   r   r"   r   GEMINI_BASE_ENDPOINTr   r   r   userr   r   r   r	   
NodeOutput)rB   r   r+   r	  rC   r   r   r  r  r   gemini_system_promptr{   output_texts                rA   executeGeminiNode.execute)  s<     **,E&&,E--3E#-6#:";LL1#>>?LL+E23LL+E23LL##A]jIkHlsw#x   )=(>aw&GPVW-!'__# #7 92
 
  -X6}}[Q,QRR; ?
s%   AD0D,B9D0=D.>/D0.D0r7   )NNNNr   )r8   r9   r:   r;   r<   classmethodr4  strintr   r)  r   r*  rb   r   r	   rI  rL  r?   r7   r@   rA   r   r     s     p
 p
d  &*$($()-1S1S 1S 	1S
 d"1S {{T!1S {{T!1S J$&1S 1S 
1S 1Sr@   r   r   r   )Gemini 3.1 ProGemini 3.1 Flash-LiteGEMINI_V2_MODELSthinking_defaultc                    [         R                  R                  S[         R                  R                  [         R                  R                  S5      [        SS5       Vs/ s H  nSU 3PM
     snSS9SS	9[         R                  R                  S
[         R                  R                  [         R                  R                  S
5      S/SS9SS	9[         R                  R                  S[         R                  R                  [         R                  R                  S5      S/SS9SS	9[         R                  " S5      R                  SSSS9[         R                  R                  SSS/U SS9[         R                  R                  SSSSSSSS 9[         R                  R                  S!S"SSSS#SS 9[         R                  R                  S$S%S&S'S(SS)9/$ s  snf )*zWPer-model inputs revealed by the model DynamicCombo (shared media + sampling controls).rC   r   r      image_r   namesrd   zCOptional image(s) to use as context for the model. Up to 16 images.templater  r   audio_1z4Optional audio clip to use as context for the model.r   video_1z4Optional video clip to use as context for the model.r  r  TzbOptional file(s) to use as context for the model. Accepts inputs from the Gemini Input Files node.r  thinking_levelLOWHIGHzHow hard the model reasons internally before answering. HIGH improves quality on difficult tasks but costs more (thinking) tokens and is slower.r  temperature      ?r          @{Gz?zRControls randomness. Lower is more focused/deterministic, higher is more creative.)r  rd   r  stepr  r  top_pffffff?z`Nucleus sampling: sample from the smallest token set whose cumulative probability reaches top_p.max_output_tokensi      i   a  Maximum tokens to generate, including the model's internal thinking. With thinking_level HIGH, a low value can leave no room for the answer; raise this if responses come back empty or truncated. The model stops early when finished, so a higher cap costs nothing extra for short replies.)r  rd   r  r  r  )r	   Autogrowr   TemplateNamesr)  rj   r   r*  r+  r'  Floatr(  )rT  rY   s     rA   _gemini_text_model_inputsrm  d  s    	[[..w'-21b\:\s|\: / 
 Z 	 	
 	[[..w' k / 
 K 	 	
 	[[..w' k / 
 K 	 	
 			&'--? 	. 	
 	FO$g	 	 	
 	h 	 	
 	v 	 	
 	9  	 
	
wF F
 ;s    Gc                   f    \ rS rSr\S 5       r\ SS\S\S\S\S\	R                  4
S jj5       rS	rg
)GeminiNodeV2i  c                    [         R                  " SSSSS[         R                  R                  SSSS	S
9[         R                  R                  S[         R                  R                  S[        S5      5      [         R                  R                  S[        S5      5      /SS9[         R                  R                  SSSSSSS9[         R                  R                  SSSSSSS9/[         R                  R                  5       /[         R                  R                  [         R                  R                  [         R                  R                  /S[         R                  " [         R                  " S/S9SS9S9
$ )Nro  r   r   zText GenerationzGenerate text responses with Google's Gemini models. Provide a text prompt and, optionally, one or more images, audio clips, videos, or files as multimodal context.r   Tr   zNText input to the model. Include detailed instructions, questions, or context.r   r+   rQ  r`  rR  r_  z/The Gemini model used to generate the response.r  r  r	  r
  r   izUSeed for sampling. Set to 0 for a random seed. Deterministic output isn't guaranteed.r  r  z<Foundational instructions that dictate the model's behavior.)r  r  r  r  r  r-   a%  
                (
                  $m := widgets.model;
                  $contains($m, "lite") ? {
                    "type": "list_usd",
                    "usd": [0.00025, 0.0015],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
                  } : {
                    "type": "list_usd",
                    "usd": [0.002, 0.012],
                    "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
                  }
                )
                r/   )
r  r  r  essentials_categoryr  r  r   r!  r"  r#  )r	   r%  r&  r   DynamicComboOptionrm  r(  r,  r-  r.  r/  r0  r1  r2  r3  s    rA   r4  GeminiNodeV2.define_schema  sm   yy"(* 1c 		"l	    %%../?AZ[aAbc../FHabgHhi N &  "+/s   		#"!!Z   /B 		  " 		..		++		##
 //	BaA
 A	
r@   r   r+   r	  r  rE   c                   #    [        USSS9  [        US      n[        US9/nUR                  S5      =(       d    0 R	                  5        Vs/ s H	  owc  M  UPM     nnUR                  S5      =(       d    0 R	                  5        V	s/ s H	  oc  M  U	PM     n
n	UR                  S5      =(       d    0 R	                  5        Vs/ s H	  oc  M  UPM     nnU(       d  U
(       d  U(       a#  UR                  [        XX5      I S h  vN 5        UR                  S	5      nUb  UR                  U5        S nU(       a  [        [        US9/S S
9n[        U [        [         SU 3SS9[        [        [        R                  US9/[!        US   US   US   US:  a  UOS [#        US   S9S9US9[$        [&        S9I S h  vN n[)        U5      n[*        R,                  " U=(       d    S5      $ s  snf s  sn	f s  snf  N N?7f)NTr   strip_whitespace
min_lengthr+   r7  rC   r   r   r  r8  r:  r;  r<  r?  ra  rf  rh  r   r^  thinkingLevel)ra  topPmaxOutputTokensr	  thinkingConfigr@  generationConfigrA  rB  rF  )r(   rS  r   getvaluesri   r   r   r   r"   r   rG  r   r   r   rH  r   r   r   r   r   r	   rI  )rB   r   r+   r	  r  model_idr   trC   r   r   r   r   r  rJ  r{   rK  s                    rA   rL  GeminiNodeV2.execute  s     	!D#E'N3#-6#:";#ii17R??ASA!AS#ii06B>>@R@!@R#ii06B>>@R@!@RVvLL7VTTU		'"LL##A]jIkHlsw#x   )=(>az&JSYZ-!'__# "8 %m 4w$)*=$>!%t#7eL\F]#^" #7  92)
 
. -X6}}[Q,QRRK TRRT
s[   AHG.G.,H
G3G3,HG8G81HG=B7H?G? >H?Hr7   N)r   )r8   r9   r:   r;   rN  r4  rO  dictrP  r	   rI  rL  r?   r7   r@   rA   ro  ro    sk    B
 B
H   0S0S 0S 	0S
 0S 
0S 0Sr@   ro  c                       \ rS rSrSr\S 5       r\S\S\4S j5       r	\SS\S	\
\   S-  S\R                  4S
 jj5       rSrg)GeminiInputFilesi*  a4  
Loads and formats input files for use with the Gemini API.

This node allows users to include text (.txt) and PDF (.pdf) files as input
context for the Gemini model. Files are converted to the appropriate format
required by the API and can be chained together to include multiple files
in a single request.
c                    [         R                  " 5       n[        R                  " U5       Vs/ s H  nUR	                  5       (       d  M  UR
                  R                  S5      (       d"  UR
                  R                  S5      (       d  M\  UR                  5       R                  [        :  d  M  UPM     nn[        US S9nU Vs/ s H  o"R
                  PM     nn[        R                  " SSSS[        R                  R                  S	UU(       a  US
   OSSS9[        R                  " S5      R                  SSSS9/[        R                  " S5      R!                  5       /S9$ s  snf s  snf )z
For details about the supported file input types, see:
https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference
z.txt.pdfc                     U R                   $ rH   )name)xs    rA   <lambda>0GeminiInputFiles.define_schema.<locals>.<lambda>B  s    r@   )keyr  zGemini Input Filesr   u  Loads and prepares input files to include as inputs for Gemini LLM nodes. The files will be read by the Gemini model when generating a response. The contents of the text file count toward the token limit. 🛈 TIP: Can be chained together with other Gemini Input File nodes.filer   NzgInput files to include as context for the model. Only accepts text (.txt) and PDF (.pdf) files for now.r  r  TzAn optional additional file(s) to batch together with the file loaded from this node. Allows chaining of input files so that a single message can include multiple input files.r  )r  r  r  r  r  r   )folder_pathsget_input_directoryosscandiris_filer  endswithstatst_sizeGEMINI_MAX_INPUT_FILE_SIZEsortedr	   r%  r'  r   r+  r,  )rB   	input_dirr   input_filess       rA   r4  GeminiInputFiles.define_schema4  sU    !446	 ZZ	*
*yy{  ((AFFOOF,C    #==	 * 	 
 [.>?'23{!vv{3yy&-*T
 '.9KNtM	   		./55(!p 6   		./668/
 	

 4s   E*>E* E*1E*E/	file_pathrE   c                 F   UR                  S5      (       a  [        R                  O[        R                  n[	        US5       nUR                  5       nS S S 5        [        R                  " W5      R                  S5      n[        [        UUS9S9$ ! , (       d  f       ND= f)Nr  rbzutf-8r\   r^   )r  r   application_pdf
text_plainopenreadr   	b64encodedecoder   r   )rB   r  r   r   file_content
base64_strs         rA   create_file_part!GeminiInputFiles.create_file_part`  s    6?6H6H6P6PN22VdVoVo	)T"a668L #%%l3::7C
'"
 	
	 #"s   B
B Nr  r  c                     Uc  / n[         R                  " U5      nU R                  U5      n[        R                  " U/U-   5      $ )z-Loads and formats input files for Gemini API.)r  get_annotated_filepathr  r	   rI  )rB   r  r  r  input_file_contents        rA   rL  GeminiInputFiles.executeo  sJ     %!# 77=	 11)<}}014FFGGr@   r7   rH   )r8   r9   r:   r;   r<   rN  r4  rO  r   r  rb   r	   rI  rL  r?   r7   r@   rA   r  r  *  s}     )
 )
V 
 
 
 
 H3 HD4Dt4K HWYWdWd H Hr@   r  c                       \ rS rSr\S 5       r\     SS\S\S\S\R                  S-  S\
\   S-  S	\S
\S\S\R                  4S jj5       rSrg)GeminiImageiy  c                    [         R                  " SSSS[         R                  R                  SSSSS	9[         R                  R                  S
[
        [
        R                  SS9[         R                  R                  SSSSSSS9[         R                  R                  SSSS9[         R                  " S5      R                  SSSS9[         R                  R                  S/ SQSSSS9[         R                  R                  SSS /S!SSS"9[         R                  R                  S#S[        SS$SS%9/[         R                  R                  5       [         R                  R                  5       /[         R                  R                  [         R                  R                  [         R                  R                  /S[         R                   " S&S'9S(9	$ ))NGeminiImageNodez!Nano Banana (Google Gemini Image)partner/image/Geminiz)Edit images synchronously via Google API.r   TzText prompt for generationr   r  r  r  r+   r  r  r	  r
  r   r  r  r  rC   r  r  r  r  r  aspect_ratioauto1:12:33:23:44:34:55:49:1616:921:9r  zkDefaults to matching the output image size to that of your input image, or otherwise generates 1:1 squares.)r  r  r  r  response_modalities
IMAGE+TEXTr   mChoose 'IMAGE' for image-only output, or 'IMAGE+TEXT' to return both the generated image and a text response.)r  r  r  r  r  r  r  zO{"type":"usd","usd":0.039,"format":{"suffix":"/Image (1K)","approximate":true}})r1   	r  r  r  r  r  r   r!  r"  r#  )r	   r%  r&  r   r'  r3   r>   r(  r)  r+  GEMINI_IMAGE_SYS_PROMPTr,  r-  r.  r/  r0  r1  r3  s    rA   r4  GeminiImage.define_schema{  s   yy%<+C		"8	    ,,CCO	   *+/?   !U   		./55!X 6  "m":!   ))73[!!   		#"3!V!   k=~ !		  "
 		..		++		##
 j[P
 P	
r@   Nr   r+   r	  rC   r  r  r  r  rE   c	                 D  #    [        USSS9  [        US9/n	U(       d  SnUS:X  a
  [        5       O[        US9n
Ub"  U	R                  [	        X5      I S h  vN 5        Ub  U	R                  U5        S nU(       a  [        [        US9/S S9n[        U [        SU 3S	S
9[        [        [        R                  U	S9/[        US:X  a  S/OSS/U
S9US9[        [        S9I S h  vN n[         R"                  " [%        U5      I S h  vN ['        U5      5      $  N N7 N7f)NTr   rw  r7  r  )aspectRatior8  /proxy/vertexai/gemini/r;  r<  r?  r   TEXTresponseModalitiesimageConfigr  r]   rD  rE  )r(   r   r   ri   ru   r   r   r"   r   r   r   r   rH  r   r   r   r	   rI  r   r   )rB   r   r+   r	  rC   r  r  r  r  r   image_configrJ  r{   s                rA   rL  GeminiImage.execute  s/     	!D#-6#:";!L.:f.D(*J[htJuLL1#>>?LL##A]jIkHlsw#x  6ug>vN2!zeD "=5HG5S	Z`biYj ," #7	 92
 
  }}#:8#DDF\]eFfgg1 ?
  Es7   AD DBD $D%"D DD D D r7   )NNr  r  r   r8   r9   r:   r;   rN  r4  rO  rP  r   r)  rb   r   r	   rI  rL  r?   r7   r@   rA   r  r  y  s    Q
 Q
f  &*)-"#/+h+h +h 	+h
 d"+h J$&+h +h !+h +h 
+h +hr@   r  c                       \ rS rSr\S 5       r\   SS\S\S\S\S\S	\S
\R                  S-  S\
\   S-  S\S\R                  4S jj5       rSrg)GeminiImage2i  c                    [         R                  " SSSS[         R                  R                  SSSSS	9[         R                  R                  S
SS/S9[         R
                  R                  SSSSSSS9[         R                  R                  S/ SQSSS9[         R                  R                  S/ SQSS9[         R                  R                  SSS/S SS!9[         R                  R                  S"SS#S$9[         R                  " S%5      R                  S&SS'S$9[         R                  R                  S(S[        SS)SS*9/	[         R                  R                  5       [         R                  R                  5       /[         R                  R                  [         R                  R                  [         R                  R                  /S[        S+9	$ ),NGeminiImage2Nodez%Nano Banana Pro (Google Gemini Image)r  <Generate or edit images synchronously via Google Vertex API.r   TText prompt describing the image to generate or the edits to apply. Include any constraints, styles, or details the model should follow.r   r  r+   r   &Nano Banana 2 (Gemini 3.1 Flash Image)r  r	  r
  r   r  b  When the seed is fixed to a specific value, the model makes a best effort to provide the same response for repeated requests. Deterministic output isn't guaranteed. Also, changing the model or parameter settings, such as the temperature, can cause variations in the response even when you use the same seed value. By default, a random seed value is used.r  r  r  r  wIf set to 'auto', matches your input image's aspect ratio; if no image is provided, a 16:9 square is usually generated.r  r,   1K2K4KGTarget output resolution. For 2K/4K the native Gemini upscaler is used.rq  r  r  r   r  )r  r  r  rC   ^Optional reference image(s). To include multiple images, use the Batch Images node (up to 14).r  r  r  r  r  r  r  r  r	   r%  r&  r   r'  r(  r)  r+  r  r,  r-  r.  r/  r0  GEMINI_IMAGE_2_PRICE_BADGEr3  s    rA   r4  GeminiImage2.define_schema   s   yy&@+V		"[    9;cd   *+/?   "m"S	    .e  
 ))73[!   !X   		./55!X 6  		#"3!V!   o?B !		  "
 		..		++		##
 2_P
 P	
r@   Nr   r+   r	  r  r,   r  rC   r  r  rE   c
                 n  #    [        USSS9  US:X  a  Sn[        US9/n
Ub<  [        U5      S:  a  [        S5      eU
R	                  [        X5      I S h  vN 5        Ub  U
R	                  U5        [        US	9nUS
:w  a  XKl        S nU	(       a  [        [        U	S9/S S9n[        U [        SU 3SS9[        [        [        R                  U
S9/[!        US:X  a  S/OSS/US9US9["        [$        S9I S h  vN n[&        R(                  " [+        U5      I S h  vN [-        U5      5      $  N N7 N7f)NTr   rw  r  r   r7     5The current maximum number of supported images is 14.	imageSizer  r8  r  r;  r<  r?  r   r  r  r  r  )r(   r   r!   r`   ri   ru   r   r  r   r   r"   r   r   r   r   rH  r   r   r   r	   rI  r   r   )rB   r   r+   r	  r  r,   r  rC   r  r  r   r  rJ  r{   s                 rA   rL  GeminiImage2.executeT  sM     	!D<<4E#-6#:";#F+b0 !XYYLL1#>>?LL(:>6!'3$##A]jIkHlsw#x  6ug>vN2!zeD "=5HG5S	Z`biYj ," #7	 92
 
  }}#:8#DDF\]eFfgg9 ?
  Es7   AD5D/B"D59D1:"D5D3D51D53D5r7   NNr   r  r7   r@   rA   r  r    s    Q
 Q
f  &*)-0h0h 0h 	0h
 0h 0h !0h d"0h J$&0h 0h 
0h 0hr@   r  c                       \ rS rSr\S 5       r\   SS\S\S\S\S\S	\S
\S\R                  S-  S\
\   S-  S\S\R                  4S jj5       rSrg)GeminiNanoBanana2i  c                    [         R                  " SSSS[         R                  R                  SSSSS	9[         R                  R                  S
S/S9[         R
                  R                  SSSSSSS9[         R                  R                  S/ SQSSS9[         R                  R                  S/ SQSS9[         R                  R                  SSS/SS9[         R                  R                  S S!S"/S9[         R                  R                  S#SS$S%9[         R                  " S&5      R                  S'SS(S%9[         R                  R                  S)S[        SS*SS+9/
[         R                  R                  5       [         R                  R                  5       [         R                  R                  S,S-S.9/[         R                  R                  [         R                  R                  [         R                  R                  /S[        SS/9
$ )0Nr  Nano Banana 2r  r  r   Tr  r   r  r+   r  r  r	  r
  r   r  r  r  r  r  r  r  r  r,   r  r  rq  r  r   r  r  r  r^  MINIMALr`  rC   r  r  r  r  r  r  r  r  thought_imageoFirst image from the model's thinking process. Only available with thinking_level HIGH and IMAGE+TEXT modality.r  r  r  r  r3  s    rA   r4  GeminiNanoBanana2.define_schema  s   yy'(+V		"[    EF   *+/?   " #S!  &  .e  
 )$l3!  
 $&/   !X   		./55!X 6  		#"3!V!   KM^ !		  "!0W    		..		++		##
 2Gd
 d	
r@   Nr   r+   r	  r  r,   r  r^  rC   r  r  rE   c                   #    [        USSS9  US:X  a  Sn[        US9/nUb<  [        U5      S:  a  [        S5      eUR	                  [        X5      I S h  vN 5        U	b  UR	                  U	5        [        US	9nUS
:w  a  XLl        S nU
(       a  [        [        U
S9/S S9n[        U [        SU 3SS9[        [        [        R                  US9/[!        US:X  a  S/OSS/U[#        US9S9US9[$        [&        S9I S h  vN n[(        R*                  " [-        U5      I S h  vN [/        U5      [-        USS9I S h  vN 5      $  N NH N' N7f)NTr   rw  r  r   r7  r  r  r  r  r8  r  r;  r<  r?  r   r  rz  )r  r  r~  r  r  r   )r(   r   r!   r`   ri   ru   r   r  r   r   r"   r   r   r   r   rH  r   r   r   r   r	   rI  r   r   )rB   r   r+   r	  r  r,   r  r^  rC   r  r  r   r  rJ  r{   s                  rA   rL  GeminiNanoBanana2.execute  sg     	!D<<4E#-6#:";#F+b0 !XYYLL1#>>?LL(:>6!'3$##A]jIkHlsw#x  6ug>vN2!zeD "=5HG5S	Z`biYj ,#7n#U"
 #7
 92
 
" }})(33"8,)(DAA
 	
; ?
$ 4AsI   AEEB*EE
"E$E%E?E 	E
EEEr7   r  r  r7   r@   rA   r  r    s    e
 e
N  &*)-6
6
 6
 	6

 6
 6
 !6
 6
 d"6
 J$&6
 6
 
6
 6
r@   r  c                     [         R                  R                  S/ SQSSS9[         R                  R                  S/ SQSS	9[         R                  R                  S
SS/S9[         R                  R                  S[         R                  R	                  [         R
                  R                  S5      [        SS5       V s/ s H  n SU  3PM
     sn SS9SS9[         R                  " S5      R                  SSSS9/$ s  sn f )Nr  )r  r  r  r  r  r  r  r  r  r  r  z1:4z4:1z8:1z1:8r  r  r  r,   r  r  rq  r^  r  r`  r  rC   r   r      rW  r   rX  z3Optional reference image(s). Up to 14 images total.rZ  r  r  Tr  r  )r	   r'  r   rj  rk  r)  rj   r+  )rY   s    rA   _nano_banana_2_v2_model_inputsr  ,  s   
" K) 	 	
. 	&] 	 	

 	' 	 	
 	[[..w'-21b\:\s|\: / 
 J 	 	
 			&'--X 	. 	
U0 0J ;s    C=c                   v    \ rS rSr\S 5       r\   SS\S\S\S\S\S\	S	\	S
\
R                  4S jj5       rSrg)GeminiNanoBanana2V2i`  c                    [         R                  " SSSS[         R                  R                  SSSSS	9[         R                  R                  S
[         R                  R                  S[        5       5      /S9[         R                  R                  SSSSSSS9[         R                  R                  SSS/SS9[         R                  R                  SS[        SSSS9[         R                  R                  SSSSSSSSS 9[         R                  R                  S!S"SSSSS#SS 9/[         R                  R                  5       [         R                  R                  5       [         R                  R                  S$S%S&9/[         R                  R                  [         R                  R                  [         R                  R                   /S[         R"                  " [         R$                  " S
S'/S(9S)S*9S+9	$ ),Nr  r  r  r  r   Tr  r   r  r+   r  r  r	  r
  r   r  r  r  r  r   r  r  r  r  r  ra  rb  r   rc  rd  zGControls randomness in generation. Lower is more focused/deterministic.)r  rd   r  re  r  r  r  rf  rg  zGNucleus sampling threshold. Lower is more focused, higher more diverse.r  r  r  zmodel.resolutionr-   a)  
                (
                  $r := $lookup(widgets, "model.resolution");
                  $prices := {"1k": 0.0696, "2k": 0.1014, "4k": 0.154};
                  {"type":"usd","usd": $lookup($prices, $r), "format":{"suffix":"/Image","approximate":true}}
                )
                r/   r  )r	   r%  r&  r   rs  rt  r  r(  r'  r  rl  r)  r,  r-  r.  r/  r0  r1  r2  r3  s    rA   r4  !GeminiNanoBanana2V2.define_schemab  s   yy)(+V		"[    %%..D:< &  *+/?   )$l3!  
 		#"3!V!    !!e!  	  !e!  	i>@ !		  "!0W    		..		++		##
 //BT8UV	g]
 ]	
r@   r   r+   r	  r  r  ra  rf  rE   c                   #    [        USSS9  US   nUS:X  a  Sn	OUn	UR                  S5      =(       d    0 n
[        US9/nU
(       an  U
R                  5        Vs/ s H	  oc  M  UPM     nnU(       aC  [	        S	 U 5       5      S
:  a  [        S5      eUR                  [        X5      I S h  vN 5        UR                  S5      nUb  UR                  U5        [        US   S9nUS   S:w  a
  US   Ul	        S nU(       a  [        [        US9/S S9n[        U [        SU	 3SS9[        [        [         R"                  US9/[%        US:X  a  S/OSS/U['        US   S9UUS9US9[(        [*        S9I S h  vN n[,        R.                  " [1        U5      I S h  vN [3        U5      [1        USS9I S h  vN 5      $ s  snf  GN NN N- N7f)NTr   rw  r+   r  r   rC   r7  c              3   8   #    U  H  n[        U5      v   M     g 7frH   rI   )rJ   r  s     rA   rL   .GeminiNanoBanana2V2.execute.<locals>.<genexpr>  s     F1+A..rN   r  r  r  r,   r  r  r  r8  r  r;  r<  r?  r   r  r^  rz  )r  r  r~  ra  r|  r  r  r  )r(   r  r   r  rc   r`   ri   ru   r   r  r   r   r"   r   r   r   r   rH  r   r   r   r   r	   rI  r   r   )rB   r   r+   r	  r  r  ra  rf  model_choicer  rC   r   r  r   r  r  rJ  r{   s                     rA   rL  GeminiNanoBanana2V2.execute  s     	!DW~CC7H#H8$*#-6#:";;A==?/\?a?M/\FFFK$%\]]#5c#IIJ		'"LL(53FG F*',^'<L$##A]jIkHlsw#x  6xjA&Q2!zeD "=5HG5S	Z`biYj ,#7eL\F]#^ +" #7 92#
 
& }})(33"8,)(DAA
 	
I 0] J
( 4As\   AGG %G +AG.G/C
G9G:"GG
G7G8GG
GGr7   N)r   rb  rg  )r8   r9   r:   r;   rN  r4  rO  r  rP  floatr	   rI  rL  r?   r7   r@   rA   r  r  `  s    ^
 ^
@    <
<
 <
 	<

 !<
 <
 <
 <
 
<
 <
r@   r  c                   L    \ rS rSr\S\\\R                        4S j5       r	Sr
g)GeminiExtensioni  rE   c                 T   #    [         [        [        [        [        [
        [        /$ 7frH   )r   ro  r  r  r  r  r  )selfs    rA   get_node_listGeminiExtension.get_node_list  s&      
 	
s   &(r7   N)r8   r9   r:   r;   r   rb   typer	   	ComfyNoder  r?   r7   r@   rA   r	  r	    s)    	
T$r||*<%= 	
 	
r@   r	  c                     #    [        5       $ 7frH   )r	  r7   r@   rA   comfy_entrypointr    s     s   )r   )F)cr<   r   r  enumr   r   ior   typingr   r   r   typing_extensionsr   r  comfy_api.latestr	   r
   r   r   comfy_api_nodes.apis.geminir   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   comfy_api_nodes.utilr   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   rG  r  GEMINI_URL_INPUT_BUDGETGEMINI_MAX_INLINE_BYTESr  r1  r2  r  rO  r3   r  r  r)  rb   rP  ru   boolrz   r   r   r   r  r   r*  r   r   r   Tensorr   r   r   tupler   r   r   rS  r  __annotations__rm  ro  r  r  r  r  r  r  r	  r  r7   r@   rA   <module>r     s  
  	      &  = =    $     0 -  * n   ]]##Wl,CD

  6sD 6 :	bll	:KK$u{{++: : 
*	:z(- ( ( (( = ('RX/\_J_ (dhisdt (V4%B 4s 4+,I +TX +ejepep +61%%B 1%ut| 1%hEKK D4D EKK D4D 4D- $u||2D 4, ekk1B _tBLL1 _ _s _z _XS X3 X5S3I X, .3'	bll	'' ' 	' ' ' 
*'ToS oSf /<$ $sCx. H HU HVxS2<< xSvLHr|| LH^Bh",, BhJGh2<< GhTa
 a
H1h`
",, `
F
n 
 r@   