
    6jyo                       U 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	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 ddlmZ  ej        e          Z ej                    dz  dz  Zd	Zd
Ze dZe dZe dZe dZe dZdZ dZ!h dZ"h dZ#h dZ$dZ%dZ&dZ'i Z(de)d<    ej*                    Z+dZ,d]dZ-d Z.d^d Z/d_d"Z0d`dad&Z1d' Z2d`dbd)Z3dcd*Z4ddd-Z5d. Z6ded0Z7dfd1Z8dfd2Z9dgd5Z:dgd6Z;dhd7Z<dhd8Z=dfd9Z>d:d;did@Z?djdAZ@dkdDZAdldGZBdgdHZCdgdIZDdgdJZEdgdKZFdmdLZGd`dndOZHdhdPZIdodTZJdhdUZKdpdVZLdqdXZMdrdYZNdqdZZOd[ ZPdsd\ZQdS )ta/  In-app OAuth flow implementations for onboarding.

The browser receives only WebUI-local flow metadata (flow_id, user_code,
verification_uri, high-level status). Provider device/auth codes and OAuth
tokens stay server-side and are persisted to the active Hermes profile's
``auth.json`` credential_pool.
    )annotationsN)datetimetimezone)Path)Any.hermes	auth.jsonzhttps://auth.openai.comapp_EMoamEEZ73f0CkXaXp7hrannz/codex/devicez!/api/accounts/deviceauth/usercodez/api/accounts/deviceauth/tokenz/oauth/tokenz/deviceauth/callbackz%https://chatgpt.com/backend-api/codexi  >   claude	anthropicclaude-codeopenai-codex>   r   r   r   >   
gemini-cli
qwen-oauthcopilot-acpminimax-oauthgoogle-gemini-clinouscopilotminimax   z9Claude Code credential linking failed. Check server logs.zdict[str, dict[str, Any]]_OAUTH_FLOWS)ANTHROPIC_TOKENANTHROPIC_API_KEYreturnNonec                     ddl m}  | 5  t          D ]"}t          j                            |d           #	 ddd           dS # 1 swxY w Y   dS )zCClear Anthropic process env fallbacks under the streaming env lock.r   	_ENV_LOCKN)api.streamingr   _ANTHROPIC_ENV_KEYSosenvironpop)r   keys     /root/hermes-webui/api/oauth.py#_clear_process_anthropic_env_valuesr'   >   s    ''''''	 & && 	& 	&CJNN3%%%%	&& & & & & & & & & & & & & & & & & &s   +AA	Ac                V    ddl m} |5   | |i |cddd           S # 1 swxY w Y   dS )av  Resolve runtime credentials under the Anthropic onboarding env lock.

    Request paths must resolve Anthropic env fallbacks per outbound request,
    not cache ANTHROPIC_TOKEN or ANTHROPIC_API_KEY across onboarding. Sharing
    the process-env lock prevents a chat stream from observing one stale
    Anthropic env value while onboarding has already cleared the other.
    r   r   N)r    r   )resolverargskwargsr   s       r&   0resolve_runtime_provider_with_anthropic_env_lockr,   G   s     ('''''	 ) )x((() ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )s   ""providerstrc                    t          | pd                                                                          } | t          v rdS | pdS )N r   r   )r.   striplower_ANTHROPIC_PROVIDER_ALIASES)r-   s    r&   $_normalize_onboarding_oauth_providerr4   U   sG    8>r""((**0022H...{%~%    r   c                     	 ddl m}  t           |                       S # t          $ r;}t                              d|           t          j                    dz  cY d }~S d }~ww xY w)Nr   )get_active_hermes_homez\Falling back to ~/.hermes for OAuth credential storage: active-profile resolution failed: %sr   )api.profilesr7   r   	Exceptionloggerwarninghome)r7   excs     r&   _get_active_hermes_homer>   \   s    '777777**,,--- 	' 	' 	' 	3	
 	
 	

 y{{Y&&&&&&&	's    
A$0AA$A$	auth_pathPath | Nonedict[str, Any]c                8   | pt           }|                                r|	 t          j        |                    d                    }t          |t                    r|ni S # t          j        $ r(}t          	                    d||           i cY d}~S d}~ww xY wi S )zDRead auth.json and return parsed dict, or an empty compatible store.utf-8encodingzFailed to parse %s: %sN)
AUTH_JSON_PATHexistsjsonloads	read_text
isinstancedictJSONDecodeErrorr:   r;   )r?   pathloadedr=   s       r&   _read_auth_jsonrP   o   s    &D{{}} 	Z @ @AAF'55=662=# 	 	 	NN3T3???IIIIII	 Is   A A   B/BBBc                     t                      S )z7Public wrapper for streaming credential self-heal code.)rP    r5   r&   read_auth_jsonrS   |   s    r5   datac                n   |pt           }|j                            dd           |                    |j         dt          j                     dt          j                    j	                   }	 |
                    t          j        | dd          dz   d	
           	 |                    d           n3# t          $ r&}t                              d||           Y d}~nd}~ww xY w|                    |           	 |                    t$          j        t$          j        z             n# t          $ r Y nw xY w|	 |                                r|                                 S S # t          $ r Y S w xY w# 	 |                                r|                                 w w # t          $ r Y w w xY wxY w)zAtomically write auth.json with owner-only permissions.

    OAuth access/refresh tokens live in this file. The temp file is chmod 0600
    before rename so the final path never inherits a permissive process umask.
    T)parentsexist_okz.tmp..   F)indentensure_ascii
rC   rD   i  zFailed to chmod 0600 on %s: %sN)rF   parentmkdir	with_namenamer"   getpiduuiduuid4hex
write_textrH   dumpschmodOSErrorr:   r;   replacestatS_IRUSRS_IWUSRrG   unlink)rT   r?   rN   tmpr=   s        r&   _write_auth_jsonro      s    &DKdT222
..DILLBIKKLL$*,,:JLL
M
MCtz$quEEELW^___	GIIe 	G 	G 	GNN;S#FFFFFFFF	GD	JJt|dl23333 	 	 	D		zz|| 

 	 	 	D		zz|| 

 	 	 	D	s   0/E8  B6 5E8 6
C& C!E8 !C&&E8 ?,D, +E8 ,
D96E8 8D99E8 >(E((
E54E58F4:(F$"F4$
F1.F40F11F4c                     t          j        t          j                                                                      dd          S )Nz+00:00Z)r   nowr   utc	isoformatri   rR   r5   r&   _now_isoru      s0    <%%//1199(CHHHr5   hermes_home
token_datac                H   t          |                    d          pd                                          }t          |                    d          pd                                          }|st          d          t	          |           dz  }t          |          }|                    dd           |                    di           }t          |t                    si }||d<   |                    d	g           }t          |t                    sg }||d	<   t                      }d
}	ddh}
|D ]2}t          |t                    r|                    d          |
v r|}	 n3|	Fdt          j                    j        d
d         z   ddddt          |d}	|                    d|	           |	                    dddd||t          ||d	           ||d<   t#          ||          }	 ddlm}  |d	           n,# t(          $ r t*                              dd           Y nw xY w|S )z<Persist Codex OAuth credentials to active-profile auth.json.access_tokenr0   refresh_tokenz3Codex token exchange did not return an access_tokenr	   version   credential_poolr   Nzmanual:device_codeoauth_devicesourcezcodex-oauth-   zCodex OAuthoauthr   )idlabel	auth_typepriorityr   base_url
created_at)	r   r   r   r   ry   rz   r   last_refresh
updated_atr    invalidate_credential_pool_cachez2Failed to invalidate openai-codex credential cacheTexc_info)r.   getr1   RuntimeErrorr   rP   
setdefaultrK   rL   listru   rb   rc   rd   CODEX_BASE_URLinsertupdatero   
api.configr   r9   r:   debug)rv   rw   ry   rz   r?   authpoolentriesrr   entry_accept_sources	candidaterN   r   s                 r&   _persist_codex_credentialsr      s   z~~n55;<<BBDDL
77=2>>DDFFM RPQQQ[!!K/I9%%DOOIq!!!??,b11DdD!! '"&oonb11Ggt$$ '&^
**CE ,^<O  	i&& 	9==+B+Bo+U+UEE} 4:<<#3CRC#88" *&
 
 	q%   	LL" *(*&
	
 
	
   DD),,DZ??????((8888 Z Z ZITXYYYYYZ Ks   $G6 6&HHc                :    t          t                      |           S N)r   r>   )rw   s    r&   _save_codex_credentialsr      s    %&=&?&?LLLr5   dict[str, Any] | Nonec                     	 ddl m} m}  |            }|r/ | |          s"t          |                    d                    r|S n2# t
          $ r%}t                              d|           Y d}~nd}~ww xY wdS )zRead Claude Code OAuth credentials from the host without exposing them.

    Delegates to the agent adapter which knows about ~/.claude/.credentials.json
    and macOS Keychain. Returns the credential dict or None.
    r   )is_claude_code_token_validread_claude_code_credentialsrefreshTokenz*Could not read Claude Code credentials: %sN)agent.anthropic_adapterr   r   boolr   r9   r:   r   )r   r   credsr=   s       r&   _read_claude_code_credentialsr      s    H	
 	
 	
 	
 	
 	
 	
 	

 -,.. 	&&u--	15eii6O6O1P1P	 L H H HA3GGGGGGGGH4s   AA 
A5A00A5c                    	 ddl m}  |t          |           dz  d t          D                        n2# t          $ r%}t
                              d|           Y d}~nd}~ww xY wt                       dS )a)  Clear Anthropic API/setup-token env values in the active profile only.

    The .env write path already clears os.environ while holding the streaming
    env lock. Keep a locked process-env clear here too so import/write failures
    cannot leave or partially clear stale Anthropic fallbacks.
    r   )_write_env_filez.envc                    i | ]}|d S r   rR   ).0r%   s     r&   
<dictcomp>z/_clear_anthropic_env_values.<locals>.<dictcomp>  s    6663S$666r5   z(Failed to clear Anthropic env values: %sN)api.providersr   r   r!   r9   r:   r;   r'   )rv   r   r=   s      r&   _clear_anthropic_env_valuesr     s    H111111&66"5666	
 	
 	
 	
  H H HA3GGGGGGGGH')))))s   14 
A#AA#c                J   t          |            t          |           dz  }t          |          }|                    dd           |                    di           }t	          |t
                    si }||d<   |                    dg           }t	          |t                    sg }||d<   t                      }d}|D ]4}t	          |t
                    r|                    d          dk    r|} n5|@d	t          j
                    j        dd
         z   dddd|d}|                    d|           |                    dddd|d           ||d<   t          ||           	 ddlm}  |d           dS # t"          $ r  t$                              dd           Y dS w xY w)u  Link Hermes to use Claude Code's credential store.

    Clears ANTHROPIC_TOKEN and ANTHROPIC_API_KEY from the Hermes .env so
    that resolve_anthropic_token() falls through to reading Claude Code's
    ~/.claude/.credentials.json directly — the same thing the CLI's
    ``use_anthropic_claude_code_credentials()`` does.

    Also writes a marker entry in auth.json credential_pool so that
    ``_provider_oauth_authenticated("anthropic", ...)`` can detect the
    linked state without touching the actual credential files.
    r	   r{   r|   r}   r   Nr   claude_code_linkedzanthropic-claude-code-r   zClaude Code (linked)r   r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   /Failed to invalidate anthropic credential cacheTr   )r   r   rP   r   rK   rL   r   ru   r   rb   rc   rd   r   r   ro   r   r   r9   r:   r   )	rv   r?   r   r   r   rr   r   r   r   s	            r&   _link_anthropic_credentialsr     s     ,,, [!!K/I9%%DOOIq!!!??,b11DdD!! '"&ook2..Ggt$$ $#[
**CE  	i&& 	9==+B+BFZ+Z+ZEE}*TZ\\-=crc-BB+ *
 
 	q%   	LL'&     DT9%%%W??????((55555 W W WFQUVVVVVVWs   %E8 8&F"!F"flow_idflowc                    dd| |                     dd          |                     dt                    d}|                     d          dk    rd|d<   |                     d	          r|d	         |d	<   |S )
NTr   statuspendingpoll_interval_seconds)okr-   r   r   r   u   Claude Code credentials were not found on this server. Please run 'claude login' or 'claude setup-token' in a terminal on the host, then return here — this page will detect the credentials automatically.action_required
expires_at)r   !ANTHROPIC_CREDENTIAL_POLL_SECONDSr   r   payloads      r&   _anthropic_public_start_payloadr   T  s    ((8Y//!%*ACd!e!e G xxY&&e 	!"
 xx 3 $\ 2Nr5   c                    dd| |                     dd          d}|                     d          dk    r|                     d          r
t          |d<   |S )NTr   r   errorr   r-   r   r   )r   ANTHROPIC_PUBLIC_LINK_ERRORr   s      r&    _anthropic_public_status_payloadr   g  sa    ((8W--	 G xxW$$'):):$6Nr5   c                h    t          j        t          | fd          }|                                 d S NT)targetr*   daemon)	threadingThread _run_anthropic_credential_workerstartr   workers     r&   "_spawn_anthropic_credential_workerr   s  s5    /wj  F LLNNNNNr5   c           
        	 t           5  t          t                              |           pi           }ddd           n# 1 swxY w Y   |sdS |                    d          dk    rdS t	          |                    d          pd          t          j                    k    rt          | d           dS t          j        t          dt          |                    d	          pt                                         t           5  t                              |           }|r|                    d          dk    r	 ddd           dS 	 ddd           n# 1 swxY w Y   	 t                      }|rt           5  t                              |           }|r|                    d          dk    r	 ddd           dS 	 ddd           n# 1 swxY w Y   t          |d
                   }t          |           t           5  t                              |           }|r|                    d          dk    r)t          |o|                    d          dk              }n,d|d<   t          j                    |d<   t          |           d}ddd           n# 1 swxY w Y   |rt!          |           dS # t"          $ r}t$                              d|           t           5  t                              |           }|rU|                    d          dk    r<d|d<   t          j                    |d<   t)          |          |d<   t          |           ddd           n# 1 swxY w Y   Y d}~dS d}~ww xY w)zNPoll for Claude Code credential appearance until found, cancelled, or expired.TNr   r   r   r   expiredr|   r   rv   	cancelledsuccessr   Fz'Anthropic credential polling failed: %sr   )_OAUTH_FLOWS_LOCKrL   r   r   floattime_set_flow_statussleepmaxintr   r   r   r   r   _drop_sensitive_flow_fields_remove_anthropic_link_markerr9   r:   r;   r.   )r   r   liver   currentrv   r   r=   s           r&   r   r   z  s   5 	9 	9((117R88D	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	F88H**F,'',1--<<Wi000F
3q#dhh'>??dCdeeffggg  	 	##G,,D 488H--::	 	 	 	 	 	 	 	:	 	 	 	 	 	 	 	 	 	 	 	 	 	 	
"	133E} #  &**733 '++h"7"79"D"D       "D              
 tM233K'444" & &&**733 &'++h"7"79"D"D $W%UX1F1F+1U V VII(1GH%,0IKKGL)/888 %I& & & & & & & & & & & & & & &  ;-k:::F 		 		 		NNDcJJJ" 9 9&**733 9w{{844	AA(/GH%,0IKKGL)'*3xxGG$/8889 9 9 9 9 9 9 9 9 9 9 9 9 9 9 FFFFF		s   *?AA7EEE!J6 3J6 :7G1J6 ?J6 GJ6 G.J6 BJJ6 JJ6 J J6 6
M6 "M1"A2M M1 M$	$M1'M$	(M11M6c                P   t          |           dz  }t          |          }|                    d          }t          |t                    sdS |                    d          }t          |t
                    sdS d |D             }t          |          t          |          k    rdS |r||d<   n|                    dd           t                      |d<   t          ||           	 ddl
m}  |d           dS # t          $ r  t                              d	d
           Y dS w xY w)zHRemove the secret-free Claude Code linked marker after a cancelled race.r	   r}   Nr   c                n    g | ]2}t          |t                    r|                    d           dk    0|3S )r   r   )rK   rL   r   )r   r   s     r&   
<listcomp>z1_remove_anthropic_link_marker.<locals>.<listcomp>  s?    xxxez%/F/Fx599U]K^K^bvKvKvEKvKvKvr5   r   r   r   r   Tr   )r   rP   r   rK   rL   r   lenr$   ru   ro   r   r   r9   r:   r   )rv   r?   r   r   r   keptr   s          r&   r   r     sW   [!!K/I9%%D88%&&DdD!! hh{##Ggt$$ xxwxxxD
4yyCLL   $ [d###!DT9%%%W??????((55555 W W WFQUVVVVVVWs   (C; ;&D%$D%Fformurlr   r   r   c                  |r5t           j                            |                              d          }d}n)t	          j        |                              d          }d}t           j                            | |d|dd          }t           j                            |d          5 }t	          j	        |
                                                    d                    cd d d            S # 1 swxY w Y   d S )	NrC   z!application/x-www-form-urlencodedzapplication/jsonPOST)zContent-TypeAccept)rT   methodheaders   )timeout)urllibparse	urlencodeencoderH   rf   requestRequesturlopenrI   readdecode)r   r   r   rT   content_typereqresps          r&   _json_requestr     s(    *|%%g..55g>>:z'""))'22)
.
 
 !-9KLL	 !  C 
		R		0	0 7Dz$))++,,W55667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   (9C..C25C2c                 :    t          t          dt          i          S )N	client_id)r   CODEX_USER_CODE_URLCODEX_CLIENT_IDrR   r5   r&   _request_codex_user_coder    s    ,{O.LMMMr5   device_auth_id	user_codec                    	 t          t          | |d          S # t          j        j        $ r}|j        dv rY d }~d S  d }~ww xY w)N)r  r  )i  i  )r   CODEX_DEVICE_TOKEN_URLr   r   	HTTPErrorcode)r  r  r=   s      r&   _poll_codex_authorizationr    sj    "-IFF
 
 	
 <!   8z!!44444s    A	>>Aauthorization_codecode_verifierc           	     P    t          t          d| t          t          |dd          S )Nr	  )
grant_typer  redirect_urir   r
  Tr   )r   CODEX_TOKEN_URLCODEX_REDIRECT_URIr   )r	  r
  s     r&   _exchange_codex_authorizationr    s:    .&.(*	
 	
 
 
 
 
r5   c                    dd| |                     dd          t          |                     dd          |                     d          |                     dd	          d
S )NTr   r   r   r  r0   r   r   r   )r   r-   r   r   verification_urir  r   r   )r   CODEX_VERIFICATION_URI)r   r   s     r&   _codex_public_start_payloadr    s`    "((8Y//2XXk2..hh|,,!%*A1!E!E	 	 	r5   c                    dd| |                     dd          d}|                     d          dk    rB|                     d          r-t          |                     d                    d d         |d<   |S )NTr   r   r   r      )r   r.   r   s      r&   _codex_public_status_payloadr    s~    "((8W--	 G xxW$$'):):$txx0011$3$7Nr5   c                z    |                     dd          }|dk    rt          | |          S t          | |          S Nr-   r   r   )r   r   r  r   r   r-   s      r&   _public_start_payloadr    s@    xx
N33H;.w===&w555r5   c                z    |                     dd          }|dk    rt          | |          S t          | |          S r  )r   r   r  r  s      r&   _public_status_payloadr    s@    xx
N33H;/>>>'666r5   c                <    dD ]}|                      |d            d S )N)r  r	  r
  ry   rz   rw   )r$   )r   r%   s     r&   r   r   &  s6       	d r5   rr   float | Nonec                   | pt          j                     } | dz
  }t          5  t          t                                                    D ]\  }}|                    d          }|dk    r<t          |                    d          pd          | k    rd|d<   t          |           |dv rCt          |                    d          pd          |k     rt                              |d            	 d d d            d S # 1 swxY w Y   d S )	Ni,  r   r   r   r   r   >   r   r   r   r   r   )	r   r   r   r   itemsr   r   r   r$   )rr   cutofffidr   r   s        r&   _cleanup_oauth_flowsr$  2  sS   

C3YF	 , ,l002233 	, 	,ICXXh''F""uTXXl-C-C-Hq'I'IS'P'P!*X+D111EEE%PTPXPXYePfPfPkjkJlJlouJuJu  d+++	,, , , , , , , , , , , , , , , , , ,s   CC;;C?C?c                h    t          j        t          | fd          }|                                 d S r   )r   r   _run_codex_oauth_workerr   r   s     r&   _spawn_codex_oauth_workerr'  ?  s.    %<G:VZ[[[F
LLNNNNNr5   r   fieldsr   c                    t           5  t                              |           }|s	 d d d            d S ||d<   t          j                    |d<   |                    |           |dv rt          |           d d d            d S # 1 swxY w Y   d S )Nr   r   >   r   r   r   r   )r   r   r   r   r   r   )r   r   r(  r   s       r&   r   r   D  s    	 . .(( 	. . . . . . . .  X!Y[[\FAAA'---. . . . . . . . . . . . . . . . . .s   BABB
Bc           
     ^   	 t           5  t          t                              |           pi           }d d d            n# 1 swxY w Y   |sd S |                    d          }|dk    rd S t	          |                    d          pd          t          j                    k    rt          | d           d S t          j        t          dt          |                    d          pd	                               t           5  t          t                              |           pi           }d d d            n# 1 swxY w Y   |                    d          dk    rd S 	 t          t          |                    d
          pd          t          |                    d          pd                    }|t          |                    d          pd                                          }t          |                    d          pd                                          }|r|st          d          t          ||          }t           5  t                              |           }|r|                    d          dk    r	 d d d            d S 	 d d d            n# 1 swxY w Y   t          t!          |d                   |           t          | d           d S # t"          $ rE}	t$                              d|	           t          | dt          |	                     Y d }	~	d S d }	~	ww xY w)NTr   r   r   r   r   r|   r   r   r  r0   r  r	  r
  z@Device auth response missing authorization_code or code_verifierrv   r   z&Codex OAuth onboarding flow failed: %sr   )r   )r   rL   r   r   r   r   r   r   r   r   r  r.   r1   r   r  r   r   r9   r:   r;   )
r   r   r   r   	code_respr	  r
  tokensr   r=   s
             r&   r&  r&  P  s   + 	9 	9((117R88D	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	F(##YF,'',1--<<Wi000F
3q#dhh'>??D1EEFFGGG 	9 	9((117R88D	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	9 	988H**F	1DHH-..4"55DHH[))/R00 I  !$Y]]3G%H%H%NB!O!O!U!U!W!W	o > > D"EEKKMMM% g] g"#efff23E}UUF #  &**733 '++h"7"79"D"D       "D               'tD,?'@'@&IIIWi000F 	 	 	NNCSIIIWgSXX>>>>FFFFF	sk   *?AA*D77D;>D;AK 6BK 7JK K J!!K $J!%6K 
L,':L''L,c                   t                      }t          j                    j        }|rt	          |            ddt          |           t          j                    t          j                    d}t          5  |t          |<   ddd           n# 1 swxY w Y   t          ||          S t          j                    t          z   }dd|t          t          |           t          j                    t          j                    d}t          5  |t          |<   ddd           n# 1 swxY w Y   t          |           t          ||          S )zDStart or immediately complete the Anthropic credential-linking flow.r   r   )r-   r   rv   r   r   Nr   )r-   r   r   r   rv   r   r   )r   rb   rc   rd   r   r.   r   r   r   r  ANTHROPIC_FLOW_MAX_WAIT_SECONDSr   r   )rv   r   r   r   r   s        r&   _start_anthropic_flowr/    s   )++EjllG 4#K000#{++)++)++
 
  	) 	)$(L!	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)$Wd333 >>J !B;''ikkikk D 
 % % $W% % % % % % % % % % % % % % %&w/// $///s$   6BBBDD#&D#bodyc           
     <   t                       t          | pi                     d          pd                                                                          }|t
          vr)|t          v s|rt          d          t          d          |t          v rt          t                                S t                      }	 t                      }n%# t          $ r}t          d|           |d}~ww xY wt          |                    d          pd                                          }t          |                    d          pd                                          }|r|st          d	          t          d
t          |                    d          pd                    }t          |                    d          pt                     }t#          j                    t%          t          |d          t                     z   }	t'          j                    j        }
dd|||	|t          |          t#          j                    t#          j                    d	}t,          5  |t.          |
<   ddd           n# 1 swxY w Y   t1          |
           t3          |
|          S )zStart the supported onboarding OAuth flow.

    Supports OpenAI Codex (device-code flow) and Anthropic/Claude Code
    (credential-linking flow). Other providers are rejected.
    r-   r0   zXOnly OpenAI Codex and Anthropic/Claude OAuth are supported in WebUI onboarding right nowzprovider is requiredzFailed to start Codex OAuth: Nr  r  z,Device code response missing required fields   intervalr   
expires_in<   r   r   )	r-   r   r  r  r   r   rv   r   r   )r$  r.   r   r1   r2   #_ALLOWED_ONBOARDING_OAUTH_PROVIDERS$_REJECTED_ONBOARDING_OAUTH_PROVIDERS
ValueErrorr3   r/  r>   r  r9   r   r   r   CODEX_FLOW_MAX_WAIT_SECONDSr   minrb   rc   rd   r   r   r'  r  )r0  r-   rv   devicer=   r  r  r3  r4  r   r   r   s               r&   start_onboarding_oauth_flowr<    s    DJB##J//5266<<>>DDFFH:::;;;x;0   /000 ...$%<%>%>??? *++KK)++ K K K@3@@AAsJK FJJ{++1r2288::I$455;<<BBDDN KN KIJJJ1c&**Z005A6677HVZZ--L1LMMJs3z2#6#68STTTJjllG"( !);''ikkikk
 
D 
 % % $W% % % % % % % % % % % % % % %g&&& $///s*   >C 
C/C**C/I44I8;I8c                P   t                       t          | pd                                          }|st          d          t          5  t
                              |          }|st          d          |                    d          dk    rct          |                    d          pd          t          j	                    k    r*d|d<   t          j	                    |d	<   t          |           t          |t          |                    cd d d            S # 1 swxY w Y   d S )
Nr0   flow_id is requiredzOAuth flow not foundr   r   r   r   r   r   )r$  r.   r1   r8  r   r   r   KeyErrorr   r   r   r  rL   )r   r#  r   s      r&   poll_onboarding_oauth_flowr@    sT   
gm


"
"
$
$C 0.///	 7 7$$ 	3122288H**uTXXl5K5K5Pq/Q/QUYU^U`U`/`/`&DN!%D'---%c4::667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   
CDD"Dc                f   t          | pi                     d          pd                                          }|st          d          t	          t          | pi                     d          pd                    }|dvrd}t
          5  t                              |          }|sd||dd	cd d d            S |                    d
          dk    r*d|d
<   t          j                    |d<   t          |           t          |t          |                    }d d d            n# 1 swxY w Y   |S )Nr   r0   r>  r-   >   r   r   r   Tr   r   r   r   r   )r.   r   r1   r8  r4   r   r   r   r   r  rL   )r0  r#  requested_providerr   results        r&   cancel_onboarding_oauth_flowrD    s   
tzry))/R
0
0
6
6
8
8C 0.///=c4:2BRBRS]B^B^Bdbd>e>eff!>>>+	 9 9$$ 	g,>3Zeff9 9 9 9 9 9 9 9 88H**(DN!%D'---'T$ZZ889 9 9 9 9 9 9 9 9 9 9 9 9 9 9 Ms   
#D&:A D&&D*-D*c                 $    t          ddi          S )Nr-   r   )r<  rR   r5   r&   start_codex_device_coderF    s    &
N'CDDDr5   c              #     K   dddV  d S )Nr   z+Use /api/onboarding/oauth/poll with flow_id)r   r   rR   )device_coder3  s     r&   poll_codex_tokenrI    s!      'T
U
UUUUUUr5   )r   r   )r-   r.   r   r.   )r   r   r   )r?   r@   r   rA   )rT   rA   r?   r@   r   r   )r   r.   )rv   r   rw   rA   r   r   )r   r   )rv   r   r   r   )r   r.   r   rA   r   rA   )r   r.   r   r   )r   r.   r   rA   r   r   r   rA   )r   rA   )r  r.   r  r.   r   r   )r	  r.   r
  r.   r   rA   )r   rA   r   r   )rr   r  r   r   )r   r.   r   r.   r(  r   r   r   )rv   r   r   rA   )r0  r   r   rA   )r   r.   r   rA   )r   )R__doc__
__future__r   rH   loggingr"   rj   r   r   rb   urllib.errorr   urllib.parseurllib.requestr   r   pathlibr   typingr   	getLogger__name__r:   r<   rF   CODEX_ISSUERr   r  r   r  r  r  r   r9  r6  r3   r7  r   r.  r   r   __annotations__Lockr   r!   r'   r,   r4   r>   rP   rS   ro   ru   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r   r$  r'  r   r&  r/  r<  r@  rD  rF  rI  rR   r5   r&   <module>rW     s     # " " " " "   				                    ' ' ' ' ' ' ' '            		8	$	$ y(;6(0(777 %HHH (HHH !///$::: 8% &\&\&\ #DDD 	( 	( 	( $ %& !") Y *, , , , ,"IN$$ > & & & &) ) )& & & &' ' ' '&
 
 
 
 
  
    :I I I IB B B BLM M M   ,* * * *&:W :W :W :Wz   &	 	 	 	   7 7 7 7tW W W W8 FK 7 7 7 7 7 7"N N N N	 	 	 	   
 
 
 
	 	 	 	6 6 6 67 7 7 7	 	 	 	
, 
, 
, 
, 
,   
	. 	. 	. 	., , , ,^!0 !0 !0 !0H20 20 20 20j7 7 7 7    *E E EV V V V V Vr5   