
    FjN^                    "   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m	Z	 ddl
m
Z
mZ ddlmZmZmZ ed         ZdZdad	ed
<    e	d           G d d                      Z e	d           G d d                      Z e	d           G d d                      ZdTdUdZddddVdZdWd ZdXd%ZdYd'Zd(dd)dZd-Zd[d1Zd\d2Zd]d3Zd^d5Z d_d8Z!	 dTd`d:Z"dad<Z#dbd>Z$dcdAZ%dddCZ&dddDdedJZ'dfdKZ(dgdLZ)dhdMZ*didNZ+djdPZ,dkdRZ-dhdSZ.dS )lz3Normalized Nous Portal account entitlement helpers.    )annotationsN)	dataclass)datetimetimezone)AnyLiteralOptional)jwtaccount_apiinference_keynoneerror<   z1tuple[str, float, 'NousPortalAccountInfo'] | None_account_info_cacheT)frozenc                  d    e Zd ZU dZded<   dZded<   dZded<   dZded<   dZded	<   dZ	ded
<   dS )NousPortalSubscriptionInfoNOptional[str]planOptional[int]tierOptional[float]monthly_chargecurrent_period_endcredits_remainingrollover_credits)
__name__
__module____qualname__r   __annotations__r   r   r   r   r        6/usr/local/lib/hermes-agent/hermes_cli/nous_account.pyr   r      s{         DD&*N****(,,,,,)-----(,,,,,,,r"   r   c                      e Zd ZU dZded<   dZded<   dZded<   dZded<   dZded	<   dZ	ded
<   dZ
ded<   dZded<   dZded<   dZded<   dZded<   dZded<   dS )NousPaidServiceAccessInfoNOptional[bool]allowedpaid_accessr   reasonorganisation_idr   effective_at_mshas_active_subscriptionactive_subscription_is_paidsubscription_tierr   subscription_monthly_chargesubscription_credits_remainingpurchased_credits_remainingtotal_usable_credits)r   r   r   r'   r    r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r!   r"   r#   r%   r%      s         "G"""""&K&&&& F    %)O))))%)O)))).22222266666'+++++3777776:"::::377777,0000000r"   r%   c                  r   e Zd ZU ded<   ded<   ded<   dZded<   dZded	<   dZded
<   dZded<   dZded<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   ed$d!            Zed$d"            Zed$d#            ZdS )%NousPortalAccountInfobool	logged_inNousAccountInfoSourcesourcefreshNr   user_idorg_id	client_id
product_idnous_clientportal_base_urlinference_base_urlFinference_credential_presentcredential_sourcezOptional[datetime]
expires_atemail	privy_did$Optional[NousPortalSubscriptionInfo]subscriptionr&   paid_service_access#Optional[NousPaidServiceAccessInfo]paid_service_access_infoOptional[dict[str, Any]]
raw_claimsraw_accountr   returnc                    | j         du S NTrH   selfs    r#   is_paidzNousPortalAccountInfo.is_paidF       '4//r"   c                    | j         du S )NFrQ   rR   s    r#   is_free_tierz"NousPortalAccountInfo.is_free_tierJ   s    '500r"   c                    | j         du S rP   rQ   rR   s    r#   tool_gateway_entitledz+NousPortalAccountInfo.tool_gateway_entitledN   rU   r"   )rN   r5   )r   r   r   r    r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rG   rH   rJ   rL   rM   r   propertyrT   rW   rY   r!   r"   r#   r4   r4   .   s        OOO!!!!KKK!G!!!! F    #I#### $J$$$$!%K%%%%%)O))))(,,,,,). ....'+++++%)J))))E#I####9=L====*.....DHHHHH+/J////,0K0000E0 0 0 X0 1 1 1 X1 0 0 0 X0 0 0r"   r4   account_infoOptional[NousPortalAccountInfo]rN   strc                    	 ddl m} n# t          $ r d}Y nw xY wd}| | j        }t	          |t
                    r|                                s|}|                    d           dS )z>Return the billing URL for a normalized Nous account snapshot.r   )DEFAULT_NOUS_PORTAL_URLhttps://portal.nousresearch.comN/z/billing)hermes_cli.authr_   	Exceptionr?   
isinstancer]   striprstrip)r[   r_   bases      r#   nous_portal_billing_urlrh   S   s    D;;;;;;; D D D"CD D+dC   '

 '&kk#((((s   	 zthis feature)
capabilityinclude_refresh_hintri   rj   r5   r   c                  t          |           }| | j        du rdS | 	d| d| dS | j        s| j        r	d| d| dS d| d	| dS | j        -d
| d}| j        r|d| j         dz  }|r|dz  }|d| dz  }|S | j        }|r|j        nd}|dk    rd| dS |dk    s	| j        du r!t          | ||          }|r| j        s|dz  }|S d| d| dS )a  Return user-facing guidance for a missing Nous paid entitlement.

    ``None`` means the account is known to have paid service access.  The
    message intentionally works from normalized entitlement fields rather than
    subscription price alone: purchased credits without a subscription still
    count as paid access, while a paid subscription with exhausted usable
    credits does not.
    NTz9Hermes could not verify your Nous Portal entitlement, so zO is unavailable. Run `hermes model` to refresh your login, or check billing at .zeNous inference credentials are configured, but Hermes cannot verify your Nous Portal paid access for zc. Log in with `hermes model` to enable Portal-managed features. Billing and credits are managed at zLog in to Nous Portal to use z9: run `hermes model`. Billing and credits are managed at z9Hermes could not verify your Nous Portal paid access, so z is unavailable.z Account lookup failed: z, Run `hermes model` to refresh your session.z Check billing at account_missingzOHermes could not find a Nous Portal account or organisation for this login, so zi is unavailable. Run `hermes model` to authenticate again; if the problem persists, contact Nous support.no_usable_creditsFzF If you recently bought credits, run `hermes model` to refresh Hermes.zIYour Nous Portal account does not currently have paid service access, so 2 is unavailable. Add credits or update billing at )	rh   rH   r6   rA   r   rJ   r)   _no_paid_access_messager9   )r[   ri   rj   billing_urldetailaccessr)   messages           r#   &format_nous_portal_entitlement_messageru   b   s    *,77KL$D$L$Lt)
 ) )%) ) )	
 ! 
4 	94>9 9 +69 9 9AJ A A2=A A A	

 '/
    	  	GF1CFFFFF 	EDDF5{55552F$.V]]$F"""R#R R R	
 $$$(HE(Q(Q),
KPP 	`(: 	`__G	[	[ 	[LW	[ 	[ 	[r"   rq   c                Z   | j         }|r|j        nd }|r|j        nd }|r|j        nd }|r|j        nd }|r|j        nd }|r|rt          |||          }	d|	 d| d| dS |r|du r	d| d| dS |du rt          |||          }	d|	 d| d	| dS t          |||          }	d
|	 d| d| dS )Nz&Your Nous Portal credits are exhaustedz, so z, is unavailable. Top up or renew credits at rl   FzGYour current Nous Portal plan does not include paid service access, so z+ is unavailable. Upgrade or add credits at zEYour Nous Portal account has no active subscription or usable creditsz- is unavailable. Subscribe or add credits at z3Your Nous Portal account has no usable paid creditsro   )rJ   r,   r-   r2   r0   r1   _credit_detail)
r[   ri   rq   rs   r,   r-   total_usablesubscription_creditspurchased_creditscredit_details
             r#   rp   rp      s   
 2F@FPf<<DHN"X&"D"DTX28B6..dLDJT6@@PT>DN::$ 
#> 
&|5IK\]]I] I I I I:EI I I	

  
#>%#G#GXX XITX X X	

 %''&|5IK\]]!! !#-! !! ! !	
 #<1EGXYYM	Xm 	X 	X	X 	XIT	X 	X 	Xr"   rx   r   ry   rz   c                    g }| |                     d| d           ||                     d|d           ||                     d|d           |sdS dd                    |           dS )	Nzusable $z.2fzsubscription $zpurchased $ z (z, ))appendjoin)rx   ry   rz   partss       r#   rw   rw      s    
 E2222333'@&:@@@AAA$:#4:::;;; r#		%  ####r"   Nonec                 
    da dS )z7Clear the short-lived account-info cache used by tests.N)r   r!   r"   r#   $reset_nous_portal_account_info_cacher      s     r"   F)force_freshmin_jwt_ttl_secondsr   r   intc                   	 ddl m}  |d          pi }n(# t          $ r}t          |d          cY d}~S d}~ww xY w|                    d          }t          |          }t          |t                    r|                                s<t          | ||          }||S t          |          }||S t          dd	d|
          S | st          ||||          }	|	|	S t          || |          S )af  Return normalized Nous Portal account entitlement information.

    By default, a valid unexpired OAuth access JWT is used as a low-latency
    local account snapshot. ``force_fresh=True`` always calls
    ``/api/oauth/account`` and bypasses the short-lived cache. JWT claims are
    decoded locally for UX gating only; server APIs remain authoritative.
    r   )get_provider_auth_statenousF)r   r6   Naccess_token)r   r   r?   r   )r6   r8   r9   r?   stater?   r   )r   r   r?   )rb   r   rc   _error_infoget_portal_base_urlrd   r]   re   _info_from_oauth_pool_info_from_inference_key_poolr4   _info_from_valid_jwt_fresh_account_info)
r   r   r   r   excr   r?   pool_oauth_info	pool_infojwt_infos
             r#   get_nous_portal_account_infor      st   7;;;;;;''//52 7 7 76666666667 99^,,L&u--OlC(( 
0B0B0D0D 
/# 3+
 
 

 &""1/BB	 $+	
 
 
 	
  '+ 3	
 
 
 O'   s    
;6;;r   dict[str, Any]r?   c           	        	 ddl m}m}  |            } |d          p| }t          |          p|}t	          ||          }|s9t
          2t
          \  }}	}
||k    r!t          j                    |	z
  t          k     r|
S t          ||          }|st          dd|          S t          |                    d          t                    r(t          |                    d          pdd||	          S t          |||
          }|t          j                    |fa|S # t          $ r<}t          |t!          |                     d                    |          cY d }~S d }~ww xY w)Nr   )r   resolve_nous_access_tokenr   empty_account_responseTr   r6   r?   r   account_response_errorr   r6   r?   rM   r   r?   r   )rb   r   r   r   
_cache_keyr   time	monotonic_ACCOUNT_INFO_CACHE_TTL_fetch_nous_account_infor   rd   r   r]   _info_from_account_payloadrc   r5   )r   r   r?   r   r   r   refreshed_state	cache_key
cached_key	cached_atcached_infopayloadinfor   s                 r#   r   r   !  s   (
VVVVVVVV002211&99BU*?;;N|_==	 	#2>1D.J	;Y&&DN,<,<y,HLc+c+c""*<II 	. /   
 gkk'**C00 	kk'**F.F /#	    *!+
 
 

  )$.*:*:DA 
 
 
599^4455+
 
 
 	
 	
 	
 	
 	
 	

s1   A:D =#D !AD 1)D 
E!%1EE!E!c                   	 t                      }|dS t          |dd          pt          |dd          }t          |t                    r|                                sdS t          dddt          |dd          p| t          |dd          p!t          |d	d          pt          |d
d          ddt          |dd           d          S # t          $ r Y dS w xY w)zEReturn an explicit unknown-entitlement snapshot for opaque Nous keys.Nruntime_api_keyr   r}   Fr   r?   r@   runtime_base_urlbase_urlTpool:labelunknownportal_oauth_missing)r6   r8   r9   r?   r@   rA   rB   r   )_select_nous_pool_entrygetattrrd   r]   re   r4   rc   )r?   entryruntime_keys      r#   r   r   T  s   '))=4e%6==cP^`bAcAc+s++ 	;3D3D3F3F 	4$"0$77 #" 3T:: 45"4d;;45*d33)-JgeWi&H&HJJ(
 
 
 	
"    tts   C AC !A*C 
CCc           
     n   	 t                      }n# t          $ r Y d S w xY w|t          |          sd S t          |dd           }t	          |t
                    r|                                sd S t          |dd           p|}|t          |dd           t          |dd           p!t          |dd           pt          |dd           t          |dd           dt          |d	d
           d}| st          ||||          }||S 	 t          ||          }n)# t          $ r}	t          |	d|          cY d }	~	S d }	~	ww xY w|st          dd|          S t	          |
                    d          t
                    r(t          |
                    d          pdd||          S t          |||          S )Nr   r?   r<   r@   r   r   	agent_keyr   r   r   )r   r<   r@   r   rB   r   Tr   r   r   r   r   r   )r   rc   _pool_entry_is_portal_oauthr   rd   r]   re   r   r   r   r   r   )
r   r   r?   r   r   entry_portal_urlr   r   r   r   s
             r#   r   r   u  sm   '))   tt}7>>}t5.$77LlC(( 0B0B0D0D t 	($// 	 
 %UK66E/66 0u0$770uj$//UK66IWUGY%G%GII
 
E  ', 3	
 
 
 O
*<9IJJ 
 
 
,
 
 
 	
 	
 	
 	
 	
 	

  
*,
 
 
 	

 '++g&&,, 
++g&&B*B,	
 
 
 	
 &(   s*    
D 
D>"D93D>9D>Optional[Any]c                     ddl m}   | d          }|r|                                sd S t          |                                          }|sd S d
d}t          ||	          S )Nr   )	load_poolr   r   r   rN   tuple[float, float, int]c                    t          t          | dd                     pd}t          t          | dd                     pd}t          t          | dd          pd          }||| fS )Nagent_key_expires_atg        rC   priorityr   )_parse_iso_timestampr   r   )r   	agent_exp
access_expr   s       r#   _entry_sort_keyz0_select_nous_pool_entry.<locals>._entry_sort_key  so    (8NPT)U)UVV]Z]	)'%t*L*LMMTQT
wuj!449:::y11r"   )key)r   r   rN   r   )agent.credential_poolr   has_credentialslistentriesmax)r   poolr   r   s       r#   r   r     s    //////9VD t++-- t4<<>>""G t2 2 2 2 wO,,,,r"   r   r   c                l   t          | dd           }t          |t                    r|                                sdS t          t          | dd          pd                                                                          }t          | dd           }|                    d          pt          |          S )Nr   F	auth_typer}   refresh_tokenoauth)r   rd   r]   re   lower
startswithr5   )r   r   r   r   s       r#   r   r     s    5.$77LlC(( 0B0B0D0D uGE;339r::@@BBHHJJIE?D99M((?D,?,??r"   r   c                   |pd                     d          }| d}d|  dd}t          j                            ||          }t          j                            |d	          5 }t          j        |                                                                          }d d d            n# 1 swxY w Y   t          |t                    r|ni S )
Nr`   ra   z/api/oauth/accountzBearer zapplication/json)AuthorizationAccept)headers   )timeout)rf   urllibrequestRequesturlopenjsonloadsreaddecoderd   dict)r   r?   rg   urlr   reqrespr   s           r#   r   r     s
    @@HHMMD
%
%
%C1<11$ G .
 
 g
 
6
6C			Q		/	/ 34*TYY[[//11223 3 3 3 3 3 3 3 3 3 3 3 3 3 3 $//777R7s   '9B,,B03B0tokenc          
        	 ddl m} n# t          $ r Y d S w xY w ||           }|sd S t          |                    d                    }|5|t          j                    t          dt          |                    z   k    rd S t          |                    d                    }t          |                    d                    }t          ||t          |                    d                    |          }	t          di dd	d
ddddt          |                    d                    dt          |                    d                    dt          |                    d          p|                    d                    dt          |                    d                    dt          |                    d                    d|dt          |                    d                    dd	dt          |                    d                    pddt          j        |t          j                  d|d|	dt#          |          S )Nr   )_decode_jwt_claimsexpr(   r.   r;   )r'   r(   r*   r.   r6   Tr8   r
   r9   Fr:   subr<   r=   r>   r?   r@   rA   rB   
auth_storerC   )tzrH   rJ   rL   r!   )rb   r   rc   _coerce_floatr   r   r   r   _coerce_bool_coerce_intr%   _coerce_strr4   r   fromtimestampr   utcr   )
r   r   r?   r   r   claimsr   r(   r.   access_infos
             r#   r   r     s   6666666   tt  &&F t


5))
*
*C
{cTY[[3q#6I2J2J+K+KKKKtvzz-8899K#FJJ/B$C$CDD+#FJJx$8$899+	  K !   $u e FJJu--...	
 6::h//000 fjj55O;9O9OPPP vzz,77888  

= 9 9::: ( 'uyy1E'F'FGGG &*T &eii0C&D&DEEU )#(,???? (K "-  <<<! s   	 
r   c                  t          |                     d          t                    r|                     d          ni }t          |                     d          t                    r|                     d          ni }t          |                     d                    }t	          |                     d                    }|r|j        nd }|	||j        }t          dddt          |                    d                    p
|r|j	        nd t          |                    d                    |t          |                    d	                    t          |                    d
          p|                    d                    t          |                    d                    pdt          |                    d                    t          |                    d                    |||t          |                     S )NuserorganisationrG   rH   Tr   idr<   r@   r   r   rB   r   rD   rE   )r6   r8   r9   r;   r<   r?   r@   rA   rB   rD   rE   rG   rH   rJ   rM   )rd   r   r   _subscription_from_payload!_paid_service_access_from_payloadr'   r(   r4   r   r*   r5   )r   r   r?   r   r   rG   rs   r(   s           r#   r   r     s    #-W[[-@-@$"G"GO7;;vRD gkk.11488	N### 
 .gkk..I.IJJL.w{{;P/Q/QRRF$*4&..Kv1( <++D1122bQW7av7M7M]aeii4455'&uyy1E'F'FGG%)%))N*C*C*]uyyQ\G]G]%^%^%eii0C&D&DEEU$((7++,,dhh{3344!'!'MM   r"   valuerF   c                   t          | t                    sd S t          t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                              S )Nr   r   r   r   r   r   )r   r   r   r   r   r   )rd   r   r   r   r   r   r   r   s    r#   r   r   >  s    eT"" t%6**++6**++$UYY/?%@%@AA&uyy1E'F'FGG'		2E(F(FGG&uyy1C'D'DEE   r"   rI   c                n   t          | t                    sd S t          |                     d                    }t          |                     d                    }t	          ||t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d                    t          |                     d	                    t          |                     d
                    t          |                     d                    t          |                     d                              S )Nr'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   )r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   )rd   r   r   r   r%   r   r   r   )r   r'   r(   s      r#   r   r   K  sW   eT"" t599Y//00Guyy7788K$599X..//#EII.?$@$@AA#EII.?$@$@AA ,UYY7P-Q-Q R R$0;X1Y1Y$Z$Z%eii0C&D&DEE$1%))<Y2Z2Z$[$['4UYY?_5`5`'a'a$1%))<Y2Z2Z$[$[*5995K+L+LMM   r"   )r?   rM   r   objectr6   rM   rK   c           
     F    t          |dd||t          |                     S )Nr   F)r6   r8   r9   r?   rM   r   )r4   r]   r   s       r#   r   r   `  s3     !'%jj   r"   c                    |                      d          }t          |t                    r|                                sd S |                                                    d          S )Nr?   ra   )r   rd   r]   re   rf   )r   r   s     r#   r   r   q  sV    II'((EeS!!  t;;==$$$r"   c                    t          j        |                     d                                                    }|pd d| S )Nzutf-8r}   :)hashlibsha256encode	hexdigest)r   r?   digests      r#   r   r   x  sD    ^L//8899CCEEF#..f...r"   c                   t          | t                    r| sd S |                                 }|                    d          r|d d         dz   }	 t	          j        |                                          S # t          $ r Y d S w xY w)NZz+00:00)rd   r]   re   endswithr   fromisoformat	timestamprc   )r   texts     r#   r   r   }  s    eS!!  t;;==D}}S $CRCy8#%d++55777   tts   %A7 7
BBc                8    t          | t                    r| r| S d S N)rd   r]   r   s    r#   r   r     s%    % % 4r"   r&   c                4    t          | t                    r| nd S r  )rd   r5   r   s    r#   r   r     s    ud++5555r"   r   c                    t          | t                    rd S 	 | d S t          |           S # t          t          f$ r Y d S w xY wr  )rd   r5   r   	TypeError
ValueErrorr   s    r#   r   r     s[    % t=45zzz"   tt   , , A Ac                    t          | t                    rd S 	 | d S t          |           S # t          t          f$ r Y d S w xY wr  )rd   r5   floatr  r  r   s    r#   r   r     s[    % t=4U||z"   ttr  r  )r[   r\   rN   r]   )r[   r\   ri   r]   rj   r5   rN   r   )r[   r4   ri   r]   rq   r]   rN   r]   )rx   r   ry   r   rz   r   rN   r]   )rN   r   )r   r5   r   r   rN   r4   )r   r   r   r5   r?   r   rN   r4   )r?   r   rN   r\   )r   r5   r   r   r?   r   rN   r\   )rN   r   )r   r   rN   r5   )r   r]   r?   r   rN   r   )
r   r]   r   r   r?   r   r   r   rN   r\   )r   r   r   r   r?   r   rN   r4   )r   r   rN   rF   )r   r   rN   rI   )
r   r  r6   r5   r?   r   rM   rK   rN   r4   )r   r   rN   r   )r   r]   r?   r   rN   r]   )r   r   rN   r   )r   r   rN   r   )r   r   rN   r&   )r   r   rN   r   )/__doc__
__future__r   r  r   r   urllib.requestr   dataclassesr   r   r   typingr   r   r	   r7   r   r   r    r   r%   r4   rh   ru   rp   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r!   r"   r#   <module>r!     s   9 9 9 " " " " " "        ! ! ! ! ! ! ' ' ' ' ' ' ' ' ) ) ) ) ) ) ) ) ) )   VW  IM  M M M M $- - - - - - - - $1 1 1 1 1 1 1 1 $!0 !0 !0 !0 !0 !0 !0 !0H) ) ) ) )$ %!%	E E E E E EP% % % %P$ $ $ $"    !5 5 5 5 5 5p0
 0
 0
 0
f   BD D D DN- - - -&@ @ @ @ &*8 8 8 8 8 . . . .b" " " "J
 
 
 
   2 &*,0     "% % % %/ / / /
	 	 	 	   6 6 6 6        r"   