§
    ã{›j¸1  ã                  óh   — d dl mZ d dlZd dlmZ d dlZ ej        d¦  «        Z G d„ d¦  «        ZdS )é    )ÚannotationsN)ÚAnyzdscons.llm.openaic                  ó8   — e Zd ZdZdd„Zdd	„Zd
dd
d
d
dœdd„Zd
S )ÚOpenAiBackendMixinzAOpenAI-compatible inference backend mixin (Ollama/vLLM/DeepSeek).Ú
agent_codeú
str | NoneÚreturnúdict[str, Any]c                óN  — d}|rY	 ddl m}  |¦   «         }|                     |¦  «        }n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY w|rw|                     d¦  «        rb|                     dd¦  «        }|                     dd	¦  «        }t                               d
||                     d¦  «        ||¦  «         |}|}	n�t          | j	        di ¦  «        }
|r|                     d¦  «        ndp|
                     |pdd	¦  «        }t          | j	        di ¦  «        }|r|                     d¦  «        ndp|r|                     |¦  «        nd}	|r|                     d¦  «        ndpd}|r|                     d¦  «        ndp| j
        }|dk    rpt          | j	        dd¦  «        rZt          | j	        dd¦  «                             d¦  «        t          | j	        dd¦  «        |	pt          | j	        dd¦  «        d||dœS |d	k    r¨t          | j	        dd¦  «        r’t          | j	        dd ¦  «        r||	pt          | j	        d!d"¦  «        }|                     d#¦  «        rd$|› �}|d%v rd&}t          | j	        d'd(¦  «                             d¦  «        t          | j	        dd ¦  «        |d	||dœS |d)k    ržt          | j	        d*d ¦  «        rˆt          | j	        d+d,¦  «                             d¦  «        t          | j	        d*d ¦  «        |	r,|	                     d-¦  «        s|	                     d.¦  «        s|	nt          | j	        d/d0¦  «        d)||pd1dœS |d2v r\ddl}|	pt          | j	        d/d0¦  «        }|d3v rd0}d t          | j	        d*d ¦  «        p|j                             d4d ¦  «        |d5||pd1dœS |	p| j        pd"}d	| j                             ¦   «         v r |                     d#¦  «        rd$|› �}|d%v rd&}| j        | j        || j        ||dœS )6z^Resolve base_url, api_key, model, temperature, and max_tokens for a specific AI agent/persona.Nr   )ÚErpDatabaseClientu4   KhÃ´ng thá»ƒ Ä‘á»�c cáº¥u hÃ¬nh AI Agent tá»« DB: %sÚ
is_expiredÚfallback_model_nameúanthropic/claude-opus-4.8Úfallback_providerÚ
openrouteruq   [STEALTH EXPIRED] Agent %s: Model '%s' Ä‘Ã£ háº¿t háº¡n Æ°u Ä‘Ã£i. Tá»± Ä‘á»™ng chuyá»ƒn vá»� Fallback '%s' (%s).Ú
model_nameÚagent_provider_routingÚproviderÚdefaultÚagent_model_routingÚtemperatureçš™™™™™É?Ú
max_tokensÚlmstudioÚlmstudio_enabledTÚlmstudio_base_urlzhttp://127.0.0.1:1234/v1ú/Úlmstudio_api_keyz	lm-studioÚlmstudio_model_namezlfm2.5-2.6b)Úbase_urlÚapi_keyÚmodelr   r   r   Úopenrouter_enabledÚopenrouter_api_keyÚ Úopenrouter_model_namezstealth/ox-alphazgemini-zgoogle/)zgoogle/gemini-3.1-proúgemini-3.1-proúgoogle/gemini-3.8-flashÚopenrouter_base_urlzhttps://openrouter.ai/api/v1ÚgeminiÚgemini_api_keyÚgemini_base_urlz7https://generativelanguage.googleapis.com/v1beta/openaizliquid/zstealth/Úgemini_model_namezgemini-3.8-flashi   )ÚantigravityÚantigravity_sdk)r'   zgemini-2.5-flashÚGEMINI_API_KEYr.   )Úapp.core.postgres.erp_clientr   Úget_ai_agent_modelÚ	ExceptionÚloggerÚdebugÚgetÚwarningÚgetattrÚ	_settingsÚ_default_max_tokensÚrstripÚ
startswithÚosÚenvironÚ_model_pathÚ_api_base_urlÚlowerÚ_api_keyÚ_active_provider)Úselfr   Ú	db_configr   ÚclientÚeÚfallback_modelÚfallback_provÚprovider_keyÚmodel_overrideÚroutingÚmodel_routingr   r   Úclean_modelr=   s                   úGC:\Projects\DSCons\app\modules\agents\application\llm\openai_backend.pyÚget_provider_for_agentz)OpenAiBackendMixin.get_provider_for_agent   sj  € àˆ	Øð 	XðXØJÐJÐJÐJÐJÐJà*Ð*Ñ,Ô,�Ø"×5Ò5°jÑAÔA�	�	øÝð Xð Xð XÝ—’ÐSÐUVÑWÔWÐWÐWÐWÐWÐWÐWøøøøðXøøøð ð 	˜Ÿš |Ñ4Ô4ð 	Ø&Ÿ]š]Ø%Ð'Bñô ˆNð &ŸMšMÐ*=¸|ÑLÔLˆMÝ�NŠNð DØØ—’˜lÑ+Ô+ØØñô ð ð )ˆLØ+ˆNˆNå˜dœnÐ.FÈÑKÔKˆGà-6Ð@�	—’˜jÑ)Ô)Ð)¸DðDà—’˜ZÐ4¨9°lÑCÔCð õ $ D¤NÐ4IÈ2ÑNÔNˆMØ=FÐP˜iŸmšm¨LÑ9Ô9Ð9ÈDð Ø1;ÐE�×!Ò! *Ñ-Ô-Ð-Àð ð 8AÐJ�y—}’} ]Ñ3Ô3Ð3ÀdÐSÈtˆà+4Ð>ˆI�MŠM˜,Ñ'Ô'Ð'¸$ð&àÔ%ð 	ð ˜:Ò%Ð%­'ØŒNÐ.°ñ+
ô +
Ð%õ $Ø”NÐ$7Ð9Sñô ç’&˜‘+”+Ý" 4¤>Ð3EÀ{ÑSÔSØ'ð QÝ˜4œ>Ð+@À-ÑPÔPØ&Ø*Ø(ð
ð 
ð 
ð ˜LÒ(Ð(Ý˜œÐ(<¸dÑCÔCð )å˜œÐ(<¸bÑAÔAð )ð )Ðp­G°D´NÐD[Ð]oÑ,pÔ,pˆKØ×%Ò% iÑ0Ô0ð 6Ø5¨Ð5Ð5�ØÐIÐIÐIØ7�õ $Ø”NØ)Ø2ñô ÷ ’&˜‘+”+Ý" 4¤>Ð3GÈÑLÔLØ$Ø(Ø*Ø(ðð ð ð ˜HÒ$Ð$Ý�d”nÐ&6¸Ñ;Ô;ð %õ $Ø”NØ%ØMñô ÷ ’&˜‘+”+Ý" 4¤>Ð3CÀRÑHÔHð #ðVð +×5Ò5°iÑ@Ô@ðVð +×5Ò5°jÑAÔAð	V˜˜õ ˜Tœ^Ð-@ÐBTÑUÔUØ$Ø*Ø(Ð0¨Dð!ð ð ð$ Ð?Ð?Ð?ØˆIˆIˆIØ(Ðl­G°D´NÐDWÐYkÑ,lÔ,lˆKØÐDÐDÐDØ0�àÝ" 4¤>Ð3CÀRÑHÔHÐpÈBÌJÏNÊNÐ[kÐmoÑLpÔLpØ$Ø)Ø*Ø(Ð0¨Dðð ð ð (ÐQ¨4Ô+;ÐQÐ?QˆØ˜4Ô-×3Ò3Ñ5Ô5Ð5Ð5Ø×(Ò(¨Ñ3Ô3ð <Ø!;¨>Ð!;Ð!;�ØÐ!LÐLÐLØ!:�ð Ô*Ø”}Ø#ØÔ-Ø&Ø$ð
ð 
ð 	
s   †%, ¬
A¶AÁAÚmessagesúlist[dict[str, Any]]c           
     ó¤  — g }|D �]I}|                      d¦  «        }t          |t          ¦  «        �rg }|D ]À}t          |t          ¦  «        r|                      d¦  «        dk    r7|                     t          |                      dd¦  «        ¦  «        ¦  «         Œg|                      d¦  «        dk    r|                     d¦  «         Œ–t          |t
          ¦  «        r|                     |¦  «         ŒÁ|                     |                      dd¦  «        d	                     |¦  «        d
œ¦  «         �Œ4|                     |¦  «         �ŒK|S )zRStrip image_url blocks and convert multimodal messages to text-only for text LLMs.ÚcontentÚtypeÚtextr%   Ú	image_urluF   [HÃ¬nh áº£nh báº£n váº½ ká»¹ thuáº­t CAD / PDF thiáº¿t káº¿ thi cÃ´ng]ÚroleÚuserú
)rX   rT   )r6   Ú
isinstanceÚlistÚdictÚappendÚstrÚjoin)rD   rQ   Úclean_messagesÚmsgÚcÚ
text_partsÚparts          rO   Ú_strip_multimodal_contentz,OpenAiBackendMixin._strip_multimodal_content’   sb  € ð 02ˆØð 	+ñ 	+ˆCØ—’˜	Ñ"Ô"ˆAÝ˜!�TÑ"Ô"ñ +Ø(*�
Øð 	0ð 	0�DÝ! $­Ñ-Ô-ð 0ØŸ8š8 FÑ+Ô+¨vÒ5Ð5Ø&×-Ò-­c°$·(²(¸6À2Ñ2FÔ2FÑ.GÔ.GÑHÔHÐHÐHØ!ŸXšX fÑ-Ô-°Ò<Ð<Ø&×-Ò-Ø hñô ð øõ $ D­#Ñ.Ô.ð 0Ø"×)Ò)¨$Ñ/Ô/Ð/øØ×%Ò%Ø ŸWšW V¨VÑ4Ô4ÀÇÂÈ:ÑAVÔAVÐWÐWñô ð ñ ð ×%Ò% cÑ*Ô*Ð*Ñ*ØÐó    Nr   )r"   r   r   Ú
extra_bodyr   r"   r   Úfloatr   ú
int | Nonerh   údict[str, Any] | Nonec          	   ƒ  ób  K  — |                       |¦  «        }|d         }|d         }	|p|d         }
|› d�}|
||dk    r|n|                     dd¦  «        |p|                     d| j        ¦  «        dœ}|r|                     |¦  «         d	|	› �d
ddœ}dd„}t	          j        | j        ¬¦  «        4 ƒd{V —†}	 |                     |||¬¦  «        ƒ d{V —†}|                     ¦   «           || 	                    ¦   «         ¦  «        cddd¦  «        ƒd{V —† S # t          $ �rô}t          d„ |D ¦   «         ¦  «        }|rÛg d¢}|D ]Ô}||
k    rŒ		 t                               d|¦  «         t          |¦  «        }||d<   |                     |||d¬¦  «        ƒ d{V —†}|                     ¦   «           || 	                    ¦   «         ¦  «        c cY d}~cddd¦  «        ƒd{V —† S # t          $ r&}t                               d||¦  «         Y d}~ŒÍd}~ww xY wg d¢}|                      |¦  «        }|D ]Û}||
k    rŒ		 t                               d|
||¦  «         t          |¦  «        }||d<   ||d<   |                     |||d¬¦  «        ƒ d{V —†}|                     ¦   «           || 	                    ¦   «         ¦  «        c cY d}~cddd¦  «        ƒd{V —† S # t          $ r&}t                               d||¦  «         Y d}~ŒÔd}~ww xY w|‚d}~ww xY w# 1 ƒd{V —†swxY w Y   dS )zCCall OpenAI-compatible HTTP API with per-agent provider resolution.r    r!   r"   z/chat/completionsr   r   r   )r"   rQ   r   r   zBearer zhttps://github.com/dsconszDSCons Operations)ÚAuthorizationzHTTP-RefererzX-TitleÚdatar
   r	   c                ó–  — d| v rÄt          | d         ¦  «        dk    r«| d         d                              di ¦  «        }|                     d¦  «        st|                     d¦  «        r|d         |d<   nS|                     d¦  «        r>t          |d         ¦  «        dk    r%|d         d                              dd¦  «        |d<   | S )	NÚchoicesr   ÚmessagerT   Ú	reasoningÚreasoning_detailsrV   r%   )Úlenr6   )rn   rb   s     rO   Ú_normalize_respzGOpenAiBackendMixin._generate_openai_compatible.<locals>._normalize_respÏ   sÔ   € Ø˜DÐ Ð ¥S¨¨i¬Ñ%9Ô%9¸AÒ%=Ð%=Ø˜9”o aÔ(×,Ò,¨Y¸Ñ;Ô;�Ø—w’w˜yÑ)Ô)ð UØ—w’w˜{Ñ+Ô+ð UØ),¨[Ô)9˜˜I™˜àŸšÐ 3Ñ4Ô4ðUå Ð$7Ô 8Ñ9Ô9¸AÒ=Ð=à),Ð-@Ô)AÀ!Ô)D×)HÒ)HÈÐQSÑ)TÔ)T˜˜I™ØˆKrg   )ÚtimeoutN)ÚjsonÚheadersc              3  óf   K  — | ],}t          |                     d ¦  «        t          ¦  «        V — Œ-dS )rT   N)r[   r6   r\   )Ú.0Úms     rO   ú	<genexpr>zAOpenAiBackendMixin._generate_openai_compatible.<locals>.<genexpr>â   s8   è è € Ð VÐ VÈ¥¨A¯EªE°)Ñ,<Ô,<½dÑ!CÔ!CÐ VÐ VÐ VÐ VÐ VÐ Vrg   )r   r   úgoogle/gemini-3.1-pro-previewz/[LLM_CLIENT] Thu lai voi model thi giac '%s'...g      N@)rw   rx   rv   z,[LLM_CLIENT] Vision fallback '%s' failed: %s)r(   r   zanthropic/claude-fable-5r}   zCPrimary model '%s' failed (%s). Retrying with text fallback '%s'...rQ   z#Fallback text model '%s' failed: %s)rn   r
   r	   r
   )rP   r6   r:   ÚupdateÚhttpxÚAsyncClientÚ_timeoutÚpostÚraise_for_statusrw   r3   Úanyr4   Úinfor]   r5   rf   r7   )rD   rQ   r"   r   r   rh   r   Úprovider_infor    r!   Úeffective_modelÚurlÚpayloadrx   ru   rF   ÚresponseÚprimary_errÚ
has_imagesÚvision_fallbacksÚ
fb_v_modelÚ
fb_payloadÚfb_resÚfb_errÚtext_fallbacksÚ
clean_msgsÚfb_modelÚfallback_payloads                               rO   Ú_generate_openai_compatiblez.OpenAiBackendMixin._generate_openai_compatible¬   sÙ  è è € ð ×3Ò3°JÑ?Ô?ˆØ  Ô,ˆØ 	Ô*ˆØÐ9 =°Ô#9ˆàÐ,Ð,Ð,ˆà$Ø à˜cÒ!Ð!ð '˜;à×"Ò" =°#Ñ6Ô6Ø$ð IØ× Ò  ¨tÔ/GÑHÔHð
ð 
ˆð ð 	'Ø�NŠN˜:Ñ&Ô&Ð&ð 1 wÐ0Ð0Ø7Ø*ð
ð 
ˆð	ð 	ð 	ð 	õ Ô$¨T¬]Ð;Ñ;Ô;ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"¸vð?"Ø!'§¢¨S°wÈ Ñ!PÔ!PÐPÐPÐPÐPÐPÐP�Ø×)Ò)Ñ+Ô+Ð+Ø&� x§}¢}¡¤Ñ7Ô7ð	@	"ð @	"ð @	"ð @	"ñ @	"ô @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"øõ
 ð ;"ñ ;"ð ;"Ý Ð VÐ VÈXÐ VÑ VÔ VÑVÔV�
Øð ð(ð (ð (Ð$ð
 '7ð ð ˜
Ø%¨Ò8Ð8Ø$ðÝ"ŸKšKØ QØ *ñô ð õ *.¨g©¬˜JØ2<˜J wÑ/Ø+1¯;ª;Ø #¨*¸gÈtð ,7ñ ,ô ,ð &ð &ð &ð &ð &ð &˜Fð #×3Ò3Ñ5Ô5Ð5Ø#2 ?°6·;²;±=´=Ñ#AÔ#AÐAÐAÐAÐAÐAÐAÐAð7@	"ð @	"ð @	"ð @	"ñ @	"ô @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"øõ8  )ð ð ð Ý"ŸLšLØ NØ *Ø &ñô ð ð ð ð ð ð øøøøðøøøð"ð "ð "�ð "×;Ò;¸HÑEÔE�
Ø .ð ð �HØ ?Ò2Ð2Ø ðÝŸšØaØ+Ø'Ø$ñ	ô ð õ ,0°©=¬=Ð(Ø4<Ð(¨Ñ1Ø7AÐ(¨Ñ4Ø'-§{¢{ØÐ&6ÀÐQUð (3ñ (ô (ð "ð "ð "ð "ð "ð "˜ð ×/Ò/Ñ1Ô1Ð1Ø.˜¨v¯{ª{©}¬}Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=Ð=ðw@	"ð @	"ð @	"ð @	"ñ @	"ô @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"øõx %ð ð ð ÝŸšØAÀ8ÈVñô ð ð ð ð ð ð øøøøðøøøð "Ð!øøøøðw;"øøøð@	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"ð @	"øøøð @	"ð @	"ð @	"ð @	"ð @	"ð @	"sŸ   Â9LÂ;ADÄLÄ'*LÅA>G*ÇLÇLÇLÇ*
H	Ç4H	ÈLÈH	È'LÉBK!ËLË	LË
LË!
L	Ë+L	ÌLÌL	ÌLÌLÌLÌ
L(Ì+L()r   r   r	   r
   )rQ   rR   r	   rR   )rQ   rR   r"   r   r   ri   r   rj   rh   rk   r   r   r	   r
   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rP   rf   r–   © rg   rO   r   r      s~   € € € € € ØKÐKðB
ð B
ð B
ð B
ðHð ð ð ð< !Ø Ø!%Ø,0Ø!%ðp"ð p"ð p"ð p"ð p"ð p"ð p"ð p"rg   r   )	Ú
__future__r   ÚloggingÚtypingr   r   Ú	getLoggerr4   r   r›   rg   rO   ú<module>r       sŠ   ðØ "Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ð Ð à €€€à	ˆÔ	Ð.Ñ	/Ô	/€ðQ"ð Q"ð Q"ð Q"ð Q"ñ Q"ô Q"ð Q"ð Q"ð Q"rg   