§
    ÷žyj<V  ã                  ó`  — U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZmZmZmZ  ej        e¦  «        ZdZded<   d	Zd
Zded<   dZ G d„ dej        ¦  «        Zd>d„Zdddœd?d„Zdddœd@d„Zddddd œZdd!d"d#œdAd)„Zd*d+ddd,œdBd6„Zd7d+d+d+d+d8œdCd;„Z  G d<„ d=e¦  «        Z!dS )DuÞ  
Video Generation Provider ABC
=============================

Defines the pluggable-backend interface for video generation. Providers register
instances via ``PluginContext.register_video_gen_provider()``; the active one
(selected via ``video_gen.provider`` in ``config.yaml``) services every
``video_generate`` tool call.

Providers live in ``<repo>/plugins/video_gen/<name>/`` (built-in, auto-loaded
as ``kind: backend``) or ``~/.hermes/plugins/video_gen/<name>/`` (user, opt-in
via ``plugins.enabled``).

Mirrors the ``image_gen`` provider design (``agent/image_gen_provider.py``) so
the two surfaces stay learnable together.

Unified surface
---------------
One tool â€” ``video_generate`` â€” covers **text-to-video** and **image-to-video**.
The router is the presence of ``image_url``: if it's set, the provider routes
to its image-to-video endpoint; if it's omitted, the provider routes to
text-to-video. Users pick one **model family** (e.g. Pixverse v6, Veo 3.1,
Kling O3 Standard); the provider handles which underlying FAL/xAI endpoint
to hit.

Video edit and video extend are intentionally NOT exposed in this surface â€”
the inconsistency across backends is too large for one unified tool. If
those use cases warrant attention later they can ship as separate tools.

Response shape
--------------
All providers return a dict built by :func:`success_response` /
:func:`error_response`. Keys:

    success         bool
    video           str | None      URL or absolute file path
    model           str             provider-specific model identifier
    prompt          str             echoed prompt
    modality        str             "text" | "image" (which mode was used)
    aspect_ratio    str             provider-native (e.g. "16:9") or ""
    duration        int             seconds (0 if not applicable)
    provider        str             provider name (for diagnostics)
    error           str             only when success=False
    error_type      str             only when success=False
é    )ÚannotationsN)ÚPath)ÚAnyÚDictÚListÚOptionalÚTuple)ú16:9z9:16z1:1z4:3z3:4z3:2z2:3zTuple[str, ...]ÚCOMMON_ASPECT_RATIOSr
   )Ú480pÚ540pÚ720pÚ1080pÚCOMMON_RESOLUTIONSr   c                  ó¼   — e Zd ZdZeej        d!d„¦   «         ¦   «         Zed!d„¦   «         Zd"d„Z	d#d	„Z
d$d„Zd%d„Zd$d„Zej        ddddeeddddœ	d&d „¦   «         ZdS )'ÚVideoGenProvideru»   Abstract base class for a video generation backend.

    Subclasses must implement :meth:`generate`. Everything else has sane
    defaults â€” override only what your provider needs.
    ÚreturnÚstrc                ó   — dS )zŽStable short identifier used in ``video_gen.provider`` config.

        Lowercase, no spaces. Examples: ``xai``, ``fal``, ``google``.
        N© ©Úselfs    ú>/home/ragecks/.hermes/hermes-agent/agent/video_gen_provider.pyÚnamezVideoGenProvider.nameR   ó   € € € ó    c                ó4   — | j                              ¦   «         S )zMHuman-readable label shown in ``hermes tools``. Defaults to ``name.title()``.)r   Útitler   s    r   Údisplay_namezVideoGenProvider.display_nameZ   s   € ð Œy�ŠÑ Ô Ð r   Úboolc                ó   — dS )z¢Return True when this provider can service calls.

        Typically checks for a required API key and optional-dependency
        import. Default: True.
        Tr   r   s    r   Úis_availablezVideoGenProvider.is_available_   s	   € ð ˆtr   úList[Dict[str, Any]]c                ó   — g S )aÍ  Return catalog entries for ``hermes tools`` model picker.

        Each entry represents a **model family** that supports text-to-video
        and/or image-to-video routing internally::

            {
                "id": "veo-3.1",                       # required
                "display": "Veo 3.1",                  # optional; defaults to id
                "speed": "~60s",                       # optional
                "strengths": "...",                    # optional
                "price": "$0.20/s",                    # optional
                "modalities": ["text", "image"],       # optional, advisory
            }

        Default: empty list (provider has no user-selectable models).
        r   r   s    r   Úlist_modelszVideoGenProvider.list_modelsg   s	   € ð" ˆ	r   úDict[str, Any]c                ó   — | j         ddg dœS )z9Return provider metadata for the ``hermes tools`` picker.Ú )r   ÚbadgeÚtagÚenv_vars)r   r   s    r   Úget_setup_schemaz!VideoGenProvider.get_setup_schemaz   s"   € ð Ô%ØØØð	
ð 
ð 	
r   úOptional[str]c                óh   — |                       ¦   «         }|r|d                              d¦  «        S dS )z7Return the default model id, or None if not applicable.r   ÚidN)r%   Úget)r   Úmodelss     r   Údefault_modelzVideoGenProvider.default_modelƒ   s6   € à×!Ò!Ñ#Ô#ˆØð 	'Ø˜!”9—=’= Ñ&Ô&Ð&Øˆtr   c           	     ób   — dgt          t          ¦  «        t          t          ¦  «        ddddddœS )a™  Return what this provider supports.

        Returned dict (all keys optional)::

            {
                "modalities": ["text", "image"],      # which inputs the backend accepts
                "aspect_ratios": ["16:9", "9:16", ...],
                "resolutions": ["720p", "1080p"],
                "max_duration": 15,                   # seconds
                "min_duration": 1,
                "supports_audio": True,
                "supports_negative_prompt": True,
                "max_reference_images": 7,
            }

        Used by the tool layer for soft validation and by ``hermes tools``
        for the picker. Default: text-only.
        Útexté
   é   Fr   )Ú
modalitiesÚaspect_ratiosÚresolutionsÚmax_durationÚmin_durationÚsupports_audioÚsupports_negative_promptÚmax_reference_images)Úlistr   r   r   s    r   ÚcapabilitieszVideoGenProvider.capabilitiesŠ   s?   € ð( "˜(Ý!Õ"6Ñ7Ô7ÝÕ 2Ñ3Ô3ØØØ#Ø(-Ø$%ð	
ð 	
ð 		
r   N©	ÚmodelÚ	image_urlÚreference_image_urlsÚdurationÚaspect_ratioÚ
resolutionÚnegative_promptÚaudioÚseedÚpromptrB   rC   rD   úOptional[List[str]]rE   úOptional[int]rF   rG   rH   rI   úOptional[bool]rJ   Úkwargsr   c       	        ó   — dS )uÊ  Generate a video from a prompt (text-to-video) or animate an image
        (image-to-video).

        Routing: if ``image_url`` is provided, the provider should route to
        its image-to-video endpoint; otherwise text-to-video. The plugin
        is responsible for picking the right underlying endpoint within
        the user's chosen model family.

        Implementations should return the dict from :func:`success_response`
        or :func:`error_response`. ``kwargs`` may contain forward-compat
        parameters future versions of the schema will expose â€”
        implementations MUST ignore unknown keys (no TypeError).

        Known optional kwarg: ``upscale`` (bool) â€” when true, the caller
        requests a post-generation high-resolution pass through the
        backend's video upscaler. Providers without an upscaler simply
        ignore it; providers that honor it should report ``upscaled: True``
        in the response ``extra``.
        Nr   )r   rK   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rO   s               r   ÚgeneratezVideoGenProvider.generate¨   r   r   ©r   r   ©r   r    )r   r#   )r   r&   )r   r-   ©rK   r   rB   r-   rC   r-   rD   rL   rE   rM   rF   r   rG   r   rH   r-   rI   rN   rJ   rM   rO   r   r   r&   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚpropertyÚabcÚabstractmethodr   r   r"   r%   r,   r2   r@   ÚDEFAULT_ASPECT_RATIOÚDEFAULT_RESOLUTIONrQ   r   r   r   r   r   K   s  € € € € € ðð ð ØÔðð ð ñ Ôñ „Xðð ð!ð !ð !ñ „Xð!ðð ð ð ðð ð ð ð&
ð 
ð 
ð 
ðð ð ð ð
ð 
ð 
ð 
ð< 	Ôð
  $Ø#'Ø48Ø"&Ø0Ø,Ø)-Ø $Ø"ð!ð !ð !ð !ð !ñ Ôð!ð !ð !r   r   r   r   c                 ó`   — ddl m}   | ¦   «         dz  dz  }|                     dd¬¦  «         |S )zBReturn ``$HERMES_HOME/cache/videos/``, creating parents as needed.r   )Úget_hermes_homeÚcacheÚvideosT)ÚparentsÚexist_ok)Úhermes_constantsr_   Úmkdir)r_   Úpaths     r   Ú_videos_cache_dirrg   Ò   sF   € à0Ð0Ð0Ð0Ð0Ð0àˆ?ÑÔ˜wÑ&¨Ñ1€DØ‡J‚J�t d€JÑ+Ô+Ð+Ø€Kr   ÚvideoÚmp4)ÚprefixÚ	extensionÚb64_datar   rj   rk   c               ó2  — t          j        | ¦  «        }t          j                             ¦   «                              d¦  «        }t          j        ¦   «         j        dd…         }t          ¦   «         |› d|› d|› d|› �z  }| 	                    |¦  «         |S )zÑDecode base64 video data and write under ``$HERMES_HOME/cache/videos/``.

    Returns the absolute :class:`Path` to the saved file.

    Filename format: ``<prefix>_<YYYYMMDD_HHMMSS>_<short-uuid>.<ext>``.
    ú%Y%m%d_%H%M%SNé   Ú_ú.)
Úbase64Ú	b64decodeÚdatetimeÚnowÚstrftimeÚuuidÚuuid4Úhexrg   Úwrite_bytes)rl   rj   rk   ÚrawÚtsÚshortrf   s          r   Úsave_b64_videor~   Û   s”   € õ Ô
˜8Ñ
$Ô
$€CÝ	Ô	×	Ò	Ñ	 Ô	 ×	)Ò	)¨/Ñ	:Ô	:€BÝŒJ‰LŒLÔ˜R˜a˜RÔ €EÝÑÔ FÐ!EÐ!E¨RÐ!EÐ!E°%Ð!EÐ!E¸)Ð!EÐ!EÑE€DØ×Ò�SÑÔÐØ€Kr   r{   Úbytesc               ó
  — t           j                              ¦   «                              d¦  «        }t          j        ¦   «         j        dd…         }t          ¦   «         |› d|› d|› d|› �z  }|                     | ¦  «         |S )z@Write raw video bytes (e.g. an HTTP download body) to the cache.rn   Nro   rp   rq   )rt   ru   rv   rw   rx   ry   rg   rz   )r{   rj   rk   r|   r}   rf   s         r   Úsave_bytes_videor�   ï   s„   € õ 
Ô	×	Ò	Ñ	 Ô	 ×	)Ò	)¨/Ñ	:Ô	:€BÝŒJ‰LŒLÔ˜R˜a˜RÔ €EÝÑÔ FÐ!EÐ!E¨RÐ!EÐ!E°%Ð!EÐ!E¸)Ð!EÐ!EÑE€DØ×Ò�SÑÔÐØ€Kr   ÚwebmÚmovÚmkv)z	video/mp4z
video/webmzvideo/quicktimezvideo/x-matroskag     €f@i  €)rj   ÚtimeoutÚ	max_bytesÚurlr…   Úfloatr†   Úintc          	     óè  — ddl }|                     | |d¬¦  «        }|                     ¦   «          |j                             d¦  «        pd                     dd¦  «        d                              ¦   «                              ¦   «         }t                               |¦  «        }|€O|                      d	d¦  «        d                              ¦   «         }d
D ]}	|                     d|	› �¦  «        r|	} nŒ|€d}t          j	         
                    ¦   «                              d¦  «        }
t          j        ¦   «         j        dd…         }t          ¦   «         |› d|
› d|› d|› �z  }d}|                     d¦  «        5 }|                     d¬¦  «        D ]…}|sŒ|t%          |¦  «        z  }||k    rS|                     ¦   «          	 |                     ¦   «          n# t*          $ r Y nw xY wt-          d| › d|dz  › d�¦  «        ‚|                     |¦  «         Œ†	 ddd¦  «         n# 1 swxY w Y   |dk    r9	 |                     ¦   «          n# t*          $ r Y nw xY wt-          d| › d�¦  «        ‚|S )aÞ  Download a video URL and write it under ``$HERMES_HOME/cache/videos/``.

    The video twin of :func:`agent.image_gen_provider.save_url_image`: several
    backends (DeepInfra, FAL) return an *ephemeral* delivery URL that expires
    before a downstream consumer can fetch it, so we materialise the bytes
    locally at tool-completion time. Streams with a size cap.

    Raises on any network / HTTP / oversize error so callers can fall back to
    returning the bare URL.
    r   NT)r…   ÚstreamzContent-Typer(   ú;r6   ú?)ri   r‚   rƒ   r„   rq   ri   rn   ro   rp   Úwbi   )Ú
chunk_sizez	Video at z	 exceeds i   zMB cap; refusing to cache.z was empty (0 bytes).)Úrequestsr0   Úraise_for_statusÚheadersÚsplitÚstripÚlowerÚ_URL_VIDEO_CONTENT_TYPESÚendswithrt   ru   rv   rw   rx   ry   rg   ÚopenÚiter_contentÚlenÚcloseÚunlinkÚOSErrorÚ
ValueErrorÚwrite)r‡   rj   r…   r†   r�   ÚresponseÚcontent_typerk   Úurl_pathÚextr|   r}   rf   Úbytes_writtenÚfhÚchunks                   r   Úsave_url_videor§     sü  € ð" €O€O€Oà�|Š|˜C¨¸ˆ|Ñ>Ô>€HØ×ÒÑÔÐàÔ$×(Ò(¨Ñ8Ô8Ð>¸B×EÒEÀcÈ1ÑMÔMÈaÔP×VÒVÑXÔX×^Ò^Ñ`Ô`€LÝ(×,Ò,¨\Ñ:Ô:€IØÐØ—9’9˜S !Ñ$Ô$ QÔ'×-Ò-Ñ/Ô/ˆØ0ð 	ð 	ˆCØ× Ò   S  Ñ+Ô+ð Ø�	Ø�ðð ÐØˆ	å	Ô	×	Ò	Ñ	 Ô	 ×	)Ò	)¨/Ñ	:Ô	:€BÝŒJ‰LŒLÔ˜R˜a˜RÔ €EÝÑÔ FÐ!EÐ!E¨RÐ!EÐ!E°%Ð!EÐ!E¸)Ð!EÐ!EÑE€Dà€MØ	�Š�4‰Œð ˜BØ×*Ò*°jÐ*ÑAÔAð 	ð 	ˆEØð ØØ�S ™ZœZÑ'ˆMØ˜yÒ(Ð(Ø—’‘
”
�
ðØ—K’K‘M”M�M�MøÝð ð ð Ø�Dðøøøå Ød ÐdÐd¨i¸KÑ.HÐdÐdÐdñô ð ð �HŠH�U‰OŒOˆOˆOð	ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð  ˜ÒÐð	Ø�KŠK‰MŒMˆMˆMøÝð 	ð 	ð 	ØˆDð	øøøåÐ? SÐ?Ð?Ð?Ñ@Ô@Ð@à€KsI   Å>AH(ÇGÇH(Ç
G)Ç&H(Ç(G)Ç)2H(È(H,È/H,È:I É
IÉIr4   r(   )ÚmodalityrF   rE   ÚextrarB   rK   r¨   rF   rE   Úproviderr©   úOptional[Dict[str, Any]]r&   c           	     ó¢   — d| |||||rt          |¦  «        nd|dœ}|r0|                     ¦   «         D ]\  }	}
|                     |	|
¦  «         Œ|S )u  Build a uniform success response dict.

    ``video`` may be an HTTP URL or an absolute filesystem path.
    ``modality`` is ``"text"`` (text-to-video) or ``"image"`` (image-to-video) â€”
    indicates which endpoint was actually hit, useful for diagnostics.
    Tr   )Úsuccessrh   rB   rK   r¨   rF   rE   rª   )r‰   ÚitemsÚ
setdefault)rh   rB   rK   r¨   rF   rE   rª   r©   ÚpayloadÚkÚvs              r   Úsuccess_responser³   E  sz   € ð$ ØØØØØ$Ø%-Ð4•C˜‘M”M�M°1Øð	ð 	€Gð ð %Ø—K’K‘M”Mð 	%ð 	%‰DˆAˆqØ×Ò˜q !Ñ$Ô$Ð$Ð$Ø€Nr   Úprovider_error)Ú
error_typerª   rB   rK   rF   Úerrorrµ   c           	     ó   — dd| |||||dœS )z$Build a uniform error response dict.FN)r­   rh   r¶   rµ   rB   rK   rF   rª   r   ©r¶   rµ   rª   rB   rK   rF   s         r   Úerror_responser¹   f  s+   € ð ØØØ ØØØ$Øð	ð 	ð 	r   c            
      óŠ   — e Zd ZU dZdZded<   dZded<   dZded	<   d
Zded<   d(d„Z	d)d„Z
d*d„Zd(d„Zddddeeddddœ	d+d'„ZdS ),Ú OpenAICompatibleVideoGenProviderug  Generic text/image-to-video over the OpenAI ``client.videos`` API.

    DeepInfra, OpenAI/Sora, and OpenRouter all expose the same
    ``POST /videos`` async-job shape (``create`` â†’ poll â†’ ``download_content``),
    so the SDK call lives here once. A concrete backend only needs to declare
    its identity and credentials::

        class FooVideoGenProvider(OpenAICompatibleVideoGenProvider):
            name = "foo"
            _env_key = "FOO_API_KEY"
            _default_base_url = "https://api.foo.com/v1/openai"
            def list_models(self):
                return [...]   # entries with an "id" key; default_model() uses [0]

    ``image_url`` routes to image-to-video; its absence routes to text-to-video.
    Provider-specific fields (``image_url``/``negative_prompt``/``seed``) ride
    in ``extra_body`` so they pass through the SDK unchanged.
    ÚOPENAI_API_KEYr   Ú_env_keyzhttps://api.openai.com/v1Ú_default_base_urlg      @rˆ   Ú_poll_interval_sg      Œ@Ú_poll_deadline_sr   c                ón   — dd l }|j                             | j        d¦  «                             ¦   «         S )Nr   r(   )ÚosÚenvironr0   r½   r”   )r   rÂ   s     r   Ú_api_keyz)OpenAICompatibleVideoGenProvider._api_key¡  s/   € Øˆ	ˆ	ˆ	àŒz�~Š~˜dœm¨RÑ0Ô0×6Ò6Ñ8Ô8Ð8r   r    c                óD   — t          |                      ¦   «         ¦  «        S ©N)r    rÄ   r   s    r   r"   z-OpenAICompatibleVideoGenProvider.is_available¦  s   € Ý�D—M’M‘O”OÑ$Ô$Ð$r   Úclientr   Úcall_kwargsr&   c                óò  — ddl } |j        j        di |¤Ž}h d£}|                     ¦   «         | j        z   }t          |dd¦  «        |vr­|                     ¦   «         |k    rIt          dt          |dd¦  «        › dt          | j        ¦  «        › d	t          |dd¦  «        ›d
�¦  «        ‚|                     | j	        ¦  «         |j         
                    |j        ¦  «        }t          |dd¦  «        |v°­|S )aC  Create the video job and poll to completion with a hard deadline.

        Replaces ``client.videos.create_and_poll`` (unbounded 1/s loop) with a
        coarse interval and a wall-clock cap. Returns the terminal video object
        (any status); raises :class:`TimeoutError` if the deadline passes
        first.
        r   N>   r¶   ÚfailedÚcanceledÚ	cancelledÚ	completedÚ	succeededÚstatusz
video job r/   r�   z( did not reach a terminal status within zs (last status=ú)r   )Útimera   ÚcreateÚ	monotonicrÀ   ÚgetattrÚTimeoutErrorr‰   Úsleepr¿   Úretriever/   )r   rÇ   rÈ   rÑ   rh   ÚterminalÚdeadlines          r   Ú_create_and_pollz1OpenAICompatibleVideoGenProvider._create_and_poll©  s0  € ð 	ˆˆˆà$�”Ô$Ð3Ð3 {Ð3Ð3ˆØYÐYÐYˆØ—>’>Ñ#Ô# dÔ&;Ñ;ˆÝ�e˜X tÑ,Ô,°HÐ<Ð<Ø�~Š~ÑÔ 8Ò+Ð+Ý"ðH¥¨°°cÑ!:Ô!:ð Hð HÝ%(¨Ô)>Ñ%?Ô%?ðHð Hå$+¨E°8¸TÑ$BÔ$BðHð Hð Hñô ð ð
 �JŠJ�tÔ,Ñ-Ô-Ð-Ø”M×*Ò*¨5¬8Ñ4Ô4ˆEõ �e˜X tÑ,Ô,°HÐ<Ð<ð ˆr   c                óª   — dd l }|j                             | j                             ¦   «         › d�d¦  «                             ¦   «         }|p| j        S )Nr   Ú	_BASE_URLr(   )rÂ   rÃ   r0   r   Úupperr”   r¾   )r   rÂ   Úoverrides      r   Ú	_base_urlz*OpenAICompatibleVideoGenProvider._base_urlÁ  sO   € Øˆ	ˆ	ˆ	à”:—>’> T¤Y§_¢_Ñ%6Ô%6Ð"AÐ"AÐ"AÀ2ÑFÔF×LÒLÑNÔNˆØÐ1˜4Ô1Ð1r   NrA   rK   rB   r-   rC   rD   rL   rE   rM   rF   rG   rH   rI   rN   rJ   rO   c       	   	     óš  — |r|                      ¦   «         st          dd| j        ¬¦  «        S |                      ¦   «         st          | j        › d�d| j        ¬¦  «        S 	 dd l}n'# t          $ r t          dd| j        ¬¦  «        cY S w xY w|p|                      ¦   «         }|s t          d	| j        › d
�d| j        ¬¦  «        S d„ ||||
dœ                     ¦   «         D ¦   «         }||dœ}|rt          |¦  «        |d<   |r||d<   |r||d<   | 
                    |                      ¦   «         |                      ¦   «         ¬¦  «        }	 	 |                      ||¦  «        }nˆ# t          $ r{}t                               d| j        d¬¦  «         t          | j        › d|› �d| j        |||¬¦  «        cY d }~t!          |dd ¦  «        }t#          |¦  «        r |¦   «          S S d }~ww xY wt!          |dd ¦  «        }|dvrjt!          |dd ¦  «        }t          |rt          |¦  «        nd|›�d| j        |||¬¦  «        t!          |dd ¦  «        }t#          |¦  «        r |¦   «          S S d }t!          |dd ¦  «        pg D ]C}t%          |t&          ¦  «        r|                     d ¦  «        nt!          |d d ¦  «        }|r|} nŒD	 |r$t          t+          || j        ¬!¦  «        ¦  «        }nT|j                             |j        ¦  «                             ¦   «         }t          t5          || j        ¬!¦  «        ¦  «        }n‘# t          $ r„}|r$t                               d"| j        |¦  «         |}nTt          | j        › d#|› �d$| j        |||¬¦  «        cY d }~t!          |dd ¦  «        }t#          |¦  «        r |¦   «          S S Y d }~nd }~ww xY wt7          ||||rd%nd&||pd| j        ¬'¦  «        t!          |dd ¦  «        }t#          |¦  «        r |¦   «          S S # t!          |dd ¦  «        }t#          |¦  «        r |¦   «          w w xY w)(Nzprompt is requiredÚinvalid_request)r¶   rµ   rª   z is not setÚmissing_credentialsr   z8openai Python package not installed (pip install openai)Úmissing_dependencyzno z, video model available (live catalog empty?)Úno_modelc                ó   — i | ]
\  }}|®||“ŒS rÆ   r   )Ú.0r±   r²   s      r   ú
<dictcomp>z=OpenAICompatibleVideoGenProvider.generate.<locals>.<dictcomp>ó  s/   € ð 	
ð 	
ð 	
á��1ð ˆ}ð ˆqð ˆ}ˆ}r   )rH   rF   rC   rJ   )rB   rK   ÚsecondsÚsizeÚ
extra_body)Úapi_keyÚbase_urlz%s video generation failedT)Úexc_infoz video generation failed: Ú	api_errorr¸   r›   rÏ   )rÍ   rÎ   r¶   zvideo job ended with status=Ú
job_failedÚdatar‡   )rj   z3%s: saving video locally failed (%s); returning URLz7 video job succeeded but no output could be retrieved: Úempty_responseÚimager4   )rh   rB   rK   r¨   rF   rE   rª   )r”   r¹   r   rÄ   r½   ÚopenaiÚImportErrorr2   r®   r   ÚOpenAIrß   rÚ   Ú	ExceptionÚloggerÚdebugrÔ   ÚcallableÚ
isinstanceÚdictr0   r§   ra   Údownload_contentr/   Úreadr�   r³   )r   rK   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rO   ró   Úmodel_idrê   rÈ   rÇ   rh   Úexcr›   rÏ   Ú	job_errorr‡   ÚitemÚ	candidateÚ	video_refr{   s                              r   rQ   z)OpenAICompatibleVideoGenProvider.generateÇ  s³  € ð ð 	˜VŸ\š\™^œ^ð 	Ý!Ø*Ð7HÐSWÔS\ðñ ô ð ð �}Š}‰Œð 	Ý!ØœÐ3Ð3Ð3Ø0Øœðñ ô ð ð
	ØˆMˆMˆMˆMøÝð 	ð 	ð 	Ý!ØPØ/Øœðñ ô ð ð ð ð	øøøð Ð0˜D×.Ò.Ñ0Ô0ˆØð 	Ý!ØS˜DœIÐSÐSÐSØ%Øœðñ ô ð ð	
ð 	
ð $3Ø ,Ø&Øð	ð ÷
 Še‰gŒgð	
ñ 	
ô 	
ˆ
ð 19ÀFÐ&KÐ&KˆØð 	3Ý%(¨¡]¤]ˆK˜	Ñ"Øð 	-Ø",ˆK˜ÑØð 	3Ø(2ˆK˜Ñ%à—’ t§}¢}¡¤ÀÇÂÑAQÔAQ�ÑRÔRˆðN	ðØ×-Ò-¨f°kÑBÔB��øÝð 	ð 	ð 	Ý—’Ð9¸4¼9Èt�ÑTÔTÐTÝ%Ø!œYÐGÐGÀ#ÐGÐGØ*Ø!œYØ"Ø!Ø!-ðñ ô ð ð ð ð ð õN ˜F G¨TÑ2Ô2ˆEÝ˜‰Œð Ø�‘”��ðøøøøðU	øøøõ ˜U H¨dÑ3Ô3ˆFØÐ7Ð7Ð7õ $ E¨7°DÑ9Ô9�	Ý%Ø,5Ðd�#˜i™.œ.˜.Ð;dÐZ`Ð;dÐ;dØ+Ø!œYØ"Ø!Ø!-ðñ ô õl ˜F G¨TÑ2Ô2ˆEÝ˜‰Œð Ø�‘”��ððS ˆCÝ  v¨tÑ4Ô4Ð:¸ð ð �Ý/9¸$ÅÑ/EÔ/EÐe˜DŸHšH U™OœO˜OÍ7ÐSWÐY^Ð`dÑKeÔKe�	Øð Ø#�CØ�EððØð Må #¥N°3¸t¼yÐ$IÑ$IÔ$IÑ JÔ J�I�Ið !œ-×8Ò8¸¼ÑBÔB×GÒGÑIÔI�CÝ #Õ$4°SÀÄÐ$KÑ$KÔ$KÑ LÔ L�IøøÝð ð ð Øð å—L’LÐ!VÐX\ÔXaÐcfÑgÔgÐgØ #�I�Iå)Ø!%¤ÐhÐhÐcfÐhÐhØ#3Ø!%¤Ø&Ø%Ø%1ðñ ô ð ð ð ð ð õ& ˜F G¨TÑ2Ô2ˆEÝ˜‰Œð Ø�‘”��ðð- �I�I�I�Iøøøøð	øøøõ $ØØØØ$-Ð9˜˜°6Ø)Ø!˜ QØœðñ ô õ ˜F G¨TÑ2Ô2ˆEÝ˜‰Œð Ø�‘”��ðøõ ˜F G¨TÑ2Ô2ˆEÝ˜‰Œð Ø�‘”��ðøøøs‰   Á"A' Á'!BÂ
BÅE$ Å#P Å$
G)Å.AG$Æ3G)Æ4P Ç$G)Ç)AP É+AP ËA:M  Ì?P Í 
OÍ
A	O	ÎOÎP ÏP Ï	OÏ#P Ð-Q
rR   rS   )rÇ   r   rÈ   r&   r   r   rT   )rU   rV   rW   rX   r½   Ú__annotations__r¾   r¿   rÀ   rÄ   r"   rÚ   rß   r\   r]   rQ   r   r   r   r»   r»   �  sþ   € € € € € € ðð ð& %€HÐ$Ð$Ð$Ñ$Ø8ÐÐ8Ð8Ð8Ñ8ð "ÐÐ!Ð!Ð!Ñ!Ø#ÐÐ#Ð#Ð#Ñ#ð9ð 9ð 9ð 9ð
%ð %ð %ð %ðð ð ð ð02ð 2ð 2ð 2ð  $Ø#'Ø48Ø"&Ø0Ø,Ø)-Ø $Ø"ðMð Mð Mð Mð Mð Mð Mð Mr   r»   )r   r   )rl   r   rj   r   rk   r   r   r   )r{   r   rj   r   rk   r   r   r   )
r‡   r   rj   r   r…   rˆ   r†   r‰   r   r   )rh   r   rB   r   rK   r   r¨   r   rF   r   rE   r‰   rª   r   r©   r«   r   r&   )r¶   r   rµ   r   rª   r   rB   r   rK   r   rF   r   r   r&   )"rX   Ú
__future__r   rZ   rr   rt   Úloggingrw   Úpathlibr   Útypingr   r   r   r   r	   Ú	getLoggerrU   r÷   r   r  r\   r   r]   ÚABCr   rg   r~   r�   r–   r§   r³   r¹   r»   r   r   r   ú<module>r     sL  ðð,ð ,ð ,ð\ #Ð "Ð "Ð "Ð "Ð "à 
€
€
€
Ø €€€Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3à	ˆÔ	˜8Ñ	$Ô	$€ð )\Ð Ð [Ð [Ð [Ñ [ØÐ à&GÐ Ð GÐ GÐ GÑ GØÐ ðð ð ð ð �s”wñ ô ð ðNð ð ð ð Øð	ð ð ð ð ð ð. Øð	ð ð ð ð ð ð ØØØð	ð Ð ð ØØ&ð=ð =ð =ð =ð =ð =ðJ ØØà&*ðð ð ð ð ð ðH 'ØØØØðð ð ð ð ð ð6Sð Sð Sð Sð SÐ'7ñ Sô Sð Sð Sð Sr   