
    `gj^U                       U d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
mZmZmZmZmZ ddlmZmZ  ej&                  e      Zddd	d
ddd
ddddd
idddddd
 ee      dedd
 ee      dedd
ddddddddd
ddd
dgddZd ed!<   d3d"Zd4d#Zd4d$Zd5d%Zd& Zd6d'Zd7d(Zd8d)Z d9d*Z!d:d+Z"d,Z#	 	 	 	 	 	 d;d-Z$d3d.Z% ejL                  dd/ee"eg d0d1e%2	       y)<u  
Video Generation Tool
=====================

Single ``video_generate`` tool that dispatches to a plugin-registered
video generation provider. Mirrors the ``image_generate`` design:

- ``agent/video_gen_provider.py`` defines the :class:`VideoGenProvider` ABC.
- ``agent/video_gen_registry.py`` holds the active providers (populated by
  plugins at import time).
- Each provider lives under ``plugins/video_gen/<name>/``.

The tool itself is intentionally backend-agnostic and ships **no in-tree
provider** — turn on a backend by enabling a plugin (``hermes plugins
enable video_gen/<name>``) and selecting it in ``hermes tools`` → Video
Generation.

Unified surface
---------------
One tool covers the common cases - text-to-video, image-to-video, and
reference-to-video - with a compact schema:

    prompt                   text instruction (required)
    image_url                drives image-to-video
    reference_image_urls     list, up to provider-declared cap
    duration                 seconds (provider clamps)
    aspect_ratio             "16:9" | "9:16" | "1:1" | ...
    resolution               "480p" | "540p" | "720p" | "1080p"
    negative_prompt          optional (Pixverse/Kling style)
    audio                    optional (Veo3/Pixverse pricing tier)
    seed                     optional
    model                    optional, override the active provider's default

Providers ignore parameters they do not support. The tool layer does
**lightweight** validation (type/required-prompt) and lets each provider
do its own clamping inside :meth:`VideoGenProvider.generate` — that keeps
the tool surface stable as new providers ship with different capabilities.

Video edit and video extend are intentionally not exposed here; providers with
those workflows should expose separate tools.
    )annotationsN)AnyDictListOptional)COMMON_ASPECT_RATIOSCOMMON_RESOLUTIONSDEFAULT_ASPECT_RATIODEFAULT_RESOLUTIONerror_response)registry
tool_errorvideo_generateuG   (rebuilt at get_definitions() time — see _build_dynamic_video_schema)objectstringz\Text instruction describing the desired video, motion, subject, style, camera movement, etc.)typedescriptiona  Optional public HTTPS URL of a still image. When provided, the active backend routes to its image-to-video endpoint (animate the image); when omitted, it routes to text-to-video. For xAI chaining, use the `image` or `public_url` HTTPS URL from a prior Imagine result.arrayr   zOptional list of public HTTPS reference image URLs (style or character refs). For xAI chaining, use `image` or `public_url` from prior Imagine results.)r   itemsr   integerzDesired video duration in seconds. Providers clamp to their supported range (commonly 4-15s). Omit to use the provider's default.z<Output aspect ratio. Providers clamp to their supported set.)r   enumr   defaultz:Output resolution. Providers clamp to their supported set.u   Optional negative prompt — content to avoid in the output. Supported by Pixverse, Kling, and similar; ignored by providers that do not support it.booleanzkOptional audio generation toggle. Supported by Veo3 and Pixverse (affects pricing tier); ignored elsewhere.z<Optional seed for reproducible outputs (provider-dependent).u   Optional model override. If omitted, the user's configured ``video_gen.model`` (set via `hermes tools` → Video Generation) is used. Models that the active provider does not know are rejected.)
prompt	image_urlreference_image_urlsdurationaspect_ratio
resolutionnegative_promptaudioseedmodelr   )r   
propertiesrequired)namer   
parametersDict[str, Any]VIDEO_GENERATE_SCHEMAc                     	 ddl m}   |        }t        |t              r|j	                  d      nd }t        |t              r|S i S # t
        $ r"}t        j                  d|       i cY d }~S d }~ww xY w)Nr   )load_config	video_genz#Could not read video_gen config: %s)hermes_cli.configr+   
isinstancedictget	Exceptionloggerdebug)r+   cfgsectionexcs       N/root/.hermes/venv/lib/python3.12/site-packages/tools/video_generation_tool.py_read_video_gen_sectionr8      sb    1m*4S$*?#''+&T$Wd3w;; :C@	s$   AA A 	A1A,&A1,A1c                     t               j                  d      } t        | t              r | j	                         r| j	                         S y )Nproviderr8   r0   r.   strstripvalues    r7   _read_configured_video_providerr@      s6    #%))*5E%%++-{{}    c                     t               j                  d      } t        | t              r | j	                         r| j	                         S y )Nr#   r;   r>   s    r7   _read_configured_video_modelrC      s6    #%))'2E%%++-{{}rA   c                     	 ddl m}  ddlm}  |         |        D ]  }	 |j	                         r y 	 y# t
        $ r Y %w xY w# t
        $ r Y yw xY w)zReturn True when at least one registered provider reports available.

    Triggers plugin discovery (idempotent) so user-installed plugins are
    visible to the toolset gate.
    r   )list_providers_ensure_plugins_discoveredTF)agent.video_gen_registryrE   hermes_cli.pluginsrG   is_availabler1   )rE   rG   r:   s      r7   #check_video_generation_requirementsrK      sk    ;A"$&( 	H((* +	 	   s5   A 6A A 	AA AA 	AAc                     	 ddl m}  ddlm}  |         |        }| |d        |        }|S # t        $ r }t
        j                  d|       Y d}~yd}~ww xY w)u   Return the active provider object or None.

    Forces plugin discovery before checking the registry — handles cases
    where a long-lived session was started before a plugin was installed.
    r   )get_active_providerrF   NT)forcez(video_gen provider resolution failed: %s)rH   rM   rI   rG   r1   r2   r3   )rM   rG   r:   r6   s       r7   _resolve_active_providerrO      sX    @A"$&(&T2*,H ?Es   -0 	AAAc                    | r'd|  d}t        j                  t        |d|             S d}t        j                  t        |d            S )Nzvideo_gen.provider='u   ' is set but no plugin registered that name. Run `hermes plugins list` to see installed video gen backends, or `hermes tools` → Video Generation to pick one.provider_not_registered)error
error_typer:   u{   No video generation backend is configured. Run `hermes tools` → Video Generation to enable one (xAI, FAL, or Google Veo).no_provider_configured)rR   rS   )jsondumpsr   )
configuredmsgs     r7   _missing_provider_errorrY      si    ":, /& ' 	 zz.";
  	
	D  ::n6  rA   c                T    | | dk(  ry 	 t        |       S # t        t        f$ r Y y w xY w)N )int	TypeError
ValueErrorr>   s    r7   _coerce_intr_     s6    }5zz" s   
 ''c                    | y t        | t              r| S t        | t              r(| j                         j	                         }|dv ry|dv ryy )N>   1onyestrueT>   0noofffalseF)r.   boolr<   r=   lower)r?   vs     r7   _coerce_boolrl     sR    }%%KKM!**++rA   c                    | y t        | t              r| g} t        | t        t        f      sy g }| D ]C  }t        |t              s|j	                         s%|j                  |j	                                E |xs d S )N)r.   r<   listtupler=   append)r?   outitems      r7   _normalize_reference_imagesrs   (  sp    }%edE]+C %dC TZZ\JJtzz|$% ;$rA   c                   | j                  d      xs dj                         }| j                  d      xs dj                         xs d }t        | j                  d            }t        | j                  d            }| j                  d      xs t        j                         xs t        }| j                  d      xs t
        j                         xs t
        }| j                  d      xs dj                         xs d }t        | j                  d	            }	t        | j                  d
            }
| j                  d      xs dj                         xs d }|st        d      S d| v sd| v rt        d      S t               }t               }|t        |      S |xs t               xs |j                         }|t        |      |||||||	|
d
}|j                         D ci c]  \  }}|	|| }}}	  |j                  dd|i|}t1        |t2              s2t)        j*                  t-        ddt'        |dd      |xs d|            S t)        j*                  |      S c c}}w # t         $ rm}t"        j%                  dt'        |dd      |       t)        j*                  t-        dt'        |dd       ddt'        |dd      |xs d|            cY d }~S d }~wt.        $ ro}t"        j%                  dt'        |dd      |       t)        j*                  t-        dt'        |dd       d| dt'        |dd      |xs d|            cY d }~S d }~ww xY w)Nr   r[   r   r   r   r   r   r    r!   r"   r#   z'prompt is required for video generation	operation	video_urlzvideo_generate only supports text-to-video, image-to-video, and reference-to-video; use a provider-specific tool for video edit/extend)
r#   _model_override_explicitr   r   r   r   r   r    r!   r"   zBvideo_gen provider '%s' rejected kwargs (signature too narrow): %sr&   ?z
Provider 'z\' signature is out of date with the video_generate schema. Report this to the plugin author.provider_contract)rR   rS   r:   r#   r   z"video_gen provider '%s' raised: %sz	' error: provider_exceptionz#Provider returned a non-dict result )r0   r=   rs   r_   r
   r   rl   r   r@   rO   rY   rC   default_modelri   r   generater]   r2   warninggetattrrU   rV   r   r1   r.   r/   )args_kwr   r   r   r   r   r   r    r!   r"   model_overriderW   r:   r#   kwargskrk   resultr6   s                       r7   _handle_video_generater   6  sK   hhx &B--/F+&,"335=I6txx@V7WX488J/0HHH^,D0DKKMeQeL((<(>,>EEG]K]Jxx 128b??AITO'*+Etxx'(Dhhw'-2446>$N
 CDDdkT1U
 	
 12J')H&z22 X:<X@V@V@XE $($8 4$ *F  &||~?tq!ad?F?""";&;F;@ fd#zz.7*Xvr2+2
  	 ::fY @   	PHfc*C	
 zz.WXvs;< =( ) +Xvr2+2

 
 
	  0Hfc*C	
 zz.wx=>iuM+Xvr2+2
  	s>   )
I(4I(=I. .	M7A"KMM+A$MMMu[  Generate a video from a text prompt (text-to-video), animate a still image (image-to-video), or guide generation with reference images. Pass `image_url` to animate an image or `reference_image_urls` for reference-to-video. Video edit/extend workflows are not part of this unified surface; use a dedicated provider-specific tool when one is available. The backend and model family are user-configured via `hermes tools` → Video Generation; the agent does not pick them. Long-running generations may take 30 seconds to several minutes — the call blocks until the video is ready. Returns the result in the `video` field — either an HTTP URL or an absolute file path. To show it to the user, reference that path/URL in your response using the file-delivery convention for the current platform (your platform guidance describes how files are delivered here).c                    g }t        | j                  d      xs g       }| j                  d      }|r|j                  |       d|v rd|vr|j                  d       |S d|v rd|vr|j                  d       |S )u   Pull human-readable caveats out of one model's catalog metadata.

    Only surfaces things that meaningfully differ from the backend's
    overall capabilities — repeating defaults is noise.
    
modalitiesmodalityimagetextu]   this model is image-to-video only — image_url is REQUIRED; text-only calls will be rejectedu?   this model is text-to-video only — image_url is not supported)setr0   addrp   )
model_metabackend_capscaveatsr   r   s        r7   _format_model_caveatsr     s     GZ^^L17R8J~~j)Hx *z!9/	
 N 
:	'";M	
 NrA   c                    t         g} t               }t               }|$| j                  d       ddj	                  |       iS 	 |j                         xs i }	 |j                         xs g }|xs |j                         t        fd|D        i       }|j                  }d| }r|d z  }| j                  |       t        ||      D ]  }| j                  d|         t        |j                  d      xs g       }	d	|	v r&d
|	v r"|j                  d      s| j                  d       |j                  d      r&| j                  ddj	                  |d                 |j                  d      r&| j                  ddj	                  |d                 |j                  d      r/|j                  d      r| j                  d|d    d|d    d       |j                  d      r| j                  d       |j                  d      r| j                  d       |j                  d      xs d}
|
r| j                  d|
 d       |j                  dk(  r6| j                  d        	 dd!lm}  |d"      }|r| j                  d$|        ddj	                  |       iS # t        $ r i }Y [w xY w# t        $ r g }Y Xw xY w# t        $ r d#}Y Zw xY w)%a\  Build a description that reflects the active backend's actual surface.

    Cheap: reads config (already memoized by the caller), asks the active
    provider for `capabilities()` and the active model's catalog entry,
    and formats a few lines of prose. Falls back to the generic
    description when no provider is configured or registered.
    u|   
No video backend is available. Calls will return an error until the user picks one via `hermes tools` → Video Generation.r   
c              3  n   K   | ],  }t        |t              s|j                  d       k(  s)| . yw)idN)r.   r/   r0   ).0mactive_models     r7   	<genexpr>z._build_dynamic_video_schema.<locals>.<genexpr>  s)     RqjD1aeeDk\6QRs   555z
Active backend: u    · model: z- r   r   r   r   uk   - supports both text-to-video (omit image_url) and image-to-video (pass image_url) — routes automaticallyaspect_ratiosz- aspect_ratio choices: z, resolutionsz- resolution choices: min_durationmax_durationz- duration range: -ssupports_audioz@- audio: pass `audio=true` to enable native audio (pricing tier)supports_negative_promptz- negative_prompt: supportedmax_reference_imagesr   z- reference_image_urls: up to z imagesxaiz- chaining: for edit/extend pass the public HTTPS MP4 in `video` or `public_url` from the prior Imagine result (files-cdn). For image-to-video / reference-to-video pass public image URLs the same way)xai_storage_notice_textr,   r[   z- storage: )_GENERIC_DESCRIPTIONrC   rO   rp   joincapabilitiesr1   list_modelsr|   nextdisplay_namer   r   r0   r&   tools.xai_httpr   )partsconfigured_modelr:   capsmodelsr   backend_labellinecr   max_refsr   noticer   s                @r7   _build_dynamic_video_schemar     s    --E35 ()HP	
 tyy/00$$&,"%%'-2 $?x'='='?LRFR
J
 ))M/D+l^,,	LL #:t4 r!X TXXl+1r2J: 5jnnZ>XG	

 xx /		$:O0P/QRSxx-dii]8K.L-MNOxxDHH^$< n!5 6a^8L7MQO	
 xx !WXxx*+34xx./41H5hZwGH}}	
	>,[9F LL;vh/0499U+,,A    n  	F	s6   J% J7 .K	 %J43J47KK	KKr,   Fu   🎬)	r&   toolsetschemahandlercheck_fnrequires_envis_asyncemojidynamic_schema_overrides)returnr(   )r   Optional[str])r   ri   )rW   r   r   r<   )r?   r   r   zOptional[int])r?   r   r   zOptional[bool])r?   r   r   zOptional[List[str]])r   r(   r   r   r   r<   )r   r(   r   r(   r   z	List[str])'__doc__
__future__r   rU   loggingtypingr   r   r   r   agent.video_gen_providerr   r	   r
   r   r   tools.registryr   r   	getLogger__name__r2   rn   r)   __annotations__r8   r@   rC   rK   rO   rY   r_   rl   rs   r   r   r   r   registerr{   rA   r7   <module>r      s  (T #   , ,  0			8	$  ] !< !J	   (+J	% "* !12 0 !/0 . !C  "J "" !;WT
j JoXb) ~ bT	6*4Y\8 "  :\-H   	 "0
8
rA   