Ë
    uPêjy3  ã                   óô   — d Z ddlZddlmZmZ ddl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 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 m!Z! er	ddl"m#Z$ e$Z%neZ% G d„ de«      Z&y)a=  
OpenRouter Image Edit Support

OpenRouter provides image editing through chat completion endpoints.
The source image is sent as a base64 data URL in the message content,
and the response contains edited images in the message's images array.

Request format:
{
    "model": "google/gemini-2.5-flash-image",
    "messages": [{
        "role": "user",
        "content": [
            {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}},
            {"type": "text", "text": "Edit this image by..."}
        ]
    }],
    "modalities": ["image", "text"]
}

Response format:
{
    "choices": [{
        "message": {
            "content": "Here is the edited image.",
            "role": "assistant",
            "images": [{
                "image_url": {"url": "data:image/png;base64,..."},
                "type": "image_url"
            }]
        }
    }],
    "usage": {
        "completion_tokens": 1299,
        "prompt_tokens": 300,
        "total_tokens": 1599,
        "completion_tokens_details": {"image_tokens": 1290},
        "cost": 0.0387243
    }
}
é    N)ÚBufferedReaderÚBytesIO)ÚTYPE_CHECKINGÚAnyÚFinalÚcast)ÚRequestFiles)ÚImageEditRequestUtils)ÚBaseLLMException)ÚBaseImageEditConfig©ÚOpenRouterException)Úget_secret_str)ÚImageEditOptionalRequestParams)ÚGenericLiteLLMParams)Ú	FileTypesÚImageObjectÚImageResponseÚ
ImageUsageÚImageUsageInputTokensDetails)ÚLoggingc                   ó‚  — e Zd ZdZdedefd„Zdededede	fd„Z
	 	 	 d"d	e	ded
edz  de	dz  dedz  de	fd„Zdefd„Zdededz  de	defd„Zdededz  dedz  de	ded	e	dee	ef   fd„Zdedej(                  dedefd„Zdeded	e	ej2                  z  defd„Zdedefd„Zdededz  fd„Zdede	deddfd „Zdedefd!„Z y)#ÚOpenRouterImageEditConfiga%  
    Configuration for OpenRouter image editing via chat completions.

    OpenRouter uses the chat completions endpoint for image editing.
    The source image is sent as a base64 data URL in the message content,
    and the response contains edited images in the message's images array.
    ÚmodelÚreturnc                 ó
   — g d¢S )N)ÚsizeÚqualityÚn© )Úselfr   s     úv/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/llms/openrouter/image_edit/transformation.pyÚget_supported_openai_paramsz5OpenRouterImageEditConfig.get_supported_openai_paramsS   s   € Ú'Ð'ó    Úimage_edit_optional_paramsÚdrop_paramsc                 óJ  — | j                  |«      }i }|j                  «       D ]|  \  }}||v sŒ|dk(  r/d|vri |d<   | j                  t        t        |«      «      |d   d<   Œ?|dk(  r4| j                  t        t        |«      «      }|sŒfd|vri |d<   ||d   d<   Œx|||<   Œ~ |S )Nr   Úimage_configÚaspect_ratior   Ú
image_size)r#   ÚitemsÚ_map_size_to_aspect_ratior   ÚstrÚ_map_quality_to_image_size)	r!   r%   r   r&   Úsupported_paramsÚmapped_paramsÚkeyÚvaluer*   s	            r"   Úmap_openai_paramsz+OpenRouterImageEditConfig.map_openai_paramsV   sÑ   € ð #'×"BÑ"BÀ5Ó"IÐØ/1ˆà4×:Ñ:Ó<ò 	/‰JˆC�ØÐ&Ò&Ø˜&’=Ø%¨]Ñ:Ø8:˜ nÑ5ØDH×DbÑDbÔcgÔhkÐmrÓcsÓDt�M .Ñ1°.ÒAØ˜IÒ%Ø!%×!@Ñ!@ÄÄcÈ5ÓAQÓ!R�JÚ!Ø)°Ñ>Ø<>˜M¨.Ñ9ØFP˜ nÑ5°lÒCà).�M #Ò&ð	/ð Ðr$   NÚheadersÚapi_keyÚlitellm_paramsÚapi_basec                 óŽ   — |xs t         j                  xs t        d«      }|st        d«      ‚|j	                  dd|› �i«       |S )NÚOPENROUTER_API_KEYzOPENROUTER_API_KEY is not setÚAuthorizationzBearer )Úlitellmr5   r   Ú
ValueErrorÚupdate)r!   r4   r   r5   r6   r7   s         r"   Úvalidate_environmentz.OpenRouterImageEditConfig.validate_environmentp   sP   € ð ÒTœWŸ_™_ÒT´Ð?SÓ0TˆÙÜÐ<Ó=Ð=Ø�‰à 7¨7¨)Ð!4ðô	
ð
 ˆr$   c                  ó   — y)z7OpenRouter uses JSON requests, not multipart/form-data.Fr    )r!   s    r"   Úuse_multipart_form_dataz1OpenRouterImageEditConfig.use_multipart_form_data‚   s   € àr$   c                 óz   — |xs t        d«      xs d}|j                  d«      }|j                  d«      s|› d�S |S )NÚOPENROUTER_API_BASEzhttps://openrouter.ai/api/v1ú/z/chat/completions)r   ÚrstripÚendswith)r!   r   r7   r6   Úbase_urls        r"   Úget_complete_urlz*OpenRouterImageEditConfig.get_complete_url†   sJ   € ð Òfœ~Ð.CÓDÒfÐHfˆØ—?‘? 3Ó'ˆØ× Ñ Ð!4Ô5Ø�ZÐ0Ð1Ð1Øˆr$   ÚpromptÚimageÚ"image_edit_optional_request_paramsc           	      óÄ  — g }|�…t        |t        «      r|n|g}|D ]k  }	|	€Œt        j                  |	«      }
| j	                  |	«      }t        j                  |«      j                  d«      }|j                  ddd|
› d|› �idœ«       Œm |r|j                  d|dœ«       |d	|d
œgddgdœ}|j                  «       D ]  \  }}|dvsŒ|||<   Œ t        t        g «      }||fS )Nzutf-8Ú	image_urlÚurlúdata:z;base64,)ÚtyperL   Útext)rO   rP   Úuser)ÚroleÚcontentrI   )r   ÚmessagesÚ
modalities)Ú
isinstanceÚlistr
   Úget_image_content_typeÚ_read_image_bytesÚbase64Ú	b64encodeÚdecodeÚappendr+   r   r	   )r!   r   rH   rI   rJ   r6   r4   Úcontent_partsÚimagesÚimgÚ	mime_typeÚimage_bytesÚb64_dataÚrequest_bodyr1   r2   Úempty_filess                    r"   Útransform_image_edit_requestz6OpenRouterImageEditConfig.transform_image_edit_request’   s*  € ð 68ˆð ÐÜ%/°´tÔ%<™EÀ5À'ˆFØò �Ø�;ØÜ1×HÑHÈÓM�	Ø"×4Ñ4°SÓ9�Ü!×+Ñ+¨KÓ8×?Ñ?ÀÓH�Ø×$Ñ$à +Ø&+¨u°Y°K¸xÈÀzÐ-RÐ%Sñõðñ Ø× Ñ ¨&¸&Ñ!AÔBð ð #Ø,ñðð # FÐ+ñ	/
ˆð =×BÑBÓDò 	*‰JˆC�ØÐ=Ò=Ø$)�˜SÒ!ð	*ô "¤,°Ó3ˆØ˜[Ð(Ð(r$   Úraw_responseÚlogging_objc           	      ó  — 	 |j                  «       }t        «       }g |_        	 |j                  dg «      }|D ]Ú  }|j                  di «      }	|	j                  dg «      }
|
D ]¯  }|j                  di «      }|j                  d«      }|sŒ)|j                  d«      rO|j                  d	d
«      }t        |«      d
kD  r|d
   nd }|j                  j                  t        |d d ¬«      «       Œ‰|j                  j                  t        d |d ¬«      «       Œ± ŒÜ 	 | j                  |||«       |S # t        $ r*}t        d|› �|j                  |j                  ¬«      ‚d }~ww xY w# t        $ r}t        d|› �di ¬«      ‚d }~ww xY w)Nz#Error parsing OpenRouter response: ©ÚmessageÚstatus_coder4   Úchoicesrk   r_   rL   rM   rN   ú,é   )Úb64_jsonrM   Úrevised_promptz3Error transforming OpenRouter image edit response: iô  )ÚjsonÚ	Exceptionr   rl   r4   r   ÚdataÚgetÚ
startswithÚsplitÚlenr]   r   Ú_set_usage_and_cost)r!   r   rg   rh   Úresponse_jsonÚeÚmodel_responserm   Úchoicerk   r_   Ú
image_dataÚimage_url_objrL   Úpartsrc   s                   r"   Útransform_image_edit_responsez7OpenRouterImageEditConfig.transform_image_edit_responseÄ   s£  € ð	Ø#/×#4Ñ#4Ó#6ˆMô !.£ˆØ ˆÔð&	Ø*×.Ñ.¨y¸"Ó=ˆGà!ò �Ø Ÿ*™* Y°Ó3�Ø Ÿ™ X¨rÓ2�à"(ò �JØ$.§N¡N°;ÀÓ$C�MØ -× 1Ñ 1°%Ó 8�Iâ Ø$×/Ñ/°Ô8à$-§O¡O°C¸Ó$;˜EÜ36°u³:À²> u¨Q¢xÀt˜Hà*×/Ñ/×6Ñ6Ü +Ø-5Ø(,Ø37ô!"õð +×/Ñ/×6Ñ6Ü +Ø-1Ø(1Ø37ô!"õñ%ñ	ðJ 	× Ñ  °ÀÔFØÐøôg ò 	Ü%Ø=¸a¸SÐAØ(×4Ñ4Ø$×,Ñ,ôð ûð	ûôV ò 	Ü%ØMÈaÈSÐQØØôð ûð	ús6   ‚D+ ¤A%E! Â
BE! Ä+	EÄ4%EÅEÅ!	F Å*E;Å;F Úerror_messagerl   c                 ó   — t        |||¬«      S )Nrj   r   )r!   r‚   rl   r4   s       r"   Úget_error_classz)OpenRouterImageEditConfig.get_error_class  s   € Ü"Ø!Ø#Øô
ð 	
r$   r   c           	      ó<   — dddddddddœ}|j                  |d«      S )zÐ
        Map OpenAI size format to OpenRouter aspect_ratio format.

        Uses the same mapping as image generation since OpenRouter
        handles both through the same chat completions endpoint.
        z1:1z3:2z16:9z2:3z9:16)Ú256x256Ú512x512Ú	1024x1024Ú	1536x1024Ú	1792x1024Ú	1024x1536Ú	1024x1792Úauto©ru   )r!   r   Úsize_to_aspect_ratios      r"   r,   z3OpenRouterImageEditConfig._map_size_to_aspect_ratio
  s9   € ð ØØØØØØØñ	'
Ðð $×'Ñ'¨¨eÓ4Ð4r$   r   c                 ó6   — dddddddœ}|j                  |«      S )zÊ
        Map OpenAI quality to OpenRouter image_size format.

        Uses the same mapping as image generation since OpenRouter
        handles both through the same chat completions endpoint.
        Ú1KÚ2KÚ4K)ÚlowÚstandardÚmediumÚhighÚhdr�   rŽ   )r!   r   Úquality_to_image_sizes      r"   r.   z4OpenRouterImageEditConfig._map_quality_to_image_size  s1   € ð ØØØØØñ(
Ðð %×(Ñ(¨Ó1Ð1r$   r|   rz   c                 óê  — |j                  di «      }|�r?|j                  dd«      }|j                  dd«      }|j                  di «      }|j                  dd«      }d}	|j                  di «      }
|
r|
j                  dd«      }	t        |t        |	||	z
  ¬«      ||¬	«      |_        |j                  d
«      }|�Kt	        |d«      si |_        d|j
                  vri |j
                  d<   t        |«      |j
                  d   d<   |j                  di «      }|r;d|j
                  vri |j
                  d<   |j
                  d   j                  |«       |j                  d|«      |j
                  d<   y)zDExtract and set usage and cost information from OpenRouter response.ÚusageÚprompt_tokensr   Útotal_tokensÚcompletion_tokens_detailsÚimage_tokensÚprompt_tokens_details)rŸ   Útext_tokens)Úinput_tokensÚinput_tokens_detailsÚoutput_tokensr�   ÚcostNÚ_hidden_paramsÚadditional_headersz$llm_provider-x-litellm-response-costÚcost_detailsÚresponse_cost_detailsr   )ru   r   r   r›   Úhasattrr¦   Úfloatr=   )r!   r|   rz   r   Ú
usage_datarœ   r�   rž   rŸ   Úinput_image_tokensr    r¥   r¨   s                r"   ry   z-OpenRouterImageEditConfig._set_usage_and_cost.  s�  € ð *×-Ñ-¨g°rÓ:ˆ
ÚØ#-§>¡>°/À1Ó#EˆMØ",§.¡.°ÀÓ"CˆLà/9¯~©~Ð>YÐ[]Ó/^Ð%Ø";×"?Ñ"?ÀÐPQÓ"RˆLð "#ÐØ+5¯>©>Ð:QÐSUÓ+VÐ!Ù$Ø%:×%>Ñ%>¸~ÈqÓ%QÐ"ä#-Ø*Ü%AØ!3Ø -Ð0BÑ Bô&ð +Ø)ô$ˆNÔ ð %Ÿ.™.¨Ó0ˆDØÐÜ˜~Ð/?Ô@Ø46�NÔ1Ø'¨~×/LÑ/LÑLØJL�N×1Ñ1Ð2FÑGÜnsØóo�×-Ñ-Ð.BÑCÐDjÑkð #-§.¡.°ÀÓ"DˆLÙØ*°.×2OÑ2OÑOØMO�N×1Ñ1Ð2IÑJØ×-Ñ-Ð.EÑF×MÑMÈlÔ[à1>×1BÑ1BÀ7ÈEÓ1Rˆ×%Ñ% gÒ.r$   c                 óŒ  — t        |t        «      r|S t        |t        «      rD|j                  «       }|j	                  d«       |j                  «       }|j	                  |«       |S t        |t        «      rD|j                  «       }|j	                  d«       |j                  «       }|j	                  |«       |S t        d«      ‚)z.Read raw bytes from various image input types.r   z1Unsupported image type for OpenRouter image edit.)rV   Úbytesr   ÚtellÚseekÚreadr   r<   )r!   rI   Úcurrent_posrt   s       r"   rY   z+OpenRouterImageEditConfig._read_image_bytes_  s•   € ä�eœUÔ#ØˆLÜ�eœWÔ%ØŸ*™*›,ˆKØ�J‰J�qŒMØ—:‘:“<ˆDØ�J‰J�{Ô#ØˆKÜ�eœ^Ô,ØŸ*™*›,ˆKØ�J‰J�qŒMØ—:‘:“<ˆDØ�J‰J�{Ô#ØˆKÜÐLÓMÐMr$   )NNN)!Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   rW   r#   r   ÚboolÚdictr3   r>   r@   rG   r   r   Útupler	   rf   ÚhttpxÚResponseÚLiteLLMLoggingObjr   r�   ÚintÚHeadersr   r„   r,   r.   ry   r¯   rY   r    r$   r"   r   r   J   s  „ ñð(°ð (¸ó (ðà$Bðð ðð ð	ð
 
óð< #Ø&*Ø#ñàðð ðð �t‘ð	ð
 ˜t™ðð ˜‘*ðð 
óð$¨ó ð
àð
ð ˜‘*ð
ð ð	
ð
 
ó
ð0)àð0)ð �d‘
ð0)ð ˜4Ñð	0)ð
 -1ð0)ð -ð0)ð ð0)ð 
ˆt�\Ð!Ñ	"ó0)ðd;àð;ð —n‘nð;ð 'ð	;ð
 
ó;ðz
¨Sð 
¸sð 
ÈTÐTY×TaÑTaÑMað 
Ðfvó 
ð5¨cð 5°có 5ð&2°#ð 2¸#À¹*ó 2ð"/Sà%ð/Sð ð/Sð ð	/Sð
 
ó/SðbN yð N°Uô Nr$   r   )'r·   rZ   Úior   r   Útypingr   r   r   r   r»   Úhttpx._typesr	   r;   Úlitellm.images.utilsr
   Ú)litellm.llms.base_llm.chat.transformationr   Ú/litellm.llms.base_llm.image_edit.transformationr   Ú$litellm.llms.openrouter.common_utilsr   Úlitellm.secret_managers.mainr   Úlitellm.types.images.mainr   Úlitellm.types.routerr   Úlitellm.types.utilsr   r   r   r   r   Ú*litellm.litellm_core_utils.litellm_loggingr   Ú_LiteLLMLoggingObjr½   r   r    r$   r"   ú<module>rÍ      sf   ðñ(óT ß &ß 2Ó 2ã Ý %ã Ý 6Ý FÝ OÝ DÝ 7Ý DÝ 5÷õ ñ ÝXà*ÑàÐôeNÐ 3õ eNr$   