
    $j n                       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	m
Z
mZ ddlmZmZ ddlmZmZmZ ed         ZdZd	Zdad
ed<    ej                    Z e
d           G d d                      Z e
d           G d d                      Z e
d           G d d                      Z e
d           G d d                      ZdZd[dZddddd\d"Zd]d$Zd^d)Z d_d+Z!d,d	d-d`d1Z"dad5Z#dbd6Z$dcd7Z%ddd9Z&ded<Z'	 dZdfd>Z(dgd@Z)dhdBZ*didEZ+djdGZ,dkdIZ-dddJdldPZ.dmdQZ/dndRZ0dodSZ1dpdTZ2dqdVZ3drdXZ4dodYZ5dS )sz3Normalized Nous Portal account entitlement helpers.    )annotationsN)	dataclassfield)datetimetimezone)AnyLiteralOptional)jwtaccount_apiinference_keynoneerror)	firecrawlfalz	fal-videozopenai-audiozbrowser-usemodal<   z1tuple[str, float, 'NousPortalAccountInfo'] | None_account_info_cacheT)frozenc                  r    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S )NousPortalSubscriptionInfoNOptional[str]planOptional[int]tierOptional[float]monthly_chargemonthly_creditscurrent_period_endcredits_remainingrollover_credits)__name__
__module____qualname__r   __annotations__r   r   r   r   r    r!        6/usr/local/lib/hermes-agent/hermes_cli/nous_account.pyr   r   $   s         DD&*N****'+O++++(,,,,,)-----(,,,,,,,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/   r0   r1   r2   r3   r4   r5   r6   r7   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                  D    e Zd ZU dZdZded<    ee          Zded<   dS )	NousToolAccessInfoa/  Free tool-pool entitlement, decoupled from paid/billing access.

    Mirrors the Portal's ``tool_access`` claim/field: ``enabled`` is true when a
    positive tool-pool balance is live and not gated off; ``coverage`` maps each
    tool category to whether the pool funds it (FAL video is excluded).
    Fboolenabled)default_factoryzdict[str, bool]coverageN)	r"   r#   r$   __doc__r;   r%   r   dictr=   r&   r'   r(   r9   r9   ?   sM           G %d ; ; ;H;;;;;;r'   r9   c                     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 <   dZded!<   ed)d#            Zed)d$            Zed)d%            Zd*d(ZdS )+NousPortalAccountInfor:   	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[NousToolAccessInfo]tool_accessOptional[dict[str, Any]]
raw_claimsraw_accountr   returnc                    | j         du S )NTrT   selfs    r(   is_paidzNousPortalAccountInfo.is_paide   s    '4//r'   c                    | j         du S )NFr^   r_   s    r(   is_free_tierz"NousPortalAccountInfo.is_free_tieri   s    '500r'   c                B    | j         du rdS | j        duo| j        j        S )zCoarse "entitled to any managed tool" gate: paid access OR a live
        free tool pool. Use :meth:`tool_gateway_entitled_for` to gate a specific
        tool category (the pool does not cover every category).TN)rT   rX   r;   r_   s    r(   tool_gateway_entitledz+NousPortalAccountInfo.tool_gateway_entitledm   s0    
 #t++4t+H0@0HHr'   categorystrc                    | j         du rdS | j        }t          |o"|j        o|j                            |          du           S )zWhether a specific tool category is entitled. Paid users are entitled
        everywhere; free tool-pool users only where ``coverage[category]`` is
        true (e.g. image but not video).T)rT   rX   r:   r;   r=   get)r`   rf   tas      r(   tool_gateway_entitled_forz/NousPortalAccountInfo.tool_gateway_entitled_forv   sL     #t++4BK2:K"+//(*C*Ct*KLLLr'   )r\   r:   )rf   rg   r\   r:   )r"   r#   r$   r%   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rS   rT   rV   rX   rZ   r[   r   propertyra   rc   re   rk   r&   r'   r(   rA   rA   L   s        OOO!!!!KKK!G!!!! F    #I#### $J$$$$!%K%%%%%)O))))(,,,,,). ....'+++++%)J))))E#I####9=L====*.....DHHHHH04K4444+/J////,0K0000E0 0 0 X0 1 1 1 X1 I I I XIM M M M M Mr'   rA   account_infoOptional[NousPortalAccountInfo]r\   rg   c                    	 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.authrp   	ExceptionrK   
isinstancerg   striprstrip)rm   rp   bases      r(   nous_portal_billing_urlry      s    D;;;;;;; D D D"CD D+dC   '

 '&kk#((((s   	 zthis feature)
capabilityinclude_refresh_hintcoverage_categoryrz   r{   r:   r|   r   c                  t          |           }| 2|'|                     |          rdS | j        r| d| dS n	| j        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 )u   Return user-facing guidance for a missing Nous tool-gateway entitlement.

    ``None`` means the account is entitled to use the capability — via paid
    service access OR a live free tool pool that covers it. The message 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.

    ``coverage_category`` scopes the check to a single tool category (e.g.
    ``"fal-video"``). When given, a user who is entitled overall but whose
    access does not fund that category gets a neutral billing nudge instead of a
    message implying their credits are exhausted. The pool-vs-paid distinction is
    never surfaced to the user.
    Nzd isn't included with your current Nous Portal access. Add credits or a subscription to enable it at .z9Hermes 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 )ry   rk   re   rB   rM   rT   r   rV   r.   _no_paid_access_messagerE   )	rm   rz   r{   r|   billing_urldetailaccessr.   messages	            r(   &format_nous_portal_entitlement_messager      sd   * *,77K(556GHH t1 
 " \ \MX\ \ \	 / 	4)
 ) )%) ) )	
 ! 
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'   r   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 r~   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 creditsr   )rV   r1   r2   r7   r5   r6   _credit_detail)
rm   rz   r   r   r1   r2   total_usablesubscription_creditspurchased_creditscredit_details
             r(   r   r      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'   r   r   r   r   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)r   r   r   partss       r(   r   r     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   rB   Naccess_token)r   r   rK   r   )rB   rD   rE   rK   staterK   r   )r   r   rK   )rs   r   rt   _error_infori   _portal_base_urlru   rg   rv   _info_from_oauth_pool_info_from_inference_key_poolrA   _info_from_valid_jwt_fresh_account_info)
r   r   r   r   excr   rK   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]rK   c           	     \   	 ddl m}m}  |            } |d          p| }t          |          p|}t	          ||          }t
          5  |sEt          >t          \  }}	}
||k    r-t          j                    |	z
  t          k     r|
cd d d            S d d d            n# 1 swxY w Y   t          ||          }|st          dd|          S t          |                    d          t                    r(t          |                    d          pdd||	          S t          |||
          }t
          5  |t          j                    |fad d d            n# 1 swxY w Y   |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   rB   rK   r   account_response_errorr   rB   rK   r[   r   rK   r   )rs   r   r   r   
_cache_key_ACCOUNT_INFO_CACHE_LOCKr   time	monotonic_ACCOUNT_INFO_CACHE_TTL_fetch_nous_account_infor   ru   ri   rg   _info_from_account_payloadrt   r:   )r   r   rK   r   r   r   refreshed_state	cache_key
cached_key	cached_atcached_infopayloadinfor   s                 r(   r   r   a  s   *
VVVVVVVV002211&99BU*?;;N|_==	% 	' 	' '#6#B5H2
I{**0@0@90LPg/g/g&		' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' +<II 	. /   
 gkk'**C00 	kk'**F.F /#	    *!+
 
 

 & 	F 	F#,dn.>.>"E	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 	F 
 
 
599^4455+
 
 
 	
 	
 	
 	
 	
 	

sy   AE% 	;BE% E% B!!E% $B!%&E% AE% E% 5EE% EE% E E% %
F+/1F& F+&F+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   rK   rL   runtime_base_urlbase_urlTpool:labelunknownportal_oauth_missing)rB   rD   rE   rK   rL   rM   rN   r   )_select_nous_pool_entrygetattrru   rg   rv   rA   rt   )rK   entryruntime_keys      r(   r   r     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   rK   rH   rL   r   r   	agent_keyr   r   r   )r   rH   rL   r   rN   r   Tr   r   r   r   r   r   )r   rt   _pool_entry_is_portal_oauthr   ru   rg   rv   r   r   r   ri   r   )
r   r   rK   r   r   entry_portal_urlr   r   r   r   s
             r(   r   r     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   r\   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        rO   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   r\   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   ru   rg   rv   lower
startswithr:   )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 )
Nrq   rr   z/api/oauth/accountzBearer zapplication/json)AuthorizationAccept)headers   )timeout)rw   urllibrequestRequesturlopenjsonloadsreaddecoderu   r?   )r   rK   rx   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#          |                    d                    dt%          |          S )Nr   )_decode_jwt_claimsexpr-   r3   rG   )r,   r-   r/   r3   rB   TrD   r   rE   FrF   subrH   rI   rJ   rK   rL   rM   rN   
auth_storerO   )tzrT   rV   rX   rZ   r&   )rs   r   rt   _coerce_floatri   r   r   r   _coerce_bool_coerce_intr*   _coerce_strrA   r   fromtimestampr   utc_tool_access_from_valuer?   )
r   r   rK   r   r   claimsr   r-   r3   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 "-  ,FJJ},E,EFFF!" <<<# 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i ddddd	dd
t          |                    d                    p
|r|j	        nd dt          |                    d                    d|dt          |                    d                    dt          |                    d          p|                    d                    dt          |                    d                    pddt          |                    d                    dt          |                    d                    d|d|d|dt          |                     d                    dt          |           S )NuserorganisationrS   rT   rB   TrD   r   rE   rG   idrH   rK   rL   rM   r   r   rN   r   rP   rQ   rV   rX   r[   r&   )ru   ri   r?   _subscription_from_payload!_paid_service_access_from_payloadr,   r-   rA   r  r/   r:   r  )r   r   rK   r  r  rS   r   r-   s           r(   r   r   \  sr    #-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 <++D1122bQW7av7M7M]a	
 eii44555 ( 'uyy1E'F'FGGG &*%))N*C*C*]uyyQ\G]G]%^%^%^ &eii0C&D&DEEU $((7++,,, dhh{33444 "\ (K "( ,GKK,F,FGGG  MMM! r'   valuerW   c                ^   t          | t                    sdS t          |                     d                    du }|                     d          }i }t          |t                    r6|                                D ]!\  }}t          |t
                    r|du ||<   "t          ||          S )zParse a Portal ``tool_access`` object (from the JWT claim or the account
    API) into :class:`NousToolAccessInfo`. Fails closed: a non-object value
    yields ``None``, and only literal ``true`` counts for ``enabled`` and each
    coverage entry.Nr;   Tr=   )r;   r=   )ru   r?   r  ri   itemsrg   r9   )r  r;   raw_coverager=   r   vals         r(   r  r    s    
 eT"" t599Y//00D8G99Z((L "H,%% ,$**,, 	, 	,HC#s## , #tgAAAAr'   rR   c                   t          | t                    sd S t          t          |                     d                    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   r    r!   )ru   r?   r   r  ri   r  r  r  s    r(   r  r    s    eT"" t%6**++6**++$UYY/?%@%@AA%eii0A&B&BCC&uyy1E'F'FGG'		2E(F(FGG&uyy1C'D'DEE   r'   rU   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/   r0   r1   r2   r3   r4   r5   r6   r7   )r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   )ru   r?   r  ri   r*   r  r  r  )r  r,   r-   s      r(   r  r    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'   )rK   r[   r   objectrB   r[   rY   c           
     F    t          |dd||t          |                     S )Nr   F)rB   rD   rE   rK   r[   r   )rA   rg   r   s       r(   r   r     s3     !'%jj   r'   c                    |                      d          }t          |t                    r|                                sd S |                                                    d          S )NrK   rr   )ri   ru   rg   rv   rw   )r   r  s     r(   r   r     sV    II'((EeS!!  t;;==$$$r'   c                    t          j        |                     d                                                    }|pd d| S )Nzutf-8r   :)hashlibsha256encode	hexdigest)r   rK   digests      r(   r   r     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)ru   rg   rv   endswithr   fromisoformat	timestamprt   )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)ru   rg   r  s    r(   r  r    s%    % % 4r'   r+   c                4    t          | t                    r| nd S r*  )ru   r:   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*  )ru   r:   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*  )ru   r:   floatr-  r.  r  s    r(   r  r    s[    % t=4U||z"   ttr/  r*  )rm   rn   r\   rg   )
rm   rn   rz   rg   r{   r:   r|   r   r\   r   )rm   rA   rz   rg   r   rg   r\   rg   )r   r   r   r   r   r   r\   rg   )r\   r   )r   r:   r   r   r\   rA   )r   r   r   r:   rK   r   r\   rA   )rK   r   r\   rn   )r   r:   r   r   rK   r   r\   rn   )r\   r   )r   r   r\   r:   )r   rg   rK   r   r\   r   )
r   rg   r   r   rK   r   r   r   r\   rn   )r   r   r   r   rK   r   r\   rA   )r  r   r\   rW   )r  r   r\   rR   )r  r   r\   rU   )
r   r  rB   r:   rK   r   r[   rY   r\   rA   )r   r   r\   r   )r   rg   rK   r   r\   rg   )r  r   r\   r   )r  r   r\   r   )r  r   r\   r+   )r  r   r\   r   )6r>   
__future__r   r  r   	threadingr   urllib.requestr   dataclassesr   r   r   r   typingr   r	   r
   rC   TOOL_COVERAGE_CATEGORIESr   r   r%   Lockr   r   r*   r9   rA   ry   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'   r(   <module>r9     sR   9 9 9 " " " " " "            ( ( ( ( ( ( ( ( ' ' ' ' ' ' ' ' ) ) ) ) ) ) ) ) ) )   VW    IM  M M M M)9>++  $- - - - - - - - $1 1 1 1 1 1 1 1 $	< 	< 	< 	< 	< 	< 	< 	< $0M 0M 0M 0M 0M 0M 0M 0Mf) ) ) ) )$ %!%'+X X X X X Xv% % % %P$ $ $ $"    !5 5 5 5 5 5p2
 2
 2
 2
j   BD D D DN- - - -&@ @ @ @ &*8 8 8 8 8 / / / /d# # # #LB B B B"      2 &*,0     "% % % %/ / / /
	 	 	 	   6 6 6 6        r'   