Ë
    âß²j:  ã                  ó®  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m	Z	m
Z
 ddlmZmZmZmZmZ ddlmZmZmZmZmZmZmZ erddlmZ  ej6                  d«      Zd	Zed
œd"d„Zd#d„Zd$d„Z 	 	 	 	 	 	 	 	 	 	 	 	 d%d„Z!d&d„Z"d'd„Z#d(d„Z$	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d)d„Z%d*d„Z&ddddœd+d„Z'dddœd,d„Z(d-d„Z)d.d„Z*d/d„Z+eddœ	 	 	 	 	 d0d „Z,d1d!„Z-y)2zêMiniMax OAuth (user-code grant) login, refresh and runtime credentials.

Split out of ``hermes_cli/auth.py``; origin helpers are imported lazily per function so
``hermes_cli.auth.<helper>`` patches still intercept and no cycle forms.
é    )ÚannotationsN)ÚdatetimeÚtimezone)ÚAnyÚCallableÚDictÚOptionalÚTYPE_CHECKING)Ú	AuthErrorÚMINIMAX_OAUTH_GRANT_TYPEÚ"MINIMAX_OAUTH_REFRESH_SKEW_SECONDSÚMINIMAX_OAUTH_SCOPEÚ_FORM_JSON_HEADERSÚ_minimax_errÚhttpx)ÚProviderConfigzhermes_cli.authi @  )Úlimitc               ó*  — t        dt        |«      «      }	 t        | dd«      r4| j                  }|d| t	        |«      |kD  rdndz   | j                  «        S g }d}| j                  «       D ]7  }|sŒ|j                  |d|dz   |z
   «       |t	        |d   «      z  }||kD  sŒ7 n d	j                  |«      }|d| j                  | j                  xs d
d¬«      }|t	        |«      |kD  rdndz   | j                  «        S # | j                  «        w xY w)zCReturn a bounded error body from a streamed MiniMax OAuth response.r   Úis_stream_consumedFNz...[truncated]Ú é   éÿÿÿÿó    zutf-8Úreplace)Úerrors)ÚmaxÚintÚgetattrÚtextÚlenÚcloseÚ
iter_bytesÚappendÚjoinÚdecodeÚencoding)Úresponser   r   ÚchunksÚtotalÚchunkÚraws          ú</home/ubuntu/.hermes/hermes-agent/hermes_cli/auth_minimax.pyÚ_minimax_response_error_textr-      s  € ä�”3�u“:Ó€EðÜ�8Ð1°5Ô9Ø—=‘=ˆDØ˜˜�<´s¸4³yÀ5Ò7HÑ#3ÈbÑQð 	�‰Õð !ˆØˆØ×(Ñ(Ó*ò 	ˆEÙØØ�M‰M˜%Ð 3 %¨!¡)¨eÑ"3Ð4Ô5Ø”S˜ ™“_Ñ$ˆEØ�u‹}Ùð	ð �h‰h�vÓˆØ�6�Eˆ{×!Ñ! (×"3Ñ"3Ò">°wÀyÐ!ÓQˆØ¬3¨s«8°eÒ+;Ñ'ÀÑDà�‰Õøˆ�‰Õús   —0D  ÁA
D  Â#AD  Ä Dc               ó�   — | j                  | j                  d|||¬«      d¬«      }|j                  dk(  r|j                  «        |S )z?POST a MiniMax OAuth form without eagerly reading error bodies.ÚPOST©ÚdataÚheadersT)ÚstreaméÈ   )ÚsendÚbuild_requestÚstatus_codeÚread)ÚclientÚurlr1   r2   r'   s        r,   Ú_minimax_post_formr;   5   sF   € à�{‰{˜6×/Ñ/°¸À$ÐPWÐ/ÓXÐaeˆ{Óf€HØ×Ñ˜sÒ"Ø�‰ŒØ€Or   c                 ó  — ddl } | j                  d«      dd }t        j                  t	        j
                  |j                  «       «      j                  «       «      j                  «       j                  d«      }||| j                  d«      fS )zGGenerate (code_verifier, code_challenge_S256, state) for MiniMax OAuth.r   Né@   é`   ú=é   )
ÚsecretsÚtoken_urlsafeÚbase64Úurlsafe_b64encodeÚhashlibÚsha256ÚencodeÚdigestr%   Úrstrip)rA   ÚverifierÚ	challenges      r,   Ú_minimax_pkce_pairrL   =   sr   € ãØ×$Ñ$ RÓ(¨¨"Ð-€HÜ×(Ñ(¬¯©¸¿¹Ó8IÓ)J×)QÑ)QÓ)SÓT×[Ñ[Ó]×dÑdÐehÓi€IØ�Y × 5Ñ 5°bÓ 9Ð9Ð9r   c               óŒ  — t        | |› d�d|t        |d|dœi t        ¥dt        t	        j
                  «       «      i¥¬«      }|j                  dk7  r(t        |«      }t        d|xs |j                  › �d	«      ‚|j                  «       }d
D ]  }||vsŒt        d|› �d«      ‚ |j                  d«      |k7  rt        dd«      ‚|S )Nz/oauth/codeÚcodeÚS256)Úresponse_typeÚ	client_idÚscopeÚcode_challengeÚcode_challenge_methodÚstatezx-request-idr0   r4   z$MiniMax OAuth authorization failed: Úauthorization_failed)Ú	user_codeÚverification_uriÚ
expired_inz&MiniMax OAuth response missing field: Úauthorization_incompleterU   z-MiniMax OAuth state mismatch (possible CSRF).Ústate_mismatch)r;   r   r   ÚstrÚuuidÚuuid4r7   r-   r   Úreason_phraseÚjsonÚget)	r9   Úportal_base_urlrQ   rS   rU   r'   ÚbodyÚpayloadÚfields	            r,   Ú_minimax_request_user_coderf   E   sì   € ô "ØØÐ
˜;Ð'à#°)ÔFYØ,ÀvÐX]ñ
ð JÔ%ÐI ~´s¼4¿:¹:»<Ó7HÑIô€Hð ×Ñ˜sÒ"Ü+¨HÓ5ˆÜÐAÀ$ÒB`È(×J`ÑJ`ÐAaÐbÐdzÓ{Ð{Ø�m‰m‹o€GØ@ò mˆØ˜ÒÜÐ!GÈÀwÐOÐQkÓlÐlðmð ‡{�{�7Ó˜uÒ$ÜÐJÐL\Ó]Ð]Ø€Nr   c               ó$   — t        | «      |dz  kD  S )zMTrue if ``expired_in`` is plausibly a unix-ms absolute time (vs TTL seconds).é   )r   )rY   Únow_mss     r,   Ú&_minimax_expired_in_looks_like_unix_msrj   ]   s   € äˆz‹?˜f¨™kÑ*Ð*r   c               óª   — t        | «      }t        |t        |j                  «       dz  «      ¬«      r|dz  S |j                  «       t        d|«      z   S )zRReturn access-token expiry as unix seconds (MiniMax uses ms epoch or TTL seconds).iè  )ri   ç     @�@r   )r   rj   Ú	timestampr   )rY   Únowr+   s      r,   Ú"_minimax_resolve_token_expiry_unixro   b   sG   € ä
ˆj‹/€CÜ-¨c¼#¸c¿m¹m»oÐPTÑ>TÓ:UÕVØ�V‰|ÐØ�=‰=‹?œS  C›[Ñ(Ð(r   c           
     óF  — t        j                  t        j                  «      }t	        t        | «      |¬«      }|j                  «       t        j                  |t        j                  ¬«      j                  «       t        dt        ||j                  «       z
  «      «      dœS )zX``obtained_at`` / ``expires_at`` / ``expires_in`` derived from a MiniMax ``expired_in``.©rn   )Útzr   )Úobtained_atÚ
expires_atÚ
expires_in)
r   rn   r   Úutcro   r   Ú	isoformatÚfromtimestampr   rm   )rY   rn   Úexpires_at_unixs      r,   Ú_minimax_expiry_fieldsrz   j   sn   € ä
�,‰,”x—|‘|Ó
$€CÜ8¼¸Z»ÈcÔR€Oà—}‘}“Ü×,Ñ,¨_ÄÇÁÔN×XÑXÓZÜ˜!œS °3·=±=³?Ñ!BÓCÓDñð r   c          	     ó\  ‡— t        |t        j                  t        j                  «      ¬«      }t        d|xs ddz  «      }t        j                  «       |k  �r%t        | |› d�t        |||dœt        ¬«      }	|	j                  dk7  rat        |	«      }
	 |
rt        j                  |
«      ni Š‰j                  d	i «      xs i j                  d
«      xs |
}t!        d|xs d› �d«      ‚	 |	j"                  r|	j                  «       ni Š‰j                  d«      }|dk(  rt!        dd«      ‚|dk(  r"t%        ˆfd„dD «       «      st!        dd«      ‚‰S t        j&                  |«       t        j                  «       |k  r�Œ%t!        dd«      ‚# t        $ r i ŠY Œëw xY w# t        $ r i ŠY Œ¡w xY w)Nrq   g       @iÐ  rl   ú/oauth/token)Ú
grant_typerQ   rW   Úcode_verifierr0   r4   Ú	base_respÚ
status_msgzMiniMax OAuth error: ÚunknownÚtoken_exchange_failedÚstatusÚerrorz8MiniMax OAuth reported an error. Please try again later.Úauthorization_deniedÚsuccessc              3  ó@   •K  — | ]  }‰j                  |«      –— Œ y ­w©N)ra   )Ú.0Úkrd   s     €r,   ú	<genexpr>z&_minimax_poll_token.<locals>.<genexpr>˜   s   øè ø€ Ò_¨!�w—{‘{ 1—~Ñ_ùs   ƒ)Úaccess_tokenÚrefresh_tokenrY   z<MiniMax OAuth success payload missing required token fields.Útoken_incompletez7MiniMax OAuth timed out before authorization completed.Útimeout)ro   r   rn   r   rv   r   Útimer;   r   r   r7   r-   r`   ÚloadsÚ	Exceptionra   r   r   ÚallÚsleep)r9   rb   rQ   rW   r~   rY   Úinterval_msÚdeadlineÚintervalr'   Ú
error_textÚmsgrƒ   rd   s                @r,   Ú_minimax_poll_tokenrš   u   s¥  ø€ ô
 2°*Ä(Ç,Á,ÌxÏ|É|ÓB\Ô]€HÜ�3˜Ò,¨°Ñ6Ó7€Hä
�)‰)‹+˜Ó
 Ü%ØØÐ˜|Ð,ä6ÀYØ&¸ñô 'ô
ˆð ×Ñ 3Ò&Ü5°hÓ?ˆJðÙ4>œ$Ÿ*™* ZÔ0ÀB�ð —;‘;˜{¨BÓ/Ò5°2×:Ñ:¸<ÓHÒVÈJˆCÜÐ!6°sÒ7G¸iÐ6HÐIÐKbÓcÐcð	Ø)1¯ª�h—m‘m”o¸BˆGð —‘˜XÓ&ˆØ�WÒÜÐYÐ[qÓrÐrØ�YÒÜÓ_Ð/^Ô_Ô_Ü"Ð#aÐcuÓvÐvØˆNä�
‰
�8Ôô? �)‰)‹+˜Ô
 ôB ÐPÐR[Ó
\Ð\øô' ò Ø’ðûô ò 	ØŠGð	ús$   ÂF Ã+F ÆFÆFÆF+Æ*F+c                ó"   — ddl m}  |d| «       y)zGPersist MiniMax OAuth state to Hermes auth store (~/.hermes/auth.json).r   )Ú_save_active_provider_stateúminimax-oauthN)Úhermes_cli.authrœ   )Ú
auth_staterœ   s     r,   Ú_minimax_save_auth_stater    ¡   s   € å;Ù °Õ<r   ÚglobalTç      .@©ÚregionÚopen_browserÚtimeout_secondsc                óÖ  — ddl m}m}m}m}m}m}m}	 |d   }
| dk(  r|
j                  d   }|
j                  d   }n|
j                  }|
j                  } |«       \  }}} |«       rd}t        d| › d	�«       t        d
|› �«       t        j                  t        j                  |«      ddid¬«      5 } ||||
j                  ||¬«      } |	t!        |d   «      t!        |d   «      |xr  |«       ¬«       |j#                  d«      }t        d«       t%        |||
j                  t!        |d   «      |t'        |d   «      |�t'        |«      nd¬«      }ddd«       d| |||
j                  t(        j#                  dd«      |d   |d   |j#                  d«      dœ
t+        |d   «      ¥} ||«       t        d«       |j#                  d«      x}rt        d |› �«       |S # 1 sw Y   Œ�xY w)!z?Run MiniMax OAuth flow, persist tokens, return auth state dict.r   )ÚPROVIDER_REGISTRYÚ_can_open_graphical_browserÚ_is_remote_sessionrL   rf   r    Ú_print_device_code_instructionsr�   ÚcnÚcn_portal_base_urlÚcn_inference_base_urlFz#Starting Hermes login via MiniMax (z
) OAuth...zPortal: ÚAcceptzapplication/jsonT)r�   r2   Úfollow_redirects)rb   rQ   rS   rU   rX   rW   )r¥   r—   zWaiting for approval...rY   N)rb   rQ   rW   r~   rY   r•   Ú
token_typeÚBearerrŒ   r�   Úresource_url)
Úproviderr¤   rb   Úinference_base_urlrQ   rR   r±   rŒ   r�   r³   u#   âœ“ MiniMax OAuth login successful.Únotification_messagezNote from MiniMax: )rž   r¨   r©   rª   rL   rf   r    r«   Úextrarb   rµ   Úprintr   ÚClientÚTimeoutrQ   r\   ra   rš   r   r   rz   )r¤   r¥   r¦   r¨   r©   rª   rL   rf   r    r«   Úpconfigrb   rµ   rJ   rK   rU   r9   Ú	code_dataÚinterval_rawÚ
token_datarŸ   r™   s                         r,   Ú_minimax_oauth_loginr¿   §   s  € ÷ N÷  Nñ  NØ Ñ0€GØ�‚~Ø!Ÿ-™-Ð(<Ñ=ˆØ$Ÿ]™]Ð+BÑCÑà!×1Ñ1ˆØ$×7Ñ7Ðá!3Ó!5Ñ€Hˆi˜áÔØˆä	Ð/°¨x°zÐ
BÔCÜ	ˆH�_Ð%Ð
&Ô'ä	�‰œeŸm™m¨OÓ<ÀxÐQcÐFdØ'+ô
-ð 
Ø06Ù.Ø O¸w×?PÑ?PÐajÐrwô
ˆ	ñ 	(Ü�	Ð,Ñ-Ó.´°I¸kÑ4JÓ0KØ%ÒGÑ*EÓ*Gõ	
ð
 !—}‘} ZÓ0ˆÜÐ'Ô(ä(Ø O¸w×?PÑ?PÜ˜) KÑ0Ó1ÀÜ˜9 \Ñ2Ó3Ø-9Ð-Eœ˜LÔ)È4ô	
ˆ
÷
ð* $ØØ*Ø0Ø×&Ñ&Ü$Ø —n‘n \°8Ó<Ø" >Ñ2Ø# OÑ4Ø"Ÿ™ ~Ó6ñô ! ¨LÑ!9Ó
:ð€Jñ ˜ZÔ(Ü	Ð
2Ô3Ø�n‰nÐ3Ó4Ð4€sÐ4ÜÐ# C 5Ð)Ô*ØÐ÷M
ð 
ús   Â2B!GÇG(F)r¦   Úforcec          	     óp  ‡— ddl m} | j                  d«      st        ddd¬«      ‚	 t	        j
                  | j                  dd	«      «      j                  «       }|s |t        j                  «       z
  t        kD  r| S t        j                  t        j                  |«      d¬«      5 }t        || d   › d�d| d   | d   dœt        ¬«      }|j                  dk7  rNt!        |«      }|j#                  «       Št%        ˆfd„dD «       «      }t        d|xs |j&                  › �d|¬«      ‚	 ddd«       j)                  «       }	|	j                  d«      dk7  rt        ddd¬«      ‚i | ¥|	d   |	j                  d| d   «      dœ¥t+        |	d   «      ¥}
 ||
«       |
S # t        $ r d
}Y �ŒMw xY w# 1 sw Y   Œ„xY w)zBRefresh MiniMax OAuth access token if close to expiry (or forced).r   )r    r�   z:MiniMax OAuth state has no refresh_token; please re-login.Úno_refresh_tokenT©Úreloginrt   r   g        )r�   r°   rb   r|   rQ   )r}   rQ   r�   r0   r4   c              3  ó&   •K  — | ]  }|‰v –— Œ
 y ­wrˆ   © )r‰   ÚmÚ
body_lowers     €r,   r‹   z/_refresh_minimax_oauth_state.<locals>.<genexpr>û   s   øè ø€ Òv¨a˜!˜zœ/Ñvùs   ƒ)Úinvalid_grantÚrefresh_token_reusedÚinvalid_refresh_tokenzMiniMax OAuth refresh failed: Úrefresh_failedNrƒ   r†   z-MiniMax OAuth refresh did not return success.rŒ   )rŒ   r�   rY   )rž   r    ra   r   r   Úfromisoformatrm   r’   r�   r   r   r¹   rº   r;   r   r7   r-   ÚlowerÚanyr_   r`   rz   )rU   r¦   rÀ   r    rt   r9   r'   rc   rÄ   rd   Ú	new_staterÈ   s              @r,   Ú_refresh_minimax_oauth_staterÑ   ã   sÍ  ø€ å8Ø�9‰9�_Ô%ÜÐWÐYkÐuyÔzÐzðÜ×+Ñ+¨E¯I©I°lÀBÓ,GÓH×RÑRÓTˆ
ñ �j¤4§9¡9£;Ñ.Ô2TÒTØˆä	�‰œeŸm™m¨OÓ<ÈtÔ	Tð ÐX^Ü%ØØÐ&Ñ'Ð(¨Ð5Ø /¸eÀKÑ>PÐchÐixÑcyÑzÜ&ô	
ˆð ×Ñ 3Ò&Ü/°Ó9ˆDØŸ™›ˆJÜÓvÐ3uÔvÓvˆGÜØ0°Ò1O¸×9OÑ9OÐ0PÐQÐScÐmtôð ð	 '÷ð  �m‰m‹o€GØ‡{�{�8Ó 	Ò)ÜÐJÐL\ÐfjÔkÐkðØ
ðà Ñ/Ø Ÿ™ _°e¸OÑ6LÓMòô ! ¨Ñ!6Ó
7ð	€Iñ ˜YÔ'ØÐøô? ò Ø‹
ðú÷
ð ús   ¨3F Â'BF,ÆF)Æ(F)Æ,F5c                óÎ   — ddl m}m} |j                  r| j	                  d«      sy || d|«       	  || «       y# t
        $ r }t        j                  d|«       Y d}~yd}~ww xY w)z_Wipe dead tokens from auth.json after a terminal refresh failure (fail fast, no network retry).r   )r    Ú_quarantine_flat_oauth_stater�   Nr�   z6MiniMax OAuth: failed to persist quarantined state: %s)rž   r    rÓ   Úrelogin_requiredra   r’   ÚloggerÚdebug)rU   Úexcr    rÓ   Ú	_save_excs        r,   Ú-_minimax_oauth_quarantine_on_terminal_refreshrÙ     sZ   € çVØ× Ò  U§Y¡Y¨Ô%?ØÙ  ¨¸Ô=ðZÙ  Õ'øÜò ZÜ�‰ÐMÈy×YÑYûðZús   ²; »	A$ÁAÁA$c                 ó²   — ddl m} m}  |d«      }|r|j                  d«      st	        ddd¬«      ‚	  | |«      S # t
        $ r}t        ||«       ‚ d	}~ww xY w)
z[Load the MiniMax OAuth state and refresh it if near expiry; quarantine on terminal failure.r   )rÑ   Úget_provider_auth_stater�   rŒ   zMNot logged into MiniMax OAuth. Run `hermes model` and select MiniMax (OAuth).Únot_logged_inTrÃ   N)rž   rÑ   rÛ   ra   r   r   rÙ   )rÑ   rÛ   rU   r×   s       r,   Ú_minimax_fresh_staterÝ     s`   € çUÙ# OÓ4€EÙ˜Ÿ	™	 .Ô1ÜØ[Ð]lÐvzô
ð 	
ðÙ+¨EÓ2Ð2øÜò Ü5°e¸SÔAØûðús   ³; »	AÁAÁAc                 ó   — dd„} | S )zÑZero-arg callable yielding a fresh MiniMax access token.

    The Anthropic SDK caches ``api_key`` at construction; MiniMax tokens live ~15 minutes, so a
    static bearer would start 401-ing mid-session.
    c                 óX   — t        «       j                  d«      } | st        ddd¬«      ‚| S )NrŒ   z6MiniMax OAuth state has no access_token after refresh.Úno_access_tokenTrÃ   )rÝ   ra   r   )Útokens    r,   Ú_providez4build_minimax_oauth_token_provider.<locals>._provide-  s/   € Ü$Ó&×*Ñ*¨>Ó:ˆÙÜÐWÐYjÐtxÔyÐyØˆr   )Úreturnr\   rÆ   )râ   s    r,   Ú"build_minimax_oauth_token_providerrä   '  s   € óð €Or   )Úmin_token_ttl_secondsÚas_token_providerc                óf   — t        «       }d|r
t        «       n|d   |d   j                  d«      ddœS )ziReturn {provider, api_key, base_url, source}; string ``api_key`` by default (``hermes status`` contract).r�   rŒ   rµ   ú/Úoauth)r´   Úapi_keyÚbase_urlÚsource)rÝ   rä   rI   )rå   ræ   rU   s      r,   Ú)resolve_minimax_oauth_runtime_credentialsrí   6  sB   € ô
 !Ó"€Eà#Ù;LÔ5Ô7ÐRWÐXfÑRgØÐ.Ñ/×6Ñ6°sÓ;Øñ	ð r   c           	     óÜ   — ddl m} 	 t        t        | dd«      xs dt        | dd«       t        | dd«      xs d	¬
«       y# t        $ r!}t         ||«      «       t        d«      ‚d}~ww xY w)z"CLI entry for MiniMax OAuth login.r   )Úformat_auth_errorr¤   Nr¡   Ú
no_browserFr�   r¢   r£   r   )rž   rï   r¿   r   r   r¸   Ú
SystemExit)Úargsr»   rï   r×   s       r,   Ú_login_minimax_oauthró   D  sm   € å1ðÜÜ˜4 ¨4Ó0Ò<°HÜ$ T¨<¸Ó?Ð?Ü# D¨)°TÓ:ÒB¸dö	
øô
 ò ÜÑ Ó$Ô%Ü˜‹mÐûðús   ˆ8A Á	A+Á
A&Á&A+)r'   úhttpx.Responser   r   rã   r\   )
r9   úhttpx.Clientr:   r\   r1   úDict[str, Any]r2   zDict[str, str]rã   rô   )rã   Útuple)r9   rõ   rb   r\   rQ   r\   rS   r\   rU   r\   rã   rö   )rY   r   ri   r   rã   Úbool)rY   r   rn   r   rã   Úfloat)rY   r   rã   rö   )r9   rõ   rb   r\   rQ   r\   rW   r\   r~   r\   rY   r   r•   zOptional[int]rã   rö   )rŸ   rö   rã   ÚNone)r¤   r\   r¥   rø   r¦   rù   rã   rö   )rU   rö   r¦   rù   rÀ   rø   rã   rö   )rU   rö   r×   r   rã   rú   )rã   rö   )rã   zCallable[[], str])rå   r   ræ   rø   rã   rö   )r»   r   rã   rú   ).Ú__doc__Ú
__future__r   ÚloggingrC   rE   r`   r�   r]   r   r   Útypingr   r   r   r	   r
   Úhermes_cli.auth_constantsr   r   r   r   r   r   r   rž   r   Ú	getLoggerrÕ   Ú_MINIMAX_OAUTH_ERROR_BODY_LIMITr-   r;   rL   rf   rj   ro   rz   rš   r    r¿   rÑ   rÙ   rÝ   rä   rí   ró   rÆ   r   r,   ú<module>r     sg  ðñõ #ã Û Û Û Û Û ß 'ß ?Õ ?÷÷ ñ ñ
 Ý.Ø	ˆ×	Ñ	Ð,Ó	-€à"+Ð ð Lkõ ó0ó:ðØðØ.1ðØ>AðØSVðØ_bðàóó0+ó
)óð)]Øð)]Ø.1ð)]Ø>Að)]àð)]à#&ð)]à47ð)]àFSð)]ð ó)]óX=ð +3ÈÐhlõ 9ðx UYÐhmõ &óR	Zóóð  %GØ#ñØ!ðàðð óôr   