
    PL
jo'                    $   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d0dZdddd1dZdddd2dZdddddd3d*Zd+ddddd,d4d/ZdS )5u  
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 )zStable short identifier used in ``video_gen.provider`` config.

        Lowercase, no spaces. Examples: ``xai``, ``fal``, ``google``.
        N selfs    </home/kuhnn/.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 )zReturn 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promptrA   rB   rC   Optional[List[str]]rD   Optional[int]rE   rF   rG   rH   Optional[bool]rI   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).
        Nr   )r   rJ   rA   rB   rC   rD   rE   rF   rG   rH   rI   rN   s               r   generatezVideoGenProvider.generate   r   r   )r   r   )r   r    )r   r#   )r   r&   )r   r-   )rJ   r   rA   r-   rB   r-   rC   rK   rD   rL   rE   r   rF   r   rG   r-   rH   rM   rI   rL   rN   r   r   r&   )__name__
__module____qualname____doc__propertyabcabstractmethodr   r   r"   r%   r,   r2   r@   DEFAULT_ASPECT_RATIODEFAULT_RESOLUTIONrP   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_dirrc      sF    000000?w&1DJJtdJ+++Kr   videomp4)prefix	extensionb64_datar   rf   rg   c               2   t          j        |           }t          j                                                            d          }t          j                    j        dd         }t                      | d| d| d| z  }|	                    |           |S )zDecode 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hexrc   write_bytes)rh   rf   rg   rawtsshortrb   s          r   save_b64_videorz      s     
8
$
$C					 	 	)	)/	:	:BJLLRaR EF!E!ER!E!E%!E!E)!E!EEDSKr   rw   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.rj   Nrk   rl   rm   )rp   rq   rr   rs   rt   ru   rc   rv   )rw   rf   rg   rx   ry   rb   s         r   save_bytes_videor}      s     
				 	 	)	)/	:	:BJLLRaR EF!E!ER!E!E%!E!E)!E!EEDSKr   r4   r(   )modalityrE   rD   extrarA   rJ   r~   rE   rD   int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   )successrd   rA   rJ   r~   rE   rD   r   )r   items
setdefault)rd   rA   rJ   r~   rE   rD   r   r   payloadkvs              r   success_responser      sz    $ $%-4CMMM1	 	G  %KKMM 	% 	%DAqq!$$$$Nr   provider_error)
error_typer   rA   rJ   rE   errorr   c           	         dd| |||||dS )z$Build a uniform error response dict.FN)r   rd   r   r   rA   rJ   rE   r   r   )r   r   r   rA   rJ   rE   s         r   error_responser     s+      $	 	 	r   )r   r   )rh   r   rf   r   rg   r   r   r   )rw   r{   rf   r   rg   r   r   r   )rd   r   rA   r   rJ   r   r~   r   rE   r   rD   r   r   r   r   r   r   r&   )r   r   r   r   r   r   rA   r   rJ   r   rE   r   r   r&   )rT   
__future__r   rV   rn   rp   loggingrs   pathlibr   typingr   r   r   r   r	   	getLoggerrQ   loggerr   __annotations__rX   r   rY   ABCr   rc   rz   r}   r   r   r   r   r   <module>r      s  , , ,\ # " " " " " 



           3 3 3 3 3 3 3 3 3 3 3 3 3 3		8	$	$ )\  [ [ [ [ &G  G G G G y y y y ysw y y yB    	     . 	     & &*     H '       r   