+
    iHàjm4  ã                  óÄ  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
HtHtHtHt ^ RIHt ^ RIHt ^ RIHt ]P*                  ! ]4      tR9tR	]R
&   RtR:tR	]R&   Rt ! R R]4      t]P<                   R2tRRRR/R R llt RRRR/R R llt!RRRRRRRR/t"RRRR R!R;R"RR#R$R%R$/R& R' llt#R(R)R*R+R,^ R-R/R. R/ llt$R0R1R2R+R3R+R4R+R*R+/R5 R6 llt% ! R7 R8]4      t&R# )<u  Video Generation Provider ABC.

Providers register via ``PluginContext.register_video_gen_provider()`` and live
in ``<repo>/plugins/video_gen/<name>/`` (built-in) or
``~/.hermes/plugins/video_gen/<name>/``; mirrors ``agent/image_gen_provider.py``.
One tool covers text-to-video and image-to-video: ``image_url`` present routes to
the provider's image-to-video endpoint. Video edit/extend are deliberately NOT
exposed â€” backends are too inconsistent for one unified tool.

Response shape (:func:`success_response` / :func:`error_response`): ``success``,
``video`` (URL or absolute path), ``model``, ``prompt``, ``modality``
("text" | "image"), ``aspect_ratio``, ``duration`` (seconds, 0 if n/a),
``provider``; plus ``error`` / ``error_type`` only when ``success`` is False.
)ÚannotationsN)ÚPath)ÚAnyÚDictÚListÚOptionalÚTuple)Úprovider_media)ÚCatalogProviderBase)Úget_secret_strú16:9ztuple[str, ...]ÚCOMMON_ASPECT_RATIOSÚ720pÚCOMMON_RESOLUTIONSc                  óx   € ] tR t^*tRtR R lt]P                  RRRRRRRRR	]R
]	RRRRRR/	R R ll4       t
RtR# )ÚVideoGenProviderzÜAbstract base class for a video generation backend: implement :attr:`name`
and :meth:`generate`. ``list_models`` entries are **model families** and may
add ``speed`` / ``strengths`` / ``price`` / advisory ``modalities``.c               ó   € V ^8„  d   QhRR/# )é   Úreturnúdict[str, Any]© )Úformats   "Ú=/home/ubuntu/.hermes/hermes-agent/agent/video_gen_provider.pyÚ__annotate__ÚVideoGenProvider.__annotate__/   s   € ÷ 	
ñ 	
˜nñ 	
ó    c                ód   € RR.R\        \        4      R\        \        4      R^
R^RRR	RR
RRRR^ /
# )zÐSupported features (keys below, all optional) used for soft validation,
capability-gated params in the dynamic ``video_generate`` schema, and the
picker. Default fails closed: text-only, no optional features.Ú
modalitiesÚtextÚaspect_ratiosÚresolutionsÚmax_durationÚmin_durationÚsupports_audioFÚsupports_negative_promptÚsupports_seedÚsupports_upscaleÚmax_reference_images)Úlistr   r   ©Úselfs   &r   ÚcapabilitiesÚVideoGenProvider.capabilities/   sL   € ð
 ˜6˜( O´TÔ:NÓ5OØœ4Ô 2Ó3°^ÀRÈÐYZØ˜eÐ%?ÀÈÐY^Ø Ð'=¸qð	
ð 	
r   ÚmodelNÚ	image_urlÚreference_image_urlsÚdurationÚaspect_ratioÚ
resolutionÚnegative_promptÚaudioÚseedc               óH   € V ^8„  d   QhRRRRRRRRRR	R
RRRRRRRRR	RRRR/# ©r   ÚpromptÚstrr-   zOptional[str]r.   r/   zOptional[list[str]]r0   zOptional[int]r1   r2   r3   r4   zOptional[bool]r5   Úkwargsr   r   r   r   )r   s   "r   r   r   ;   sŠ   € ÷ 
Qñ 
QØð
QØ%2ð
QØFSð
Qà1ð
QàDQð
Qð ð
Qð ?Bð
Qð 'ð	
Qð 7Eð	
Qð
 ð
Qð
 /2ð
Qð 
ñ
Qr   c       	        ó   € R# )a,  Generate a video from a prompt, or animate ``image_url`` when given; return
:func:`success_response` / :func:`error_response`. Unknown ``kwargs`` MUST be
ignored. Known optional kwarg ``upscale`` (bool): a post-generation high-res
pass; providers that honor it report ``upscaled: True`` in ``extra``.Nr   )r*   r8   r-   r.   r/   r0   r1   r2   r3   r4   r5   r:   s   &&$$$$$$$$$,r   ÚgenerateÚVideoGenProvider.generate:   s   ‚ r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r+   ÚabcÚabstractmethodÚDEFAULT_ASPECT_RATIOÚDEFAULT_RESOLUTIONr<   Ú__static_attributes__r   r   r   r   r   *   sˆ   † ñLõ	
ð 	×Ñð
QØ59ð
QØVZð
Qà48ð
QàTXð
Qð 1ð
Qð EWð
Qð *.ð	
Qð HLð	
Qð
 #ö
Qó ô
Qr   r   z/videosÚprefixÚvideoÚ	extensionÚmp4c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úb64_datar9   rH   rJ   r   r   r   )r   s   "r   r   r   K   s/   € ÷ hñ h˜Sð h¨Cð hÀCð hÐRVñ hr   c               ó<   € \         P                  ! \        WVR7      # )zXDecode base64 video data into ``$HERMES_HOME/cache/generated/videos/``; return the path.©rH   rJ   )r	   Úsave_b64Ú_GENERATED_VIDEO_KIND)rM   rH   rJ   s   &$$r   Úsave_b64_videorR   K   s   € ä×"Ò"Ô#8¸(Ð]fÔgÐgr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   ÚrawÚbytesrH   r9   rJ   r   r   r   )r   s   "r   r   r   P   s/   € ÷ eñ e˜%ð e¨3ð eÀ3ð eÐQUñ er   c               ó<   € \         P                  ! \        WVR7      # )z@Write raw video bytes (e.g. an HTTP download body) to the cache.rO   )r	   Ú
save_bytesrQ   )rT   rH   rJ   s   &$$r   Úsave_bytes_videorX   P   s   € ä×$Ò$Ô%:¸CÐZcÔdÐdr   z	video/mp4z
video/webmÚwebmzvideo/quicktimeÚmovzvideo/x-matroskaÚmkvÚtimeoutg     €f@Ú	max_bytesÚheadersÚrequire_video_content_typeFÚtrusted_originc               ó8   € V ^8„  d   QhRRRRRRRRRR	R
RRRRR/# )r   Úurlr9   rH   r\   Úfloatr]   Úintr^   zOptional[dict[str, str]]r_   Úboolr`   r   r   r   )r   s   "r   r   r   Z   sZ   € ÷ ñ Ø	ðð ðð ð	ð
 ðð &ðð !%ðð ðð 
ñr   c               óT   € \         P                  ! \        WW#R\        RRRRWEVR7      # )a0  Download an (often ephemeral) video URL into ``$HERMES_HOME/cache/generated/videos/``;
raises on network / HTTP / oversize / empty errors so callers can fall back to the URL.
``trusted_origin`` is only for URLs built from the operator's configured provider
``base_url`` (see ``provider_media.save_url``).rK   ÚVideoz#Video at {url} was empty (0 bytes).)rH   r\   r]   Ú
chunk_sizeÚcontent_typesÚurl_extensionsÚdefault_extensionÚlabelÚempty_errorr^   Úrequire_known_content_typer`   i   )rK   rY   rZ   r[   )r	   Úsave_urlrQ   Ú_URL_VIDEO_CONTENT_TYPES)rb   rH   r\   r]   r^   r_   r`   s   &$$$$$$r   Úsave_url_videorq   Z   s5   € ô ×"Ò"Ü˜s¸7ØÔ-EØ4ÈØÐ#HØØ%ôð r   Úmodalityr   r1   Ú r0   Úextrac               ó<   € V ^8„  d   QhRRRRRRRRRRRRR	RR
RRR/	# )r   rI   r9   r-   r8   rr   r1   r0   rd   Úproviderrt   zOptional[dict[str, Any]]r   r   r   )r   s   "r   r   r   r   sV   € ÷ ñ ØðØðØ'*ðØ69ðØRUðàðà!$ðà-Eðð ñr   c                ó¸   € RRRT RTRTRTRTRV'       d   \        V4      M^ R	V/pT;'       g    / P                  4        F  w  ršVP                  Wš4       K  	  V# )
zPUniform success dict; ``extra`` keys are added without overriding standard ones.ÚsuccessTrI   r-   r8   rr   r1   r0   rv   )rd   ÚitemsÚ
setdefault)rI   r-   r8   rr   r1   r0   rv   rt   ÚpayloadÚkÚvs   $$$$$$$$   r   Úsuccess_responser~   r   si   € ð 	�4˜ %¨°%¸À6È:ÐW_Ø˜ jÇ8´#°h´-ÐQRÐT^Ð`hð€Gð —�˜"×#Ñ#Ö%‰ˆØ×Ñ˜1Ö ñ &à€Nr   Ú
error_typeÚprovider_errorrv   r-   r8   c               ó4   € V ^8„  d   QhRRRRRRRRRRRRRR	/# )
r   Úerrorr9   r   rv   r-   r8   r1   r   r   r   )r   s   "r   r   r   €   sF   € ÷ ñ ØðØ"ðØADðØRUðàðà$'ðð ñr   c                ó&   € RRRRRV RVRVRVR	VR
V/# )z$Build a uniform error response dict.rx   FrI   Nr‚   r   r-   r8   r1   rv   r   ©r‚   r   rv   r-   r8   r1   s   $$$$$$r   Úerror_responser…   €   s2   € ð 	�5˜' 4¨°%¸ÀzÐSZÐ\aØ�&˜.¨,¸
ÀHðð r   c                  ó¸   € ] tR t^‹t$ RtRtR]R&   RtR]R&   RtR]R	&   R
t	R]R&   R R lt
R R ltR R ltR R ltRRRRRRRRR]R]RRRRRR/	R R lltR tR# )!Ú OpenAICompatibleVideoGenProvideruÀ  Generic text/image-to-video over the OpenAI ``client.videos`` API.

DeepInfra, OpenAI/Sora, and OpenRouter share the ``POST /videos`` async-job
shape (``create`` â†’ poll â†’ ``download_content``); a concrete backend sets
``name``, ``_env_key``, ``_default_base_url`` and ``list_models()`` (entries
with an ``id`` key; ``default_model()`` uses ``[0]``). Provider-specific
fields (``image_url``/``negative_prompt``/``seed``) ride in ``extra_body``.
ÚOPENAI_API_KEYr9   Ú_env_keyzhttps://api.openai.com/v1Ú_default_base_urlg      @rc   Ú_poll_interval_sg      Œ@Ú_poll_deadline_sc               ó   € V ^8„  d   QhRR/# ©r   r   r9   r   )r   s   "r   r   Ú-OpenAICompatibleVideoGenProvider.__annotate__ž   s   € ÷ 5ñ 5˜#ñ 5r   c                	óH   € \        V P                  4      P                  4       # ©N)r   r‰   Ústripr)   s   &r   Ú_api_keyÚ)OpenAICompatibleVideoGenProvider._api_keyž   s   € ä˜dŸm™mÓ,×2Ñ2Ó4Ð4r   c               ó   € V ^8„  d   QhRR/# )r   r   re   r   )r   s   "r   r   r�   ¢   s   € ÷ %ñ %˜dñ %r   c                	ó4   € \        V P                  4       4      # r‘   )re   r“   r)   s   &r   Úis_availableÚ-OpenAICompatibleVideoGenProvider.is_available¢   s   € Ü�D—M‘M“OÓ$Ð$r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úclientr   Úcall_kwargsr   r   r   )r   s   "r   r   r�   ¥   s!   € ÷ ñ  sð ¸ð ÈCñ r   c                óö  € VP                   P                  ! R	/ VB p0 R
mp\        P                  ! 4       V P                  ,           p\        VRR4      V9  d¡   \        P                  ! 4       V8¼  d@   \        R\        VRR4       R\        V P                  4       R\        VRR4      : R24      h\        P                  ! V P                  4       VP                   P                  VP                  4      pK²  V# )zwCreate the job and poll to a terminal status (any); raise
:class:`TimeoutError` when ``_poll_deadline_s`` passes first.ÚstatusNz
video job ÚidÚ?z( did not reach a terminal status within zs (last status=Ú)r   >   r‚   ÚfailedÚcanceledÚ	cancelledÚ	completedÚ	succeeded)ÚvideosÚcreateÚtimeÚ	monotonicrŒ   ÚgetattrÚTimeoutErrorrd   Úsleepr‹   Úretrieverž   )r*   rš   r›   rI   ÚterminalÚdeadlines   &&&   r   Ú_create_and_pollÚ1OpenAICompatibleVideoGenProvider._create_and_poll¥   sÙ   € ð —‘×$Ò$Ñ3 {Ñ3ˆÚYˆÜ—>’>Ó# d×&;Ñ&;Õ;ˆÜ�e˜X tÓ,°HÔ<Ü�~Š~Ó 8Ô+Ü"Ø ¤¨°°cÓ!:Ð ;ð <%Ü%(¨×)>Ñ)>Ó%?Ð$@ð A$Ü$+¨E°8¸TÓ$BÑ#EÀQðHóð ô
 �JŠJ�t×,Ñ,Ô-Ø—M‘M×*Ñ*¨5¯8©8Ó4ŠEØˆr   c               ó   € V ^8„  d   QhRR/# rŽ   r   )r   s   "r   r   r�   ¶   s   € ÷ añ a˜3ñ ar   c                	ó’   € \        V P                  P                  4        R 24      P                  4       ;'       g    V P                  # )Ú	_BASE_URL)r   ÚnameÚupperr’   rŠ   r)   s   &r   Ú	_base_urlÚ*OpenAICompatibleVideoGenProvider._base_url¶   s7   € Ü §¡§¡Ó!2Ð 3°9Ð=Ó>×DÑDÓF×`Ð`È$×J`ÑJ`Ð`r   r-   Nr.   r/   r0   r1   r2   r3   r4   r5   c               óH   € V ^8„  d   QhRRRRRRRRRR	R
RRRRRRRRR	RRRR/# r7   r   )r   s   "r   r   r�   ¹   sŠ   € ÷ hñ hØðhØ%2ðhØFSðhà1ðhàDQðhð ðhð ?Bðhð 'ð	hð 7Eð	hð
 ðhð
 /2ðhð 
ñhr   c       	   
     	ó0	  a aaa€ S'       d   SP                  4       '       g   \        R RS P                  R7      # S P                  4       '       g&   \        S P                   R2RS P                  R7      #  ^ RIpT;'       g    S P                  4       oS'       g'   \        RS P                   R	2R
S P                  R7      # R TTTT 3R llpRTRSRTRT
/P                  4        UUu/ uF  w  rïTf   K  YïbK  	  pppRSRS/pT'       d   \        T4      TR&   T'       d   TTR&   T'       d   TTR&   ^ RI
Hp RS P                  4       RS P                  4       /pT! TR,          4      pTe   TTR&   TP                  ! R-/ TB p  S P                  TT4      p\%        TR R4      pTR.9  dT   \%        TR!R4      pT! T'       d   \        T4      MR"T: 2R#4      \%        TRR4      p\'        T4      '       d	   T! 4        # # Rp\%        TR$R4      ;'       g    .  FK  p\)        T\*        4      '       d   TP-                  R%4      M\%        TR%R4      ;'       g    RpT'       g   KK   M	   T'       d"   \        \/        TS P                  R&7      4      pMTTP0                  P3                  TP4                  4      P7                  4       p\        \9        TS P                  R&7      4      p \;        TSST'       d   R*MR+ST;'       g    ^ S P                  R,7      \%        TRR4      p\'        T4      '       d	   T! 4        # #   \         d    \        RRS P                  R7      u # i ; iu uppi   \         dk   p\         P#                  RS P                  RR7       T! S P                   RT 2R4      u Rp?\%        TRR4      p\'        T4      '       d	   T! 4        # # Rp?ii ; i  \         dz   pT'       gD   T! S P                   R'T 2R(4      u Rp?\%        TRR4      p\'        T4      '       d	   T! 4        # # \         P#                  R)S P                  T4       Tp Rp?EL|Rp?ii ; i  \%        TRR4      p\'        T4      '       d	   T! 4        i i ; i)/zprompt is requiredÚinvalid_request)r‚   r   rv   z is not setÚmissing_credentialsNz:openai Python package not installed. Run: hermes pm repairÚmissing_dependencyzno z, video model available (live catalog empty?)Úno_modelc               ó$   € V ^8„  d   QhRRRRRR/# )r   r‚   r9   r   r   r   r   )r   s   "r   r   Ú?OpenAICompatibleVideoGenProvider.generate.<locals>.__annotate__Õ   s!   € ÷ 	ñ 	˜ð 	¨ð 	°ñ 	r   c           	     ó8   <€ \        WSP                  SSSR 7      # )r„   )r…   rµ   )r‚   r   r1   Úmodel_idr8   r*   s   &&€€€€r   ÚfailÚ7OpenAICompatibleVideoGenProvider.generate.<locals>.failÕ   s!   ø€ Ü!Ø¸T¿Y¹YÈhÐ_eØ)ôð r   r3   r1   r.   r5   r-   r8   ÚsecondsÚsizeÚ
extra_body)Úbuild_keepalive_http_clientÚapi_keyÚbase_urlÚhttp_clientz%s video generation failedT)Úexc_infoz video generation failed: Ú	api_errorÚcloser�   r‚   zvideo job ended with status=Ú
job_failedÚdatarb   )rH   z7 video job succeeded but no output could be retrieved: Úempty_responsez3%s: saving video locally failed (%s); returning URLÚimager   )rI   r-   r8   rr   r1   r0   rv   r   )r¤   r¥   )r’   r…   rµ   r“   r‰   ÚopenaiÚImportErrorÚdefault_modelry   r9   Úagent.process_bootstraprÈ   r·   ÚOpenAIr°   Ú	ExceptionÚloggerÚdebugrª   ÚcallableÚ
isinstanceÚdictÚgetrq   r¦   Údownload_contentrž   ÚreadrX   r~   ) r*   r8   r-   r.   r/   r0   r1   r2   r3   r4   r5   r:   rÓ   rÃ   r|   r}   rÇ   r›   rÈ   Úclient_kwargsrË   rš   rI   ÚexcrÎ   r�   Ú	job_errorrb   ÚitemÚ	video_refrT   rÂ   s    ff$$$$d$$$$,                   @r   r<   Ú)OpenAICompatibleVideoGenProvider.generate¹   sJ  û€ ÷ ˜VŸ\™\Ÿ^š^Ü!Ð(<ÐIZÐei×enÑenÔoÐoØ�}‰}�ŠÜ!ØŸ™˜ {Ð3Ð@UÐ`d×`iÑ`iôð ð	Ûð ×0Ð0˜D×.Ñ.Ó0ˆßÜ!Ø˜DŸI™I˜;Ð&RÐSØ%°·	±	ôð ÷
	ó 	ð " ?°NÀLØ˜YØ˜ð÷ ‰e‹gð	ô
ñ‘�ð
 ô ˆAŠDñð 	ñ 
ð (/°¸(ÀFÐ&KˆßÜ%(¨£]ˆK˜	Ñ"ßØ",ˆK˜ÑßØ(2ˆK˜Ñ%õ 	Hà)2°D·M±M³OÀZÐQU×Q_ÑQ_ÓQaÐ(bˆÙ1°-À
Õ2KÓLˆØÒ"Ø+6ˆM˜-Ñ(Ø—’Ñ/ Ñ/ˆð+	ðXØ×-Ñ-¨f°kÓB�ô ˜U H¨dÓ3ˆFØÐ7Ô7ä# E¨7°DÓ9�	Ù¯iœC 	œNÐ?[Ð\bÑ[eÐ=fÐhtÓuô: ˜F G¨TÓ2ˆEÜ˜�ŠÙ•ð ð3 ˆCÜ  v¨tÓ4×:Ð:¸Ò:�Ü*4°T¼4×*@Ò*@�t—x‘x ”ÄgÈdÐTYÐ[_ÓF`×iÐiÐei�ß‘3Ùñ ;ð

 ßÜ #¤N°3¸t¿y¹yÔ$IÓ J‘Ià Ÿ-™-×8Ñ8¸¿¹ÓB×GÑGÓI�CÜ #Ô$4°SÀÇÁÔ$KÓ L‘Iô $Ø x¸ß$-™°6ÈØ!Ÿ˜ Q°·±ôô ˜F G¨TÓ2ˆEÜ˜�ŠÙ•ð øôq ô 	Ü!ØRØ/¸$¿)¹)ôò ð	üó(
øô: ô XÜ—‘Ð9¸4¿9¹9Èt�ÔTÙ˜tŸy™y˜kÐ)CÀCÀ5ÐIÈ;ÓWÔWôH ˜F G¨TÓ2ˆEÜ˜�ŠÙ•ð ûðOXûô4 ô  ßÙ 4§9¡9 +Ð-dÐehÐdiÐ jÐl|Ó}Ô}ô ˜F G¨TÓ2ˆEÜ˜�ŠÙ•ð ô —‘ÐRÐTX×T]ÑT]Ð_bÔcØ–	ûð	 ûô ˜F G¨TÓ2ˆEÜ˜�ŠÙ•ð úsÃ   Á7L? Ã*M(Ã7M(Æ
M. ÆA Q- ÈQ- ÈA Q- ÉQ- É'Q- É,O& É4 O& ÊQ- ÊAO& Ë(Q- ÌQ- Ì?#M%Í$M%Í.O#Í99OÎ2O#Î3Q- ÏO#Ï#Q- Ï&Q*Ï1Q%ÐQ*ÐQ- Ð<#Q%ÑQ- Ñ%Q*Ñ*Q- Ñ-(Rr   )r>   r?   r@   rA   rB   r‰   Ú__annotations__rŠ   r‹   rŒ   r“   r—   r°   r·   rE   rF   r<   rG   r   r   r   r‡   r‡   ‹   s¶   ‡ ñð %€HˆcÓ$Ø8Ð�sÓ8ð
 "Ð�eÓ!Ø#Ð�eÓ#õ5õ%õõ"aðhØ59ðhØVZðhà48ðhàTXðhð 1ðhð EWðhð *.ð	hð HLð	hð
 #÷hó hr   r‡   )r   z9:16z1:1z4:3z3:4z3:2z2:3z21:9)Ú480pÚ540pr   Ú768pÚ1080pi  €)'Ú__conditional_annotations__rB   Ú
__future__r   rC   Úloggingr¨   Úpathlibr   Útypingr   r   r   r   r   Úagentr	   Úagent.provider_baser
   Úagent.secret_scoper   Ú	getLoggerr>   rÙ   r   rç   rE   r   rF   r   ÚGENERATED_SUBDIRrQ   rR   rX   rp   rq   r~   r…   r‡   )rì   s   @r   Ú<module>rö      st  øðôõ #ã 
Û Û Ý ß 3Õ 3å  Ý 3Ý -à	×	Ò	˜8Ó	$€ð
)Ð �oó ð Ð à&OÐ �OÓ OØÐ ôQÐ*ô Qð< *×:Ñ:Ð;¸7ÐCÐ ðh°ð hÈ÷ hð
e¨wð eÀu÷ eð �˜ fÐ.?ÀÐHZÐ\aðÐ ð
ð ðð ð	ð
 'ðð )-ðð (-ðð !÷ð0Ø<BðØXZðàðàHL÷ðØ%5ðØGIðØXZðàðà*,÷ôVÐ'7ö Vr   