o
    ưi4                     @   s   d Z ddlZddlmZmZmZ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 ddlmZ dd	lmZmZmZmZmZ dd
lmZ ddlmZ G dd deeZdS )zv
Supports writing files to Google AI Studio Files API.

For vertex ai, check out the vertex_ai/files/handler.py file.
    N)AnyListLiteralOptional)FileDeleted)verbose_logger)extract_file_data)BaseFilesConfigLiteLLMLoggingObj)GeminiCreateFilesResponseObject)AllMessageValuesCreateFileRequestHttpxBinaryResponseContent%OpenAICreateFileRequestOptionalParamsOpenAIFileObject)LlmProviders   )GeminiModelInfoc                   @   s*  e Zd Zdd ZedefddZ		d2deeef de	d	e
e d
eeef deeef dee	 dee	 deeef fddZ	d3dee	 dee	 de	d
ededee de	fddZde	de
e fddZded
ede	dedef
ddZde	ded
ededef
ddZdee	 dejdededef
ddZd e	d
ededee	ef fd!d"Zdejdededefd#d$Zd e	d
ededee	ef fd%d&Zdejdededefd'd(Zd)ee	 d
ededee	ef fd*d+Z dejdedede
e fd,d-Z!d
ededee	ef fd.d/Z"dejdedede#fd0d1Z$dS )4GoogleAIStudioFilesHandlerc                 C   s   d S N selfr   r   _/home/app/Keep/.python/lib/python3.10/site-packages/litellm/llms/gemini/files/transformation.py__init__    s   z#GoogleAIStudioFilesHandler.__init__returnc                 C   s   t jS r   )r   ZGEMINIr   r   r   r   custom_llm_provider#   s   z.GoogleAIStudioFilesHandler.custom_llm_providerNheadersmodelmessagesoptional_paramslitellm_paramsapi_keyapi_basec           	      C   s"   |  |}|std||d< |S )z
        Validate environment and add Gemini API key to headers.
        Google AI Studio uses x-goog-api-key header for authentication.
        z?GEMINI_API_KEY is required for Google AI Studio file operationszx-goog-api-key)get_api_key
ValueError)	r   r   r   r   r    r!   r"   r#   Zresolved_api_keyr   r   r   validate_environment'   s
   
z/GoogleAIStudioFilesHandler.validate_environmentstreamc           
      C   sN   d}|  |}|std|p|dp|  }|stdd|||}	|	S )z{
        OPTIONAL

        Get the complete url for the request

        Some providers need `model` in `api_base`
        zupload/v1beta/filesapi_base is requiredr"   api_key is requiredz{}/{}?key={})get_api_baser%   getr$   format)
r   r#   r"   r   r    r!   r'   ZendpointZfinal_api_keyurlr   r   r   get_complete_url<   s   
z+GoogleAIStudioFilesHandler.get_complete_urlc                 C   s   g S r   r   )r   r   r   r   r   get_supported_openai_paramsY   s   z6GoogleAIStudioFilesHandler.get_supported_openai_paramsnon_default_paramsdrop_paramsc                 C   s   |S r   r   )r   r0   r    r   r1   r   r   r   map_openai_params^   s   z,GoogleAIStudioFilesHandler.map_openai_paramscreate_file_datac                 C   s   | d}|du rtdt|}t|d }ddt||d dd	}||d
  dd|d p7ttt ii}	t|ddd}
||	d|
|d ddS )z
        Transform the OpenAI-style file creation request into Gemini's format

        Returns:
            dict: Contains both request data and headers for the two-step upload
        fileNzFile data is requiredcontentZ	resumablestartcontent_typezapplication/json)zX-Goog-Upload-ProtocolX-Goog-Upload-Commandz#X-Goog-Upload-Header-Content-Lengthz!X-Goog-Upload-Header-Content-TypezContent-Typer   Zdisplay_namefilename0zupload, finalize)zContent-LengthzX-Goog-Upload-Offsetr8   )r   data)Zinitial_requestZupload_request)r+   r%   r   lenstrupdateinttime)r   r   r3   r    r!   Z	file_dataZextracted_data	file_sizer   Zinitial_dataZupload_headersr   r   r   transform_create_file_requestg   s2   
z8GoogleAIStudioFilesHandler.transform_create_file_requestraw_responselogging_objc                 C   s   z3|  }tdi |di }t|d t|d ttt|d ddd|d dd	d
ddW S  t	yR } zt
dt|  tdt| d}~ww )zV
        Transform Gemini's file upload response into OpenAI-style FileObject
        r4   uri	sizeBytes
createTimeZ+00:00%Y-%m-%dT%H:%M:%S.%f%zdisplayName	user_datauploadedNidbytesZ
created_atr9   objectpurposestatusZstatus_detailsz$Error parsing file upload response: r   )jsonr   r+   r   r?   r@   mktimestrptimereplace	Exceptionr   	exceptionr=   r%   )r   r   rC   rD   r!   response_jsonZresponse_objecter   r   r   transform_create_file_response   s:   

z9GoogleAIStudioFilesHandler.transform_create_file_responsefile_idc                 C   sp   | dp|  }|std|drd||}|i fS | | dp'd}|d}d|||}|i fS )	z
        Get the URL to retrieve a file from Google AI Studio.
        
        We expect file_id to be the URI (e.g. https://generativelanguage.googleapis.com/v1beta/files/...)
        as returned by the upload response.
        r"   r)   httpz	{}?key={}r#   z)https://generativelanguage.googleapis.com/z{}/v1beta/{}?key={})r+   r$   r%   
startswithr,   r*   rstrip)r   r]   r    r!   r"   r-   r#   r   r   r   transform_retrieve_file_request   s   

z:GoogleAIStudioFilesHandler.transform_retrieve_file_requestc                 C   s   zS|  }|dd}|dkrd}n	|dkrd}nd}t|dd	t|d
dttt|d ddd|dd	dd||dkrOt|dd	dW S ddW S  t	yr } zt
dt|  tdt| d}~ww )zY
        Transform Gemini's file retrieval response into OpenAI-style FileObject
        stateZSTATE_UNSPECIFIEDZACTIVE	processedZFAILEDerrorrM   rE    rF   r   rG   rH   rI   rJ   rK   r4   rL   NrN   z&Error parsing file retrieve response: )rT   r+   r   r?   r@   rU   rV   rW   r=   rX   r   rY   r%   )r   rC   rD   r!   rZ   Zgemini_staterS   r[   r   r   r    transform_retrieve_file_response   s@   	

z;GoogleAIStudioFilesHandler.transform_retrieve_file_responsec           	      C   s   |  |d}|std|dp|  }|std|dr*|dd }n|dr1|nd| }| d| }i }||fS )	au  
        Transform delete file request for Google AI Studio.
        
        Args:
            file_id: The file URI (e.g., "files/abc123" or full URI)
            optional_params: Optional parameters
            litellm_params: LiteLLM parameters containing api_key
            
        Returns:
            tuple[str, dict]: (url, params) for the DELETE request
        r#   r(   r"   r)   r^   z/v1beta/files/)r*   r+   r%   r$   r`   split)	r   r]   r    r!   r#   r"   	file_namer-   paramsr   r   r   transform_delete_file_request  s   
z8GoogleAIStudioFilesHandler.transform_delete_file_requestc              
   C   s   z?|j dkr8d}t|dr0|jr0t|jj}d|v r0|dd dd }|ds0d| }t|d	d
dW S td|j	  t
y^ } ztdt|  tdt| d}~ww )z
        Transform Gemini's file delete response into OpenAI-style FileDeleted.
        
        Google AI Studio returns an empty JSON object {} on successful deletion.
           deletedrequestz/files/rh   ?r   ri   Tr4   )rO   ro   rQ   zFailed to delete file: z$Error parsing file delete response: N)status_codehasattrrp   r=   r-   rj   r`   r   r%   textrX   r   rY   )r   rC   rD   r!   r]   r-   r[   r   r   r   transform_delete_file_response9  s(   


z9GoogleAIStudioFilesHandler.transform_delete_file_responserR   c                 C      t dNz8GoogleAIStudioFilesHandler does not support file listingNotImplementedError)r   rR   r    r!   r   r   r   transform_list_files_request\     z7GoogleAIStudioFilesHandler.transform_list_files_requestc                 C   rv   rw   rx   r   rC   rD   r!   r   r   r   transform_list_files_responsed  r{   z8GoogleAIStudioFilesHandler.transform_list_files_responsec                 C   rv   NzBGoogleAIStudioFilesHandler does not support file content retrievalrx   )r   Zfile_content_requestr    r!   r   r   r   transform_file_content_requestl  r{   z9GoogleAIStudioFilesHandler.transform_file_content_requestc                 C   rv   r~   rx   r|   r   r   r   transform_file_content_responset  r{   z:GoogleAIStudioFilesHandler.transform_file_content_response)NNr   )%__name__
__module____qualname__r   propertyr   r   dictr   r=   r   r   r   r&   boolr.   r   r/   r2   r   rB   httpxResponser
   r   r\   tuplerb   rg   rm   r   ru   rz   r}   r   r   r   r   r   r   r   r      s&   




	



	
8
*


+

*
#




r   )__doc__r@   typingr   r   r   r   r   Zopenai.types.file_deletedr   Zlitellm._loggingr   Z8litellm.litellm_core_utils.prompt_templates.common_utilsr   Z*litellm.llms.base_llm.files.transformationr	   r
   Zlitellm.types.llms.geminir   Zlitellm.types.llms.openair   r   r   r   r   Zlitellm.types.utilsr   Zcommon_utilsr   r   r   r   r   r   <module>   s    