Ë
    âß²j  ã                  ó‚  — U d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlmZmZmZ  ej                   e«      ZdÎd„ZdZd	d	d	d	d
d
dddœZddd	d	d	d	d	d	dœZddd	d	dddddœZi d eddddddddd¬«	      “d edddddddddd d!d"œd# e ed$d%d&«      «      d'd'd(œd¬)«      “d* ed+ddd,d-d.d/d0ddd¬1«      “d2 ed3ddd4d5d6ed7d8d¬9«
      “d: ed;d<d=d>d?d@ddAdBdCdDddd¬E«      “dF edGd<d=dHdIdJedKd8d¬9«
      “dL edMdNd=dOdPdQedRd7dSd¬T«      “dU edVdNd=dWdXdYddRedZed[d¬\«      “d] ed^d_d=d`dadbddRedced[dddeidd¬f«      “dg edhdid=djdkdlddRedmed[dddeidd¬f«      “dn edod<d=dpdqdrddsdtdud¬v«      “dw edxdd=dydzd{ddRd|dKd0d¬}«      “d~ edd<d=d€d�d‚dddƒd„d¬…«      “d† ed‡dNd=dˆd‰dŠd‹dRdŒd�dd¬Ž«      “d� ed�dNd=d‘d’d“d‹dRdŒd�dd¬Ž«      “d” ed•d–d=d—d˜d™d‹dŒd�ddd¬š«      “d› edœdNd=d�dždŸdRdŒd�d¬ «
      “ ed¡dNd=d¢d£d¤d‹dd¥d¦dKd§dd¬¨«       ed©dNd=dªd«d¬d‹dd¥d¦dKd§dd¬¨«       ed­d<d=d®d¯d°ddRd±dtd�dd¬²«      d³œ¥Zd´edµ<   d*ZdÏdÐd¶„ZdÑd·„ZdÒd¸„ZdÓd¹„Z 	 	 	 	 	 	 	 	 	 	 dÔdº„Z!dÕd»„Z"da#ded¼<    ejH                  «       Z%da&ded½<   da'ded¾<    ejH                  «       Z(dÖd¿„Z)dÀ„ Z*d×dÁ„Z+dÂ„ Z,dØdÃ„Z-dÄZ.d&Z/dÏdÙdÅ„Z0dÆZ1dÇdÈdÉœZ2dÚdÛdÊ„Z3 G dË„ dÌe«      Z4dÜdÍ„Z5ddl6Z6y)ÝuØ  FAL.ai video generation backend.

The user picks a **model family** (e.g. "Pixverse v6"); the plugin routes to its text-to-video endpoint without
``image_url`` and to its image-to-video endpoint otherwise. Active-family precedence:
tool ``model=`` â†’ ``FAL_VIDEO_MODEL`` env â†’ ``video_gen.fal.model`` â†’ ``video_gen.model`` (family id or an endpoint
path containing one) â†’ ``DEFAULT_MODEL``. Auth via ``FAL_KEY`` or the managed Nous gateway; output is an HTTPS URL.
é    )ÚannotationsN)ÚAnyÚDictÚListÚOptionalÚTuple)ÚVideoGenProviderÚerror_responseÚsuccess_responser   c                ó&   — | ||||||d d d ddddœ|¥S )NF)ÚdisplayÚspeedÚpriceÚtierÚ	strengthsÚtext_endpointÚimage_endpointÚaspect_ratiosÚresolutionsÚ	durationsÚaudioÚnegativeÚseed© )r   r   r   r   ÚtextÚimageÚcapss          úC/home/ubuntu/.hermes/hermes-agent/plugins/video_gen/fal/__init__.pyÚ_familyr      sA   € Ø¨¸ÀtÐZcÐvzð  OTØ!°$ÀTÐTYÐglÐv{ñEð @DðEð Eó    )ú21:9ú16:9ú4:3ú1:1ú3:4ú9:16Ú768PÚ2KÚ4K)Ú480pÚ540pÚ720pÚ768pÚ1080pÚ2kÚ4kÚ2160pÚ480PÚ1080Pzltx-2.3zLTX 2.3 (22B)z~30-60sÚcheapz322B model with native audio generation. Affordable.z fal-ai/ltx-2.3-22b/text-to-videoz!fal-ai/ltx-2.3-22b/image-to-videoT)r   r   r   zltx-2.5zLTX 2.5z~30-90szdLightricks open-source audio-video model. Native audio, up to 20s / 4K (i2v), camera-motion presets.z%lightricks/ltx-2.5/text-to-video/fastz&lightricks/ltx-2.5/image-to-video/fast)r"   r&   )r,   r.   Ú1440pr1   r5   r1   )r/   r0   )é   é   r6   é   é   é
   )r5   r1   )Úduration_intr   r   Úresolution_aliasesr   Úduration_enumÚduration_cap_by_resolutionr   zpixverse-v6zPixverse v6z.Affordable. Negative prompts. 1-15s durations.z fal-ai/pixverse/v6/text-to-videoz!fal-ai/pixverse/v6/image-to-video©Ú360pr+   r,   r.   )é   é   )r   r   r   r   r   zseedance-2.0-minizSeedance 2.0 MinizAByteDance. Faster/cheaper Seedance tier, audio + lip-sync, 4-15s.z)bytedance/seedance-2.0/mini/text-to-videoz*bytedance/seedance-2.0/mini/image-to-video)r*   r,   )é   rB   )r   r   r   r   zveo3.1zVeo 3.1z~60-120sÚpremiumzBGoogle DeepMind. Cinematic, native audio, strong prompt adherence.zfal-ai/veo3.1zfal-ai/veo3.1/image-to-video)r,   r.   r0   )rC   é   )rC   r6   rE   Ús)r   r   r   r=   Úduration_suffixr   r   r   zseedance-2.0zSeedance 2.0z;ByteDance. Cinematic, synchronized audio + lip-sync, 4-15s.z$bytedance/seedance-2.0/text-to-videoz%bytedance/seedance-2.0/image-to-video)r*   r,   r.   zseedance-2.5zSeedance 2.5z~60-180szUByteDance flagship. Native 30s single-pass, audio in the same latent space, lip-sync.z$bytedance/seedance-2.5/text-to-videoz%bytedance/seedance-2.5/image-to-video)Úaspect_ratio)rC   é   )r   Úimage_drop_keysr   r   r   z
minimax-h3z
MiniMax H3zCMiniMax frontier. Native 2K (up to 4K), 5-15s, seven aspect ratios.zminimax/h3/text-to-videozminimax/h3/image-to-video)r'   r(   r)   )é   rB   )r;   rJ   r   r   r<   r   Úaudio_nativezminimax-h3-maxzMiniMax H3 Max (fal post-train)z~5-30szffal's post-trained MiniMax H3. Top-ranked quality/prompt adherence/aesthetics, 768p in seconds, 5-15s.zminimax/h3-max/text-to-videozminimax/h3-max/image-to-video)r2   r'   Úprompt_expansion_modeÚbalanced)	r;   rJ   r   r   r<   r   Ústatic_payloadrL   r   zminimax-h3-max-turboz%MiniMax H3 Max Turbo (fal post-train)z~5-20sznfal's throughput-tuned H3 Max variant. Near-Max quality at a fraction of the price/latency, 480P-1080P, 5-15s.z"minimax/h3-max-turbo/text-to-videoz#minimax/h3-max-turbo/image-to-video)r2   r'   r3   zflux-3zFLUX 3 (via FAL)zGBlack Forest Labs frontier video. Native audio, 5-20s, 8 aspect ratios.z$blackforestlabs/flux-3/text-to-videoz%blackforestlabs/flux-3/image-to-video)r!   z2:1r"   r#   r$   r%   r&   )r,   r.   )rK   r7   )r;   r   r   r   r   zgrok-imagine-1.5zGrok Imagine 1.5 (via FAL)z=xAI. Fast stylized video with audio, 1-15s, cheap per second.z)xai/grok-imagine-video/v1.5/text-to-videoz*xai/grok-imagine-video/v1.5/image-to-video)r"   r#   z3:2r$   z2:3r%   r&   )r;   rJ   r   r   r   rL   zgemini-omni-flashzGemini Omni Flash 1.1 (via FAL)zZGoogle. Text & image to video with native audio, physics-grounded motion, up to 4K, 3-10s.z+google/gemini-omni-flash/v1.1/text-to-videoz,google/gemini-omni-flash/v1.1/image-to-video)r@   r,   r.   r0   )é   r:   )r;   r   r   r   rL   zkling-v3zKling 3.0 (Standard)zDKuaishou frontier core model. Cinematic motion, native audio, 3-15s.z,fal-ai/kling-video/v3/standard/text-to-videoz-fal-ai/kling-video/v3/standard/image-to-videoÚstart_image_url©r"   r&   r$   )rP   rB   )Úimage_param_keyrJ   r   r   r   r   zkling-v3-prozKling 3.0 ProzBKling 3.0 top quality tier. Cinematic motion, native audio, 3-15s.z'fal-ai/kling-video/v3/pro/text-to-videoz(fal-ai/kling-video/v3/pro/image-to-videozkling-v3-4kzKling v3 4Kz	~120-300sz14K output, native audio (Chinese/English), 3-15s.z&fal-ai/kling-video/v3/4k/text-to-videoz'fal-ai/kling-video/v3/4k/image-to-video)rS   r   r   r   r   r   zkling-o3zKling O3 (Standard)zIKuaishou frontier. Multi-shot native storytelling, optional audio, 3-15s.z,fal-ai/kling-video/o3/standard/text-to-videoz-fal-ai/kling-video/o3/standard/image-to-video)rJ   r   r   r   zWan 3.0zEAlibaba latest gen. 2-30s clips, native audio, up to 1080p, lip-sync.zalibaba/wan-3.0/text-to-videozalibaba/wan-3.0/image-to-videor   )r"   r#   r$   r%   r&   )r9   rI   )rS   r;   Úaudio_param_keyr   r   r   r   r   zWan 3.0 PrimezMAlibaba premium tier. Faster iteration, higher fidelity, 2-30s, native audio.z#alibaba/wan-3.0-prime/text-to-videoz$alibaba/wan-3.0-prime/image-to-videozHappy Horse 1.1zYAlibaba flagship. 1080p, native audio + multilingual lip-sync, 3-15s, nine aspect ratios.z&alibaba/happy-horse/v1.1/text-to-videoz'alibaba/happy-horse/v1.1/image-to-video)	r"   r&   r$   r#   r%   r!   z9:21z5:4z4:5)r;   rJ   r   r   r   rL   r   )zwan-3.0zwan-3.0-primezhappy-horsezDict[str, Dict[str, Any]]ÚFAL_FAMILIESc                óö   ‡— ‰€y| j                  d«      }|rt        |ˆfd„¬«      }n| d   \  }}t        |t        |‰«      «      }| j                  d«      xs i j                  |«      }|€|S t        ||«      S )a/  Snap to the nearest ``duration_enum`` entry when the family declares one, else clamp into the ``durations``
    ``(min, max)`` range; None stays None (endpoint default). A ``duration_cap_by_resolution`` ceiling for the resolved
    *resolution* is applied last (fal rejects LTX 2.5 >10s at 1440p/2160p).Nr=   c                ó    •— t        | ‰z
  «      S ©N)Úabs)ÚdÚdurations    €r   ú<lambda>z!_clamp_duration.<locals>.<lambda>…   s   ø€ ¬#¨a°(©lÓ*;€ r    )Úkeyr   r>   )ÚgetÚminÚmax)Úfamilyr[   Ú
resolutionÚenumÚclampedÚloÚhiÚcaps    `      r   Ú_clamp_durationrh   }   s‚   ø€ ð ÐØØ�:‰:�oÓ&€DÙÜ�dÓ ;Ô<‰à˜Ñ$‰ˆˆBÜ�bœ#˜b (Ó+Ó,ˆØ�:‰:Ð2Ó3Ò9°r×
>Ñ
>¸zÓ
J€CØ�kˆ7Ð8¤s¨7°CÓ'8Ð8r    c                ó>   — dD �cg c]  }| |› d�   sŒ|‘Œ c}S c c}w )N)r   r   Ú	_endpointr   )ÚmetaÚms     r   Ú_modalitiesrm   �   s#   € Ø(ÖB�!¨D°A°3°i°Ó,AŠAÒBÐBùÒBs   …“c           
     ó,  ‡ — ‰ j                  «       Š ‰ r‰ t        v r‰ xs dS t        j                  «       D ���cg c](  \  }}|d   |d   fD ]  }t        |t        «      r||f‘Œ Œ* }}}}|D ��cg c]  \  }}‰ |k(  sŒ|‘Œ c}}xsr |D ��cg c]C  \  }}|j                  ‰ dz   «      sŒ|t        ‰ «      dz   d j                  dd«      d   dv sŒB|‘ŒE c}}xs t        ˆ fd„t        D «       t        d	¬
«      }|r|d   S dS c c}}}w c c}}w c c}}w )znKnown family ID from a bare id, full endpoint path, truncated stem (``minimax/h3``) or provider-prefixed name.Nr   r   ú/rA   r   )ztext-to-videozimage-to-videoc              3  óJ   •K  — | ]  }|‰j                  d «      v sŒ|–— Œ y­w)ro   N)Úsplit)Ú.0ÚfidÚcs     €r   ú	<genexpr>z(_normalize_family_key.<locals>.<genexpr>�   s    øè ø€ ÒI˜c°S¸A¿G¹GÀC»LÒ5H”cÑIùs   ƒ#œ#T)r]   Úreverse)	ÚstriprU   ÚitemsÚ
isinstanceÚstrÚ
startswithÚlenrq   Úsorted)rt   rs   rk   ÚepÚ	endpointsÚhits   `     r   Ú_normalize_family_keyr�   ‘   sE  ø€ à	�‰‹	€AÙ�”\Ñ!ØŠy�DÐÜ,8×,>Ñ,>Ó,@÷ cð c™y˜s DØ  Ñ1°4Ð8HÑ3IÐJòcØÌjÐY[Ô]`ÔNað �r’ð c�ð c€Iò cð
  )×4‘G�C˜¨A°«GŠCÓ4ò bØ"+÷  S‘w�s˜B¨r¯}©}¸QÀ¹WÕ/EÈ"ÌSÐQRËVÐVWÉZÈ[È/×J_ÑJ_Ð`cÐefÓJgÐhiÑJjð  oRò  KRŠsó  SòbäÓI¤\ÔIÌsÐ\`Ôað ñ ˆ3ˆq‰6Ð"˜dÐ"ùôcùó
 5ùó Ss#   º-DÁ0D
Á>D
ÂDÂ*&DÃDc                óX  — ddl }	 ddlm}  |«       }t        |t        «      r|j                  d«      nd}t        |t        «      r|ni }t        |j                  d«      t        «      r|j                  d«      ni }| |j                  j                  d«      |j                  d«      |j                  d«      fD ].  }t        |t        «      rt        |«      nd}|sŒ#|t        |   fc S  t        t        t           fS # t        $ r#}t        j                  d|«       d}Y d}~�Œd}~ww xY w)	z>Decide which FAL family to use. Returns ``(family_id, meta)``.r   N)Úload_configz#Could not load video_gen config: %sÚ	video_genÚfalÚFAL_VIDEO_MODELÚmodel)ÚosÚhermes_cli.configrƒ   Ú	ExceptionÚloggerÚdebugry   Údictr^   Úenvironrz   r�   rU   ÚDEFAULT_MODEL)Úexplicitrˆ   rƒ   ÚcfgÚexcÚfal_cfgrt   rs   s           r   Ú_resolve_familyr”   ¡   sü   € ãðÝ1Ù‹mˆô #-¨S´$Ô"7ˆ#�'‰'�+Ô
¸T€CÜ˜C¤Ô&‰#¨B€CÜ *¨3¯7©7°5«>¼4Ô @ˆc�g‰g�eŒnÀb€GØ˜Ÿ
™
Ÿ™Ð'8Ó9¸7¿;¹;ÀwÓ;OÐQT×QXÑQXÐY`ÓQaÐbò *ˆÜ*4°Q¼Ô*<Ô# AÔ&À$ˆÚØœ SÑ)Ð)Ò)ð*ô œ,¤}Ñ5Ð5Ð5øô ò Ü�‰Ð:¸CÔ@ØŽûðús   †C= Ã=	D)ÄD$Ä$D)c               ó  — | j                  d«      xs i j                  |xs dj                  «       |«      }	| d   rt        | ||	«      nd}
|d|f|| j                  d«      xs d|f|duxr | j                  dd	«      d|f| d
   xr || d
   v d|f| d   xr |	| d   v d|	f|
dud| j                  d«      r|
n|
› | j                  dd«      › �f| d   xr |du| j                  d«      xs dt        |«      f| d   xr |d|ffD ���ci c]  \  }}}|r||“Œ }}}}|r| j                  dd«      ndD ]  }|j	                  |d«       Œ | j                  d«      xs i j                  «       D ]  \  }}|j                  ||«       Œ |S c c}}}w )us   Build a family-specific payload, dropping keys the family doesn't declare (unsupported enums â†’ endpoint default).r<   Ú r   NÚpromptrS   Ú	image_urlr   Tr   rH   r   rb   r[   r;   rG   r   rT   Úgenerate_audior   Únegative_promptrJ   r   rO   )r^   Úlowerrh   ÚboolÚpoprx   Ú
setdefault)ra   r—   r˜   r[   rH   rb   rš   r   r   Úresolvedrd   Úokr]   ÚvalueÚpayloads                  r   Ú_build_payloadr£   ´   s  € ð —
‘
Ð/Ó0Ò6°B×;Ñ;¸ZÒ=MÈ2×<TÑ<TÓ<VÐXbÓc€HØ=CÀKÒ=PŒo˜f h°Ô9ÐVZ€Gà	�˜6Ð"Ø	�F—J‘JÐ0Ó1Ò@°[À)ÐLà	�TÐ	Ò	6˜fŸj™j¨°Ó6¸ÀÐEØ	�Ñ	 Ò	L \°V¸OÑ5LÐ%LÈnÐ^jÐkØ	�Ñ	Ò	D 8¨v°mÑ/DÐ#DÀlÐT\Ð]à	˜Ð	˜j°V·Z±ZÀÔ5O©'ÐX_ÐW`Ðag×akÑakÐl}ð  @Bó  bCð  aDð  VEð  	FØ	�‰Ò	.˜U¨$Ð.°·
±
Ð;LÓ0MÒ0aÐQaÔcgÐhmÓcnÐoØ	�
Ñ	Ò	/ Ð1BÀOÐTðA÷ ð ©n¨b°#°uñ 
ð  # E™zð €Gò ñ 5>ˆv�z‰zÐ+¨RÔ0À2ò ˆØ�‰�C˜Õðà—z‘zÐ"2Ó3Ò9°r×@Ñ@ÓBò '‰
ˆˆUØ×Ñ˜3 Õ&ð'à€Nùô!s   ÄFc                óÂ   — t        | t        «      r| j                  d«      nd}t        |t        «      r|j                  d«      nt        |t        «      r|nd}||xs dfS )zJReturn ``(video_field, url)`` from a FAL result dict (url None if absent).ÚvideoNÚurl)ry   r�   r^   rz   )Úresultr¥   r¦   s      r   Ú_video_url_from_resultr¨   Ì   sP   € ä#-¨f´dÔ#;ˆF�J‰J�wÔÀ€EÜ(¨´Ô5ˆ%�)‰)�EÔ
ÄJÈuÔVYÔDZ¹5Ð`d€CØ�#’+˜ÐÐr    Ú_fal_clientÚ_managed_fal_video_clientÚ _managed_fal_video_client_configc                 ól   — t         5  t        €ddlm}   | «       at        cddd«       S # 1 sw Y   yxY w)z7Lazy-load ``fal_client`` once via ``tools.fal_common``.Nr   ©Úimport_fal_client)Ú_fal_client_lockr©   Útools.fal_commonr®   r­   s    r   Ú_load_fal_clientr±   Û   s0   € ô 
ñ ÜÐÝ:Ù+Ó-ˆKÜ÷	÷ ò ús   ‡*ª3c                 óÚ   — ddl m}  ddlm}m}m}m}  |d«      }||k(  r | d«      }|€t         |d|d«      «      ‚|S |� |«       st         |d|d«      «      ‚y |«       rdS  | d«      S )	uñ   Resolve the FAL video route from the stored ``video_gen`` selection: ``"nous"`` â†’ managed only (unentitled â‡’
    selection-naming error); other stored provider â†’ direct only (missing FAL_KEY â‡’ error); never-configured â†’ autodetect.r   )Úresolve_managed_tool_gateway)ÚNOUS_MANAGED_PROVIDERÚfal_key_is_configuredÚread_selectionÚselection_errorr„   z	fal-queueNzDthe Nous Tool Gateway is not available (not entitled or unreachable)zFAL_KEY is not set)Útools.managed_tool_gatewayr³   Útools.tool_backend_helpersr´   rµ   r¶   r·   Ú
ValueError)r³   r´   rµ   r¶   r·   ÚselectedÚgateways          r   Ú"_resolve_managed_fal_video_gatewayr½   å   s’   € õ HßxÓxÙ˜kÓ*€HØÐ(Ò(Ù.¨{Ó;ˆØˆ?Ü™_¨[Ð:Oð  RXó  Yó  Zð  ZØˆØÐÙ$Ô&Ü™_¨[¸(ÐDXÓYÓZÐZØÙ(Ô*ˆ4ÐYÑ0LÈ[Ó0YÐYr    c                 ó8   — ddl m}  t        «       duxs  | «       S )zsTrue if the selected (or, never-configured, any) FAL backend is reachable; raises on a stored-but-broken selection.r   ©rµ   N)r¹   rµ   r½   r¿   s    r   Ú_fal_video_availablerÀ   ÷   s   € å@Ü-Ó/°tÐ;ÒVÑ?TÓ?VÐVr    c                ó  — ddl m} | j                  j                  d«      | j                  f}t
        5  t        �	t        |k7  r) |t        «       | j                  | j                  ¬«      a|at        cddd«       S # 1 sw Y   yxY w)zQReuse the managed FAL client so its internal httpx.Client is not leaked per call.r   )Ú_ManagedFalSyncClientro   N)r]   Úqueue_run_origin)	r°   rÂ   Úgateway_originÚrstripÚnous_user_tokenÚ_managed_fal_video_client_lockrª   r«   r±   )Úmanaged_gatewayrÂ   Úclient_configs      r   Ú_get_managed_fal_video_clientrÊ   ý   s|   € õ 7Ø$×3Ñ3×:Ñ:¸3Ó?À×A`ÑA`Ða€MÜ	'ñ )Ü$Ð,Ô0PÐTaÒ0aÙ(=Ô>NÓ>PÐVe×VuÑVuØO^×OmÑOmô)oÐ%à/<Ð,Ü(÷)÷ )ò )ús   ´>A<Á<Bc           	     óŠ  ‡ ‡‡
— t        «       }dt        t        j                  «       «      i}t	        «       Š
‰
€|j                  ‰ ‰|¬«      S ddlm}m}m	} 	  |ˆˆ ˆ
fd„d‰ ¬«      S # t        $ rQ} ||«      }|�Ad	|cxk  rd
k  r6n ‚  ||d«      }	|	�t        d‰ › d|› d|	› �«      |‚t        d‰ › d|› d�«      |‚‚ d}~ww xY w)zNSubmit via direct credentials or the managed queue gateway; ``.get()`` blocks.zx-idempotency-keyN©Ú	argumentsÚheadersr   )Ú_extract_http_statusÚ_managed_fal_billing_errorÚ(submit_managed_fal_with_rate_limit_retryc                ó>   •— t        ‰«      j                  ‰‰| ¬«      S )NrÌ   )rÊ   Úsubmit)Úrequest_headersrÍ   ÚendpointrÈ   s    €€€r   r\   z+_submit_fal_video_request.<locals>.<lambda>  s&   ø€ Ô$AÀ/Ó$R×$YÑ$YØ I°ð %Zó %H€ r    zvideo endpoint)ÚwhatÚnamei�  iô  rÕ   z-Nous Subscription gateway rejected endpoint 'z' (HTTP z): uÓ   ). This model may not yet be enabled on the Nous Portal's FAL proxy. Either:
  â€¢ Set FAL_KEY in your environment to use FAL.ai directly, or
  â€¢ Pick a different model via `hermes tools` â†’ Video Generation.)r±   rz   ÚuuidÚuuid4r½   rÓ   r°   rÏ   rÐ   rÑ   rŠ   rº   )rÕ   rÍ   ÚclientrÎ   rÏ   rÐ   rÑ   r’   ÚstatusÚbillingrÈ   s   ``        @r   Ú_submit_fal_video_requestrÝ   
  s  ú€ äÓ€FØ"¤C¬¯
©
«Ó$5Ð6€GÜ8Ó:€OØÐØ�}‰}˜X°ÀGˆ}ÓLÐL÷ñ ðÙ7õHà!¨ô2ð 	2øô ò 
Ù% cÓ*ˆØÐ #¨Ô"5°#Ô"5ð 	ñ 1°°jÓAˆGØÐ"Ü ØCÀHÀ:ÈXÐV\ÐU]Ð]`ÐahÐ`iÐjólØqtðuäÐLÈXÈJÐV^Ð_eÐ^fð geð fó gàloðpð 	ûð
ús   ÁA( Á(	CÁ1AB=Â=Czfal-ai/seedvr/upscale/videoc                óf  — 	 t         j                  dt        «       | dt        dœ}t        «       �|st	        d«      ‚||d<   t        t        |«      j                  «       }t        |«      \  }}|st         j                  d«       |S # t        $ r }t         j                  d|«       Y d}~yd}~ww xY w)	zHBest-effort SeedVR2 upscale; returns the new URL or None (never raises).z%Upscaling video with SeedVR2 (%dx)...Úfactor)Ú	video_urlÚupscale_modeÚupscale_factorNz9Managed SeedVR upscale requires the source FAL request idÚsource_request_idzVideo upscale failed: %szVideo upscaler returned no URL)r‹   ÚinfoÚUPSCALER_FACTORr½   ÚRuntimeErrorrÝ   ÚUPSCALER_ENDPOINTr^   rŠ   Úwarningr¨   )rà   rã   rÍ   r§   r’   Ú_videor¦   s          r   Ú_upscale_videorê   +  s¥   € ð
Ü�‰Ð;¼_ÔMØ2;ÈXÔixÑ$yˆ	Ü-Ó/Ð;Ù$Ü"Ð#^Ó_Ð_Ø->ˆIÐ)Ñ*Ü*Ô+<¸iÓH×LÑLÓNˆô )¨Ó0�K€FˆCÙÜ�‰Ð7Ô8Ø€Jøô ò Ü�‰Ð1°3Ô7Üûðús   ‚AB Â	B0ÂB+Â+B0u«   No FAL backend available. Either set FAL_KEY (run `hermes tools` â†’ Video Generation â†’ FAL to configure) or sign in to Nous (`hermes setup`) for managed gateway access.uƒ   FAL family {fid} has no image-to-video endpoint. Pick a family with image-to-video support via `hermes tools` â†’ Video Generation.z�FAL family {fid} has no text-to-video endpoint. Pass an image_url to use its image-to-video endpoint, or pick a different family.)r   r   c                ó$   — t        | |d|||¬«      S )Nr…   )ÚerrorÚ
error_typeÚproviderr‡   r—   rH   )r
   )rì   rí   r—   r‡   rH   s        r   Ú
_fal_errorrï   F  s$   € Ü °*ÀuÐTYÐbhð  xDô  Eð  Er    c                  ó’   — e Zd ZdZdZdZdd„Zdd„Zdd„Zdd„Z	dd„Z
d	d	d	d	d
dd	d	d	d	dœ
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zy	)ÚFALVideoGenProviderzFFAL.ai multi-family backend; routes t2v/i2v on ``image_url`` presence.r…   ÚFALc                ó6   — 	 t        «       S # t        $ r Y yw xY w)NF)rÀ   rŠ   ©Úselfs    r   Úis_availablez FALVideoGenProvider.is_availableP  s"   € ð	Ü'Ó)Ð)øÜò 	Ùð	ús   ‚	 Œ	—c                óò   — t         j                  «       D ���cg c]J  \  }}d|idD �ci c]  }|||   “Œ
 c}¥dt        |«      i¥|d   x}rt        |«      t	        |«      dœni ¥‘ŒL c}}}S c c}w c c}}}w )NÚid)r   r   r   r   r   Ú
modalitiesr   )Úmin_durationÚmax_duration)rU   rx   rm   r_   r`   )rõ   rs   rk   ÚkrZ   s        r   Úlist_modelszFALVideoGenProvider.list_modelsW  s¤   € ô ".×!3Ñ!3Ó!5÷7ð 7á�C˜ð �sð kÐ3eÖf¨a˜q $ q¡'™zÒfð kÐhtô  wBð  CGó  wHñ kØNRÐS^ÑN_ÐI_ÈÐI_¤S¨£V¼SÀ»VÒDÐfhòkô 7ð 	7ùÒfùô 7s   ™A2¨A-µ3A2Á-A2c                ó   — t         S rX   )r�   rô   s    r   Údefault_modelz!FALVideoGenProvider.default_model\  s   € ÜÐr    c                ó   — ddddddœgddœS )	Nrò   ÚpaidÚFAL_KEYzFAL.ai API keyzhttps://fal.ai/dashboard/keys)r]   r—   r¦   u®   LTX 2.3/2.5, Pixverse, Seedance 2.0/2.5/Mini, Veo 3.1, MiniMax H3, FLUX 3, Kling 3.0/4K/O3, Wan 3.0, Happy Horse, Grok Imagine, Gemini Omni â€” text-to-video & image-to-video)r×   ÚbadgeÚenv_varsÚtagr   rô   s    r   Úget_setup_schemaz$FALVideoGenProvider.get_setup_schema_  s1   € Ø¨ÀYÐZjð  tSñ  >Tð  =UðHñIð 	Ir    c                ó’  — 	 t        d «      \  }}|r“|d   xs d}t        |«      xs dgt        |d   xs g «      t        |d   xs g «      t	        |«      t        |«      t        |d   «      t        |j                  d«      «      t        |d   «      t        |d	   «      d
ddœS t        j                  «       D �cg c]  }|d   sŒ	|d   ‘Œ }}ddgg d¢g d¢t	        dg|D �cg c]  }t	        |«      ‘Œ c}z   «      t        |D �cg c]  }t        |«      ‘Œ c}d¬«      d
d
d
d
ddœ
S # t        $ r d }Y �Œ&w xY wc c}w c c}w c c}w )Nr   )rA   rA   r   r   r   r   rL   r   r   Tr   )rù   r   r   rû   rú   Úsupports_audioÚaudio_always_onÚsupports_negative_promptÚsupports_seedÚsupports_upscaleÚmax_reference_imagesr   rR   r?   rA   )Údefault)
rù   r   r   rû   rú   r  r
  r  r  r  )
r”   rŠ   rm   Úlistr`   r_   rœ   r^   rU   Úvalues)rõ   Ú
_family_idra   r   rl   ÚspansrZ   s          r   Úcapabilitiesz FALVideoGenProvider.capabilitiesd  s~  € ð	ä!0°Ó!6ÑˆJ˜ñ Ø˜{Ñ+Ò5¨vˆIÜ"-¨fÓ"5Ò"A¸&¸ÔTXÐY_Ð`oÑYpÒYvÐtvÓTwÜ#'¨¨}Ñ(=Ò(CÀÓ#DÔVYÐZcÓVdÔvyð  {Dó  wEÜ&*¨6°'©?Ó&;ÔPTÐU[×U_ÑU_Ð`nÓUoÓPpÜ04°V¸JÑ5GÓ0HÔ[_Ð`fÐgmÑ`nÓ[oØ(,Àañ	Ið Iô
 *6×)<Ñ)<Ó)>ÖQ AÀ!ÀKÃ.��;“ÐQˆÐQØ% wÐ/ÒBYò  kLÜ # Q C¸5Ö*A°a¬3¨q­6Ò*AÑ$AÓ BÔTWÐinÖXoÐdeÔY\Ð]^ÕY_ÒXoÐyzÔT{Ø"&ÀDÐ[_Ðuyð  TUñVð 	Vøô ò 	Ø‹Fð	üò Rùâ*AùÒXos)   ‚D( Â;
D:ÃD:Ã#D?ÄEÄ(D7Ä6D7Nr"   r,   )
r‡   r˜   Úreference_image_urlsr[   rH   rb   rš   r   r   Úupscalec       
        óø  — 	 t        «       st        t        d|«      S 	 	 t        «        |xs dj                  «       }t        |«      \  }}|xs dj                  «       xs d }|rdnd}||› d�   }|s&t        t        |   j                  |¬«      d	||¬
«      S |st        dd||¬
«      S t        ||||||||	|
¬«	      }	 t        ||«      }t        |dd «      }t        |j                  «       «      \  }}|st        dd||¬
«      S |rt'        ||«      nd }t)        |«      }|r|st"        j%                  d«       |xs |}||dœ|rdt*        ini ¥}t-        |t.        «      r9|j1                  |rdndD �ci c]  }|j                  |«      sŒ|||   “Œ c}«       t3        ||||d|d|v r|ndd|v r6t5        dj7                  d„ t	        |d   «      D «       «      xs d «      ¬"«      S d!¬"«      S # t        $ r }t        t	        |«      d|«      cY d }~S d }~ww xY w# t        $ r t        dd|«      cY S w xY w# t         $ r7}t"        j%                  d|||d¬«       t        d|› �d|||¬«      cY d }~S d }~ww xY wc c}w )#NÚauth_requiredz@fal_client Python package not installed (pip install fal-client)Úmissing_dependencyr–   r   r   rj   )rs   Úmodality_unsupported)r‡   zprompt is required.Úmissing_prompt)r—   r˜   r[   rH   rb   rš   r   r   Ú
request_idz1FAL video gen failed (family=%s, endpoint=%s): %sT)Úexc_infozFAL video generation failed: Ú	api_error)r‡   rH   z%FAL returned no video URL in responseÚempty_responseu?   Video upscale pass failed â€” returning native-resolution video)rÕ   Úupscaledrâ   )Úcontent_type)Ú	file_sizer   r…   rH   r[   c              3  óB   K  — | ]  }|j                  «       sŒ|–— Œ y ­wrX   )Úisdigit)rr   rt   s     r   ru   z/FALVideoGenProvider.generate.<locals>.<genexpr>¥  s   è ø€ Ò T qÈÏ	É	Í¤Ñ Tùs   ‚˜Ú0r   )r¥   r‡   r—   Úmodalityrî   ÚextrarH   r[   )rÀ   rï   Ú_NO_BACKEND_MSGrº   rz   r±   ÚImportErrorrw   r”   Ú_MODALITY_MISSING_MSGÚformatr£   rÝ   Úgetattrr¨   r^   rŠ   r‹   rè   rê   rœ   rå   ry   r�   Úupdater   ÚintÚjoin)rõ   r—   r‡   r˜   r  r[   rH   rb   rš   r   r   r  Úkwargsr’   Ú	family_idra   Úimage_url_normÚmodality_usedrÕ   r¢   Úhandlerã   r¥   r¦   Úupscaled_urlr  r&  rü   s                               r   ÚgeneratezFALVideoGenProvider.generatew  sú  € ð
	AÜ'Ô)Ü!¤/°?ÀFÓKÐKð *ð	@ÜÔð ’,˜B×%Ñ%Ó'ˆÜ+¨EÓ2Ñˆ	�6Ø#š/ r×0Ñ0Ó2Ò:°dˆÙ#1™°vˆØ˜]˜O¨9Ð5Ñ6ˆÙÜÔ3°MÑB×IÑIÈiÐIÓXÐZpÐrxð  AJô  Kð  KÙÜÐ3Ð5EÀvÐU^Ô_Ð_Ü  °À.Ð[cÐr~Ø,6ÈÐ_dÐkoôqˆð	FÜ.¨x¸ÓAˆFÜ '¨°¸dÓ CÐÜ/°·
±
³Ó=‰JˆE�3ñ ÜÐEÐGWÐY_ÐgpÔqÐqáAH”~ cÐ+<Ô=ÈdˆÜ˜Ó%ˆÙ™8Ü�N‰NÐ\Ô]ØÒ!˜cˆØ-5À8ñ  !JÑwÐQaÔcrÑPsð  FHð  !JˆÜ�eœTÔ"Ø�L‰LÁXÑ0AÐSpö  C¨!Ðuz×u~Ñu~ð  @Aõ  vB˜!˜U 1™X™+ò  Cô  DÜØ˜Y¨vÀÐX]ÐejØ)7¸7Ñ)B™ÈØ`jÐnuÑ`u”S˜Ÿ™Ñ T¬C°¸
Ñ0CÓ,DÔ TÓTÒ[ÐX[Ó\ô
ð 	
ð |}ô
ð 	
øôG ò 	AÜœc #›h¨¸Ó@Õ@ûð	Aûô ò 	@ÜÐ`ÐbvÐx~ÓÒð	@ûô" ò 	FÜ�N‰NÐNÐPYÐ[cÐehÐswˆNÔxÜÐ =¸c¸UÐCÀ[ÐRXÐ`ið  yEô  Fõ  Fûð	Füò CsX   ‚G, Ÿ
H Â?5H4 Å3I7Æ
I7Ç,	HÇ5HÈ
HÈHÈH1È0H1È4	I4È=,I/É)I4É/I4©Úreturnrœ   )r7  zList[Dict[str, Any]])r7  úOptional[str])r7  úDict[str, Any])r—   rz   r‡   r8  r˜   r8  r  zOptional[List[str]]r[   úOptional[int]rH   rz   rb   rz   rš   r8  r   úOptional[bool]r   r:  r  r;  r/  r   r7  r9  )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r×   Údisplay_namerö   rý   rÿ   r  r  r5  r   r    r   rñ   rñ   J  sÏ   „ ÙPà€DØ€Lóó7ó
óIó
Vð( 6:ÐVZð  IMØ"&¸FÐV\ð  @DØ $¸DÐ\`ñ/
Øð/
Ø%2ð/
ØFSð/
ð sFð/
àð/
à69ð/
àPSð/
ào|ð/
ð ð/
ð -:ð/
ð LZð/
ð mpð/
ð 
ô	/
r    rñ   c                ó6   — | j                  t        «       «       y)uF   Plugin entry point â€” wire ``FALVideoGenProvider`` into the registry.N)Úregister_video_gen_providerrñ   )Úctxs    r   ÚregisterrD  ©  s   € à×#Ñ#Ô$7Ó$9Õ:r    )r   rz   r   rz   r   rz   r   rz   r   r8  r   rz   r   r   r7  r9  rX   )ra   r9  r[   r:  rb   r8  r7  r:  )rk   r9  r7  z	List[str])rt   rz   r7  r8  )r�   r8  r7  zTuple[str, Dict[str, Any]])ra   r9  r—   rz   r˜   r8  r[   r:  rH   rz   rb   rz   rš   r8  r   r;  r   r:  r7  r9  )r§   r   r7  zTuple[Any, Optional[str]])r7  r   r6  )rÕ   rz   rÍ   r9  )rà   rz   rã   r8  r7  r8  )r–   r–   )rì   rz   rí   rz   r—   rz   r‡   rz   rH   rz   r7  r9  )r7  ÚNone)7r?  Ú
__future__r   ÚloggingÚ	threadingrØ   Útypingr   r   r   r   r   Úagent.video_gen_providerr	   r
   r   Ú	getLoggerr<  r‹   r   Ú_SIX_ASPECTSÚ_H3_ALIASESÚ_H3_MAX_ALIASESÚ_H3_MAX_TURBO_ALIASESÚtupleÚrangerU   Ú__annotations__r�   rh   rm   r�   r”   r£   r¨   r©   ÚLockr¯   rª   r«   rÇ   r±   r½   rÀ   rÊ   rÝ   rç   rå   rê   r'  r)  rï   rñ   rD  rˆ   r   r    r   ú<module>rT     sæ  ðòõ #ã Û Û ß 3Õ 3ç WÑ Wà	ˆ×	Ñ	˜8Ó	$€óEð
 =€à v°vÀvÐX\ÐdhÐptð  @Dñ  E€Ø!¨6¸6È6Ð\bÐjpÐx~ð  JPñ  Q€Ø!'°ÀÐQWÐbiÐqxð  AHð  SZñ  [Ð ðR+à‰w�¨	°7Ð<qØ9Ð;^ÐfjÐuyð  AEôFðR+ð
 ‰w�y )¨Wð  7]Ø>Ð@hÐw{ð  L\Ø#FÐbiÐqxÑ[yØ!(¹¹eÀAÀrÈ1»oÓ8NÐuwð  CEñ  lFð  NRôSðR+ð ‘7˜=¨)°WÐ>nð  qSØ>ÐLmð  zAð  IMð  X\ð  cgôhðR+ð ™Ð!4°iÀð  KNØ!LÐNzð  KWØ-=ÈÐX\ô^ðR+ð ‰g�i ¨YÐ8|ð  NØ4ÐDTÐbyð  FLð  \eØ&)°ÀÈ4ôQðR+ð$ ‘G˜N¨J¸	ð  DAØBÐDkð  |HØ(AÈWÐ\`ôbð%R+ð* ‘G˜N¨J¸	ð  D[ØBÐDkð  |HØ,=ÐK[ÐgnÐvzô|ð+R+ð0 ‘'˜,¨
°Ið  @EØ4Ð6QÐ`dð  wHØ(4ÐBVÐkvð  CJð  Y]ô^ð1R+ð8 ‘gÐ?ÀÈ9ð WNØOmð  pOØ+/ÐARÐbnð  }MØ1@ÈGÐe|ð  Ið  eJð  Y]ð  dhôið9R+ðD ™GÐ$KÈXÐW`ð ceð gKØ$IÐX\Ðnð  P\Ø0IÐ^sð  @GØ4KÈZÐ3XÐgkÐrvô	xðER+ðN ‰gÐ(¨*°ið  BKØ<Ð>eÐtxØ$XÐfwð  DKð  SWôXðOR+ðT ™Ð <¸iÈð  UTØ KÐMyð  IMØ0Að  REØ,EÐQXÐgkômðUR+ð^ ™Ð!BÀJÐPYð  \xØ!NÐP~ð  NRØ/?ÐMlÐxð  OSôTð_R+ðh ‘Ð.°
¸Ið  HNØFÐHwð  J[Ø(9ÐI`ÐlsÐ{ð  KOôPðiR+ðn ‘G˜O¨Z¸ð  EIØEÐGqð  DUØ,=ÐMdÐpwð  @Dð  OSôTðoR+ðt ‘7˜=¨+°yÐBuð  x`ØDÐVgð  xOØ%,°DÀ4ÈdôTðuR+ð~ ‘Ð-¨z¸9ð  GRØFÐHwØ(9ÐI`ÐlsÐ{ôAðR+ñH �y *¨ið  :AØ6Ð8XÐj{ð  KOØ'.Ð>cð  rKØ!(°¸4ôAñ ˜_¨j¸)ð  FUØBÐDjð  }NØ*.ÀÐW|Ø)BÈgÐ]aÐhlônñ Ð,¨j¸)ð  FaØCÐEnð  ~BØ+<ð  MPØ'8ÀGÐZ^Ðeiôkò]R+€Ð'ó Rðh €ô9ó Có#ó 6ð&Ø"ðØ5BðØKYðØanðð tBóó0ð €ˆSÓ Ø!�9—>‘>Ó#Ð à!%Ð ˜3Ó %Ø(,Ð   #Ó ,Ø!/ §¡Ó!1Ð óòZó$Wò
)óð: 2Ð Ø€ôð&U€ð Sð PñÐ ôEô\
Ð*ô \
ó~;ô 
r    