o
    ưi_R                     @   s   d dl m Z  d dlmZmZmZmZmZmZmZ d dl	Z	d dl
mZ d dlZd dlmZ d dlmZ d dlmZ d dlmZmZmZmZ d d	lmZ d d
lmZ d dlmZmZ d dlm Z m!Z! erkd dl"m#Z$ e$Z%neZ%G dd deZ&dS )    )datetime)TYPE_CHECKINGAnyDictListOptionalTupleUnionN)RequestFiles)RUNWAYML_DEFAULT_API_VERSIONBaseLLMException)BaseVideoConfig)AsyncHTTPHandlerHTTPHandler_get_httpx_clientget_async_httpx_client)get_secret_str)GenericLiteLLMParams) VideoCreateOptionalRequestParamsVideoObject)encode_video_id_with_providerextract_original_video_id)Loggingc                       s*  e Zd ZdZ fddZdedefddZdeded	e	de
fd
dZ		dIdededee dee def
ddZdedee dedefddZdededede
dededee
eef fddZ		dIdedejdedee dee
 defddZdedefd d!Zd"ee defd#d$Z	dJd%edededed&ee deee
f fd'd(Zd)e
eef defd*d+Zdejdedefd,d-Z dejdedefd.d/Z!	dJd%ededededed0ee
eef  deee
f fd1d2Z"	dJdejdedee defd3d4Z#				dKdededed5ee d6ee d7ee d8ee
eef  deee
f fd9d:Z$	dJdejdedee de
eef fd;d<Z%d%ededededeee
f f
d=d>Z&dejdedefd?d@Z'd%ededededeee
f f
dAdBZ(	dJdejdedee defdCdDZ)dEedFede*eej+f de,fdGdHZ-  Z.S )LRunwayMLVideoConfiga   
    Configuration class for RunwayML video generation.
    
    RunwayML uses a task-based API where:
    1. POST /v1/image_to_video creates a task
    2. The task returns immediately with a task ID
    3. Client must poll or wait for task completion
    c                    s   t    d S N)super__init__)self	__class__ b/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/runwayml/videos/transformation.pyr   +   s   zRunwayMLVideoConfig.__init__modelreturnc                 C   s   g dS )a&  
        Get the list of supported OpenAI parameters for video generation.
        Maps OpenAI params to RunwayML equivalents:
        - prompt -> promptText
        - input_reference -> promptImage
        - size -> ratio (e.g., "1280x720" -> "1280:720")
        - seconds -> duration
        )r#   promptinput_referencesecondssizeuserextra_headersr!   )r   r#   r!   r!   r"   get_supported_openai_params.   s   	z/RunwayMLVideoConfig.get_supported_openai_paramsvideo_create_optional_paramsdrop_paramsc              	   C   s   i }d|v r|d }||d< d|v r'|d }t |tr'd|v r'|dd|d< d|v rR|d }|durRzt |tr?tt|nt||d	< W n ttfyQ   Y nw | |}| D ]\}	}
|	|vrg|
||	< q[|S )
a  
        Map OpenAI parameters to RunwayML format.
        
        Mappings:
        - prompt -> promptText
        - input_reference -> promptImage  
        - size -> ratio (convert "WIDTHxHEIGHT" to "WIDTH:HEIGHT")
        - seconds -> duration (convert to integer)
        r&   ZpromptImager(   x:ratior'   Nduration)	
isinstancestrreplaceintfloat
ValueError	TypeErrorr+   items)r   r,   r#   r-   Zmapped_paramsr&   r(   r'   Zsupported_openai_paramskeyvaluer!   r!   r"   map_openai_paramsA   s,   &
z%RunwayMLVideoConfig.map_openai_paramsNheadersapi_keylitellm_paramsc                 C   sZ   |r
|j r
|p	|j }|ptj ptdptd}|du rtd|d| tdd |S )z
        Validate environment and set up authentication headers.
        RunwayML uses Bearer token authentication via RUNWAYML_API_SECRET.
        ZRUNWAYML_API_SECRETZRUNWAYML_API_KEYNzeRunwayML API key is required. Set RUNWAYML_API_SECRET environment variable or pass api_key parameter.zBearer zapplication/json)AuthorizationzX-Runway-VersionzContent-Type)r>   litellmr   r7   updater   )r   r=   r#   r>   r?   r!   r!   r"   validate_environmentp   s&   

z(RunwayMLVideoConfig.validate_environmentapi_basec                 C   s   |du rd}| dS )z
        Get the base URL for RunwayML API.
        The specific endpoint path will be added in the transform methods.
        Nzhttps://api.dev.runwayml.com/v1/)rstrip)r   r#   rD   r?   r!   r!   r"   get_complete_url   s   

z$RunwayMLVideoConfig.get_complete_urlr%   $video_create_optional_request_paramsc           
      C   s,   ||d}| | g }| d}	|||	fS )aB  
        Transform the video creation request for RunwayML API.
        
        RunwayML expects:
        {
            "model": "gen4_turbo",
            "promptImage": "https://... or data:image/...",
            "promptText": "description",
            "ratio": "1280:720",
            "duration": 5
        }
        )r#   Z
promptTextz/image_to_video)rB   )
r   r#   r%   rD   rH   r?   r=   request_dataZ
files_listZfull_api_baser!   r!   r"   transform_video_create_request   s   


z2RunwayMLVideoConfig.transform_video_create_requestraw_responselogging_objcustom_llm_providerrI   c              	   C   s  |  }|ddd| |dd| |dd}d|v r7|d r7t|d tr1|d d	 n|d |d
< d|v rE| |d|d< d|v sMd|v r\|dd|ddd|d< |rd|v rh|d |d< d|v r|d }t|trd|v r|dd|d< d|v rt|d |d< tdi |}	|r|	j	rt
|	j	|||	_	i }
|	rt|	dr|	jrz	t|	j|
d< W n ttfy   Y nw |
|	_|	S )ax  
        Transform the RunwayML video creation response.
        
        RunwayML returns a task object that looks like:
        {
            "id": "task_123...",
            "status": "PENDING" | "RUNNING" | "SUCCEEDED" | "FAILED",
            "output": ["https://...video.mp4"] (when succeeded)
        }
        
        We map this to OpenAI VideoObject format.
        id videostatuspending	createdAtrN   objectrQ   Z
created_atoutputr   
output_urlcompletedAtcompleted_atfailureCodefailureunknownVideo generation failedcodemessageerrorr#   r0   r/   r.   r(   r1   r'   Zduration_secondsNr!   )jsonget_map_runway_status_parse_runway_timestampr2   listr3   r4   r   rN   r   hasattrr'   r6   r7   r8   usage)r   r#   rK   rL   rM   rI   response_data
video_datar0   	video_objZ
usage_datar!   r!   r"   transform_video_create_response   sF   
&



z3RunwayMLVideoConfig.transform_video_create_responserunway_statusc                 C   s"   ddddddd}| | dS )z
        Map RunwayML status to OpenAI status format.
        
        RunwayML statuses: PENDING, RUNNING, SUCCEEDED, FAILED, CANCELLED
        OpenAI statuses: queued, in_progress, completed, failed
        ZqueuedZin_progress	completedfailed)PENDINGRUNNINGZ	SUCCEEDEDFAILED	CANCELLED	THROTTLED)rc   upper)r   rm   Z
status_mapr!   r!   r"   rd     s   z&RunwayMLVideoConfig._map_runway_statustimestamp_strc              	   C   sB   |sdS zt |dd}t| W S  ttfy    Y dS w )z
        Convert RunwayML ISO 8601 timestamp to Unix timestamp.
        
        RunwayML returns timestamps like: "2025-11-11T21:48:50.448Z"
        We need to convert to Unix timestamp (seconds since epoch).
        r   Zz+00:00)r   fromisoformatr4   r5   	timestampr7   AttributeError)r   rv   dtr!   r!   r"   re   !  s   z+RunwayMLVideoConfig._parse_runway_timestampvideo_idvariantc           	      C   s"   t |}| d| }i }||fS )a  
        Transform the video content request for RunwayML API.

        RunwayML doesn't have a separate content download endpoint.
        The video URL is returned in the task output field.
        We'll retrieve the task and extract the video URL.
        /tasks/r   )	r   r|   rD   r?   r=   r}   original_video_idurlparamsr!   r!   r"   transform_video_content_request3  s   z3RunwayMLVideoConfig.transform_video_content_requestri   c                 C   s   d}d|v r|d r|d }t |tr|d n|}|sB|dd}|dv r-td| d|d	kr>|d
d}td| td|S )z~
        Helper method to extract video URL from RunwayML response.
        Shared between sync and async transforms.
        NrV   r   rQ   UNKNOWN)rp   rq   rt   z#Video is still processing (status: z). Please wait and try again.rr   r[   zUnknown errorzVideo generation failed: z<Video URL not found in response. Video may not be ready yet.)r2   rf   rc   r7   )r   ri   	video_urlrV   rQ   Zfailure_reasonr!   r!   r"    _extract_video_url_from_responseK  s   z4RunwayMLVideoConfig._extract_video_url_from_responsec                 C   s0   |  }| |}t }||}|  |jS )a
  
        Transform the RunwayML video content download response (synchronous).
        
        RunwayML's task endpoint returns JSON with a video URL in the output field.
        We need to extract the URL and download the video.
        
        Example response:
        {
            "id":"63fd0f13-f29d-4e58-99d3-1cb9efa14a5b",
            "createdAt":"2025-11-11T21:48:50.448Z",
            "status":"SUCCEEDED",
            "output":["https://dnznrvs05pmza.cloudfront.net/.../video.mp4?_jwt=..."]
        }
        )rb   r   r   rc   raise_for_statuscontent)r   rK   rL   ri   r   Zhttpx_clientvideo_responser!   r!   r"    transform_video_content_responsec  s   

z4RunwayMLVideoConfig.transform_video_content_responsec                    s@   |  }| |}ttjjd}||I dH }|  |jS )a  
        Transform the RunwayML video content download response (asynchronous).
        
        RunwayML's task endpoint returns JSON with a video URL in the output field.
        We need to extract the URL and download the video asynchronously.
        
        Example response:
        {
            "id":"63fd0f13-f29d-4e58-99d3-1cb9efa14a5b",
            "createdAt":"2025-11-11T21:48:50.448Z",
            "status":"SUCCEEDED",
            "output":["https://dnznrvs05pmza.cloudfront.net/.../video.mp4?_jwt=..."]
        }
        )Zllm_providerN)	rb   r   r   rA   ZLlmProvidersZRUNWAYMLrc   r   r   )r   rK   rL   ri   r   Zasync_httpx_clientr   r!   r!   r"   &async_transform_video_content_response  s   
z:RunwayMLVideoConfig.async_transform_video_content_response
extra_bodyc                 C      t d)z
        Transform the video remix request for RunwayML API.
        
        RunwayML doesn't have a direct remix endpoint in their current API.
        This would need to be implemented when/if they add this feature.
        0Video remix is not yet supported by RunwayML APINotImplementedError)r   r|   r%   rD   r?   r=   r   r!   r!   r"   transform_video_remix_request     z1RunwayMLVideoConfig.transform_video_remix_requestc                 C   r   )z,Transform the RunwayML video remix response.r   r   r   rK   rL   rM   r!   r!   r"   transform_video_remix_response     z2RunwayMLVideoConfig.transform_video_remix_responseafterlimitorderextra_queryc                 C   r   )z
        Transform the video list request for RunwayML API.
        
        RunwayML doesn't expose a list endpoint in their public API yet.
        2Video listing is not yet supported by RunwayML APIr   )r   rD   r?   r=   r   r   r   r   r!   r!   r"   transform_video_list_request  r   z0RunwayMLVideoConfig.transform_video_list_requestc                 C   r   )z+Transform the RunwayML video list response.r   r   r   r!   r!   r"   transform_video_list_response  r   z1RunwayMLVideoConfig.transform_video_list_responsec                 C   s$   t |}| d| d}i }||fS )zx
        Transform the video delete request for RunwayML API.
        
        RunwayML uses task cancellation.
        r~   z/cancelr   r   r|   rD   r?   r=   r   r   datar!   r!   r"   transform_video_delete_request  s   z2RunwayMLVideoConfig.transform_video_delete_requestc              	   C   s0   |  }t|dddd| |dd}|S )z4Transform the RunwayML video delete/cancel response.rN   rO   rP   	cancelledrS   rT   )rb   r   rc   re   )r   rK   rL   ri   rk   r!   r!   r"   transform_video_delete_response  s   
z3RunwayMLVideoConfig.transform_video_delete_responsec                 C   s"   t |}| d| }i }||fS )z
        Transform the RunwayML video status retrieve request.
        
        RunwayML uses GET /v1/tasks/{task_id} to retrieve task status.
        r~   r   r   r!   r!   r"   'transform_video_status_retrieve_request  s   z;RunwayMLVideoConfig.transform_video_status_retrieve_requestc                 C   s   |  }|ddd| |dd| |dd}d|v r7|d r7t|d tr1|d d	 n|d |d
< d|v rE| |d|d< d|v rO|d |d< d|v sWd|v rf|dd|ddd|d< tdi |}|rz|jrzt|j|d|_|S )zH
        Transform the RunwayML video status retrieve response.
        rN   rO   rP   rQ   rR   rS   rT   rV   r   rW   rX   rY   progressrZ   r[   r\   r]   r^   ra   Nr!   )	rb   rc   rd   re   r2   rf   r   rN   r   )r   rK   rL   rM   ri   rj   rk   r!   r!   r"   (transform_video_status_retrieve_response  s(   	
&



z<RunwayMLVideoConfig.transform_video_status_retrieve_responseerror_messagestatus_codec                 C   s   ddl m} ||||d)N   r   )r   r`   r=   )Zbase_llm.chat.transformationr   )r   r   r   r=   r   r!   r!   r"   get_error_class9  s   z#RunwayMLVideoConfig.get_error_class)NNr   )NNNN)/__name__
__module____qualname____doc__r   r3   rf   r+   r   boolr   r<   dictr   r   rC   rG   r   r
   rJ   httpxResponseLiteLLMLoggingObjr   rl   rd   r5   re   r   r   r   bytesr   r   r   r   r   r   r   r   r   r   r	   ZHeadersr   r   __classcell__r!   r!   r   r"   r   !   s   	
3
#

+
H



&



	


	





*r   )'r   typingr   r   r   r   r   r   r	   r   Zhttpx._typesr
   rA   Zlitellm.constantsr   Z)litellm.llms.base_llm.chat.transformationr   Z+litellm.llms.base_llm.videos.transformationr   Z&litellm.llms.custom_httpx.http_handlerr   r   r   r   Zlitellm.secret_managers.mainr   Zlitellm.types.routerr   Zlitellm.types.videos.mainr   r   Zlitellm.types.videos.utilsr   r   Z*litellm.litellm_core_utils.litellm_loggingr   Z_LiteLLMLoggingObjr   r   r!   r!   r!   r"   <module>   s$    $