+
    jHàjr/  ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHtH	t	H
t
Ht ^ RIHtHtHt ]P                   ! R4      tRtRt]	! RR	7       ! R
 R4      4       t]P*                  ! 4       tRsR]R&   ]P2                  ! 4       tRsRs]P*                  ! 4       tRsR]R&   R0tR R lt ]3R R llt!R R lt"R R lt#R R lt$R R lt%R R lt&R R  lt'R!R/R" R# llt(R$ R% lt)R& R' lt*R!R/R( R) llt+R* R+ lt,R, R- lt-R. R/ lt.R# )1a±  Record of who carries inference, for ``setup.status`` and ``setup.ready``.

It runs once per process on a daemon thread: at ``hermes serve`` boot, and on the gateway when the
local Desktop first connects (``tui_gateway.methods_onboarding.begin_local_desktop_boot``). It never
creates an identity: the desktop's welcome-trial claim (``hermes_cli.welcome_trial``) and the first
hosted connector action are the only creators. For the desktop's local backend it first records a
fresh install's onboarding decision (``onboarding_run.latch_first_install``) and settles a claim cut
off before its marker write (``welcome_trial.settle_interrupted_claim``). Then it inventories
credentials cheap-first, resolves which provider carries inference, records the answer in process
memory, and tells every connected client with one ``setup.ready`` event. ``free_tier.status`` and
``setup.status`` read the record; provider resolution never reaches the portal.
)ÚannotationsN)ÚasdictÚ	dataclassÚfieldÚreplace)ÚAnyÚDictÚOptionalzhermes_cli.authg       @zsetup.readyT)Úfrozenc                  óÖ   € ] tR t^t$ RtR]R&   R]R&   R]R&   R]R&   R]R&   R	tR]R
&   ]! ]R7      t	R]R&   ]! ]
P                  R7      tR]R&   ]R R l4       tR R ltR R ltRtR# )ÚSetupRecordzlWhat the bootstrap found. One shape for every reader; no version field (renderer and backend
ship together).ÚboolÚprovider_configuredÚstrÚinference_providerÚfree_tier_accountÚhas_identityÚother_providersÚ Úerror)Údefault_factoryúdict[str, Any]ÚfailureÚfloatÚfinished_atc               ó   € V ^8„  d   QhRR/# ©é   Úreturnr   © )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/hermes_cli/free_tier_bootstrap.pyÚ__annotate__ÚSetupRecord.__annotate__/   s   € ÷ Lñ L ñ Ló    c                	óH   € V P                   ;'       d    V P                  R 8H  # )Únous)r   r   ©Úselfs   &r!   Úfree_tier_routeÚSetupRecord.free_tier_route.   s!   € à×%Ñ%×KÐK¨$×*AÑ*AÀVÑ*KÐKr$   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r    s   "r!   r"   r#   2   s   € ÷ ñ ˜Nñ r$   c                	óz   € \        V 4      pVP                  VP                  R 4      4       V P                  VR&   V# )r   r)   )r   ÚupdateÚpopr)   )r(   Úpayloads   & r!   Ú
as_payloadÚSetupRecord.as_payload2   s8   € ô ˜“,ˆØ�‰�w—{‘{ 9Ó-Ô.Ø%)×%9Ñ%9ˆÐ!Ñ"Øˆr$   c               ó   € V ^8„  d   QhRR/# r,   r   )r    s   "r!   r"   r#   :   s   € ÷ "ñ " ñ "r$   c                	ó,   € \        V P                  4      # )N)Údictr   r'   s   &r!   Úfailure_fieldsÚSetupRecord.failure_fields:   s   € Ü�D—L‘LÓ!Ð!r$   r   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__r   r   r5   r   Útimer   Úpropertyr)   r1   r6   Ú__static_attributes__r   r$   r!   r   r      sw   ‡ ñð ÓØÓØÓØÓØÓØ€Eˆ3ƒOñ $°DÔ9€Gˆ^Ó9Ù¨t¯y©yÔ9€K�Ó9àôLó ðLõ÷"ñ "r$   r   úOptional[SetupRecord]Ú_recordFzOptional[tuple]Ú_inventory_stampc               ó   € V ^8„  d   QhRR/# ©r   r   rA   r   )r    s   "r!   r"   r"   J   s   € ÷ ñ Ð-ñ r$   c                 ó   € \         # )z7The record, or None until the first bootstrap finishes.)rB   r   r$   r!   Úcurrent_recordrG   J   s   € ä€Nr$   c               ó    € V ^8„  d   QhRRRR/# )r   Útimeoutr   r   rA   r   )r    s   "r!   r"   r"   O   s   € ÷ 	ñ 	˜Uð 	ÐBWñ 	r$   c                ó\   € \         '       g   R# \        P                  V 4       \        4       # )a‹  Block up to ``timeout`` seconds for a bootstrap that is IN FLIGHT, then return whatever it
produced, reconciled with any provider configured since (:func:`reconcile_record`). Returns
None at once when no bootstrap ever started in this process (a bare ``tui_gateway`` under
test, an old serve without the boot hook): the caller falls back to its live probe instead of
paying the wait for nothing.N)Ú_startedÚ_doneÚwaitÚreconcile_record)rI   s   &r!   Úwait_for_recordrO   O   s!   € ÷ ‹8ÙÜ	‡J�JˆwÔÜÓÐr$   c               ó   € V ^8„  d   QhRR/# rE   r   )r    s   "r!   r"   r"   [   s   € ÷ ñ Ð/ñ r$   c                 óâ  € \         p V e   V P                  '       d   V # ^ RIHpHp V! 4       V! V! 4       4      8w  g   \
        \        4       8X  d   V # \        4       '       g   \         # \        V RR\        4       \        P                  ! 4       R7      p\        ;_uu_ 4        \         V Jd   \         uuRRR4       # Vs RRR4       \        4        \        V4       V#   + '       g   i     L'; i)aL  Let a provider configured AFTER boot count: a record that says ``provider_configured:
false`` is re-inventoried once ``config.yaml`` / ``.env`` / ``auth.json`` moved since the
inventory that built it, and replaced (+ ``setup.ready``) when something now carries
inference. The identity and failure block are kept as is. A record that already says ``True`` is never re-probed, so the answer
only moves false -> true here. Every write path that assigns the main model (the Models page,
a picker key save) calls this for the immediate broadcast; ``setup.status`` calls it for
writes this process never saw (``hermes setup`` / ``hermes model`` from a shell, a hand edit).
The record is the LAUNCH profile's: a call scoped to another profile's home (a dashboard
write with ``?profile=B``) leaves it alone, or B's providers would open the launch gate.N)Úget_process_hermes_homeÚhermes_home_keyT)r   r   r   r   )rB   r   Úhermes_constantsrR   rS   rC   Ú_config_stampÚ_inventory_other_providersr   Ú_resolve_inferencer>   Ú_lockÚ_due_changedÚ
_broadcast)ÚrecordrR   rS   Ú	refresheds       r!   rN   rN   [   s³   € ô €FØ‚~˜×3×3Ð3ØˆßIÙÓ™OÑ,CÓ,EÓFÔFÔJZÔ^kÓ^mÔJmØˆÜ%×'Ò'ÜˆÜ˜°DÈ$Ü+=Ó+?ÌTÏYÊYË[ôZ€Iç	ŽÜ˜&Ó Ü÷ 
Šð ˆ÷ 
ô „NÜˆyÔØÐ÷ 
�ús   Â"CÂ=CÃC.	c               ó   € V ^8„  d   QhRR/# ©r   r   ÚNoner   )r    s   "r!   r"   r"   y   s   € ÷ ñ ˜ñ r$   c                 ó”   € \         ;_uu_ 4        R sRsRsR s\
        P                  4        R R R 4       R #   + '       g   i     R # ; i)NF)rX   rB   rK   Ú_settledrC   rL   Úclearr   r$   r!   Úreset_for_testsrc   y   s1   € ç	ŽØˆØˆØˆØÐÜ�‰Œ÷ 
��Šús	   �6¶A	c               ó   € V ^8„  d   QhRR/# )r   r   Útupler   )r    s   "r!   r"   r"   ƒ   s   € ÷ 
ñ 
�uñ 
r$   c                 ó  € ^ RI Hp  V ! 4       p. p\         FA  p W,          P                  4       pVP	                  VP
                  VP                  34       KC  	  \        V4      #   \         d    TP	                  R4        Ko  i ; i)é    )Úget_hermes_homeN)	Úhermes_cli.configrh   Ú_INVENTORY_FILESÚstatÚappendÚst_mtime_nsÚst_sizeÚOSErrorre   )rh   ÚhomeÚstampÚnameÚsts        r!   rU   rU   ƒ   ss   € Ý1ÙÓ€DØ€Eß ˆð	Ø•+×#Ñ#Ó%ˆBØ�L‰L˜"Ÿ.™.¨"¯*©*Ð5Ö6ñ !ô �‹<Ðøô ô 	Ø�L‰L˜×ð	ús   š=A&Á&BÂBc               ó   € V ^8„  d   QhRR/# r   r   )r    s   "r!   r"   r"   �   s   € ÷ ñ  Dñ r$   c                 óœ   € ^ RI Hp  \        4       s V ! RRR7      R8g  #   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)	aV  Is anything usable configured BESIDES the free tier? Asks the resolver ladder itself (the
thing that picks the provider for a turn) with the free-tier rung hidden: an explicit key, a
config pin, a sign-in or a host credential answers; nothing else falls through to
``no_provider_configured``. Not ``_has_any_provider_configured``: that first-run guard also
counts host credentials (gh auth, Claude Code) and a config pin, and it does not hide the
free-tier rung.

Stamps the config files BEFORE reading them, so a write that lands during the inventory is
seen by the next :func:`reconcile_record`.
©Úresolve_providerÚautoT)Úskip_free_tierr&   z8free tier bootstrap: nothing else carries inference (%s)NF)Úhermes_cli.authrw   rU   rC   Ú	ExceptionÚloggerÚdebug)rw   Úexcs     r!   rV   rV   �   sI   € õ 1Ü$“ÐðÙ °tÔ<ÀÑFÐFøÜô Ü�‰ÐOÐQTÔUÝûðús   ’ ŸAªAÁAc               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r    s   "r!   r"   r"   ¥   s   € ÷ ñ ˜Cñ r$   c                 ój   € ^ RI Hp   \        V ! R4      ;'       g    R4      #   \         d     R# i ; i)rg   rv   rx   r   )rz   rw   r   r{   rv   s    r!   rW   rW   ¥   s5   € Ý0ðÜÑ# FÓ+×1Ð1¨rÓ2Ð2øÜô Úðús   ˆ# œ# £2±2c               ó    € V ^8„  d   QhRRRR/# )r   Úotherr   r   r   r   )r    s   "r!   r"   r"   ­   s   € ÷ ñ ˜Dð  [ñ r$   c                ó¬  € ^ RI Hp VP                  4       pV'       d   / MVP                  4       ;'       g    / pV'       d   VP	                  V4      MRp\        T ;'       g4    T;'       g*    \        V4      ;'       d    VP                  V4      '       * \        4       T\        V4      T \        VP                  R4      ;'       g    R4      VR7      # )zJOne inventory pass into a record. Reads only: no identity is created here.©Ú	anon_authFr   r   )r   r   r   r   r   r   r   )Ú
hermes_clir…   Úcurrent_nous_stateÚlast_mint_failureÚfree_inference_activer   r   Úis_guest_staterW   r   Úget)r‚   r…   Ústater   r   s   $    r!   Ú_build_recordr�   ­   s®   € å$à&/×&BÑ&BÓ&D€Eß$)™b°	×0KÑ0KÓ0M×0SÐ0SÐQS€GßBG˜	×7Ñ7¸Ô>ÈUÐÜØ!×oÐoÐ%6×oÐo¼4À»;×;nÐ;nÈy×OgÑOgÐhmÓOnÔKnÜ-Ó/Ø+Ü˜%“[ØÜ�'—+‘+˜gÓ&×,Ð,¨"Ó-Øôð r$   Úannouncec               ó    € V ^8„  d   QhRRRR/# )r   rŽ   r   r   r   r   )r    s   "r!   r"   r"   ¿   s   € ÷ ñ ˜tð ¨{ñ r$   c                óî  € \         ;_uu_ 4        \        e   \        uuRRR4       # \        '       d2   \        P	                  \
        4       \        e   \        uuRRR4       # RsRRR4       \        4       p\        \        4       R7      p\         ;_uu_ 4        W!uss	\        P                  4        RRR4       V '       d   \        V4       V#   + '       g   i     Lr; i  + '       g   i     L8; i)zÚSettle an interrupted claim -> inventory -> resolve inference -> record ->
broadcast. Idempotent per process: a second call returns the existing record. Never raises.
``announce=False`` skips the ``setup.ready`` event.NT©r‚   )rX   rB   rK   rL   rM   ÚSETUP_READY_WAIT_SECONDSÚ_settle_installr�   rV   ra   ÚsetrZ   )rŽ   Úsettledr[   s   $  r!   Úrun_bootstrapr–   ¿   s    € ÷
 
ŽÜÒÜ÷ 
Š÷ ‹8Ü�J‰JÔ/Ô0ÜÒ"Ü÷ 
Šð ˆ÷ 
ô Ó€GÜÔ!;Ó!=Ô>€Fß	ŽØ"Ðˆ�Ü�	‰	Œ÷ 
÷ Ü�6ÔØ€M÷! 
�ú÷ 
�ús'   �C¨C´&CÁ%CÂC$ÃC!	Ã$C4	c               ó   € V ^8„  d   QhRR/# r   r   )r    s   "r!   r"   r"   ×   s   € ÷ ñ ˜ñ r$   c                 ó$  € Rp  ^ RI Hp ^ RIHp VP	                  4       '       d   V! 4         ^ RIH	p T! 4        T #   \
         d    Rp \        P                  RRR7        L6i ; i  \
         d    Rp \        P                  RRR7        T # i ; i)	z¾Record a fresh install and settle the guest's claim; True when neither step failed. A failure is
logged: onboarding.state still answers live, and the record still says who carries inference.Tr„   )Úlatch_first_installFz7onboarding: could not record the first-install decision)Úexc_info)Úsettle_interrupted_claimz0free tier: could not settle an interrupted claim)
r†   r…   Úhermes_cli.onboarding_runr™   Úon_local_desktop_backendr{   r|   ÚwarningÚhermes_cli.welcome_trialr›   )r•   r…   r™   r›   s       r!   r“   r“   ×   s˜   € ð €GðaÝ(ÝAØ×-Ñ-×/Ò/ÙÔ!ðZÝEÙ Ô"ð €Nøô ô aØˆÜ�‰ÐPÐ[_ˆÖ`ðaûô ô ZØˆÜ�‰ÐIÐTXˆÕYØ€NðZús$   „!= ¦= ®A' ½$A$Á#A$Á'$BÂBc               ó   € V ^8„  d   QhRR/# r^   r   )r    s   "r!   r"   r"   ì   s   € ÷ !ñ ! Dñ !r$   c                 óÄ  € \         ;_uu_ 4        \        RJ;'       d    \        '       * p RRR4       X '       d   \        P	                  RR7      '       g   R#  \        4       '       d$   \         ;_uu_ 4        RsRRR4       \        4        \        P                  4        R#   + '       g   i     L€; i  + '       g   i     LC; i  \        P                  4        i ; i)zÓThe local Desktop connected again to a process whose bootstrap could not settle the install:
try those steps again and rebuild the record when they pass. Nothing before the bootstrap
finished or once it settled.NF)ÚblockingT)rX   rB   ra   Ú_resettle_lockÚacquirer“   Úrefresh_recordÚrelease)Ú	unsettleds    r!   Úresettle_after_failed_bootr¨   ì   s‰   € ÷
 
ŽÜ 4Ð'×8Ð8´¬Lˆ	÷ 
çœN×2Ñ2¸EÐ2×BÒBÙð!Ü×Òß–Ø�÷ äÔä×ÑÖ ÷ 
�ú÷ —ûô 	×ÑÕ ús/   �B#ÁC	 Á8B6Á;C	 Â#B3	Â6C	ÃC	 Ã	Cc               ó    € V ^8„  d   QhRRRR/# )r   rŽ   r   r   rA   r   )r    s   "r!   r"   r"   þ   s   € ÷ ñ  ð Ð0Eñ r$   c                óÔ   € \         f   R# \        \        4       R7      p\        ;_uu_ 4        Vs RRR4       \	        4        V '       d   \        V4       V#   + '       g   i     L/; i)z´Rebuild the launch profile's record after the identity changed (a trial claim), so
``setup.status`` and the ``setup.ready`` listeners move with it. None before the first bootstrap.Nr‘   )rB   r�   rV   rX   rY   rZ   )rŽ   r[   s   $ r!   r¥   r¥   þ   sF   € ô ‚ÙÜÔ!;Ó!=Ô>€Fß	ŽØˆ÷ 
ä„NßÜ�6ÔØ€M÷ 
�ús   ­AÁA'	c               ó   € V ^8„  d   QhRR/# r^   r   )r    s   "r!   r"   r"     s   € ÷  ñ  �dñ  r$   c                 ó2   € ^ RI Hp  V P                  4        R# )rg   ©Úonboarding_dueN)r†   r®   Ú
invalidater­   s    r!   rY   rY     s   € Ý)à×ÑÖr$   c               ó    € V ^8„  d   QhRRRR/# )r   r[   r   r   r_   r   )r    s   "r!   r"   r"     s   € ÷ ;ñ ;�{ð ; tñ ;r$   c                ó¨   €  ^ RI Hp V! \        V P                  4       4       R#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)rg   )Ú_broadcast_global_eventzsetup.ready not broadcast: %sN)Útui_gateway.serverr²   ÚSETUP_READY_EVENTr1   r{   r|   r}   )r[   r²   r~   s   &  r!   rZ   rZ     s@   € ð;Ý>ÙÔ 1°6×3DÑ3DÓ3FÖGøÜô ;Ü�‰Ð4°c×:Ò:ûð;ús   ‚!% ¥A°AÁAc               ó   € V ^8„  d   QhRR/# )r   r   zthreading.Threadr   )r    s   "r!   r"   r"     s   € ÷ ñ Ð$4ñ r$   c                 óN   € ^ RI Hp  V ! \        RR7      pVP                  4        V# )z@Run on a daemon thread so the inventory never delays the socket.)Úspawn_context_threadzfree-tier-bootstrap)rr   )Úagent.memory_providerr·   r–   Ústart)r·   Úthreads     r!   Ústart_background_bootstrapr»     s    € å:á!¤-Ð6KÔL€FØ
‡L�L„NØ€Mr$   )zconfig.yamlz.envz	auth.json)/Ú__conditional_annotations__r<   Ú
__future__r   ÚloggingÚ	threadingr>   Údataclassesr   r   r   r   Útypingr   r   r	   Ú	getLoggerr|   r’   r´   r   ÚLockrX   rB   r=   ÚEventrL   rK   ra   r£   rC   rj   rG   rO   rN   rc   rU   rV   rW   r�   r–   r“   r¨   r¥   rY   rZ   r»   )r¼   s   @r!   Ú<module>rÅ      s  øðôõ #ã Û Û ß 9Ó 9ß &Ñ &à	×	Ò	Ð,Ó	-€ð Ð Ø!Ð ñ �$Ô÷"ð "ó ð"ð@ 	�ŠÓ€Ø!%€Ð	Ó %Ø�ŠÓ€Ø€Ø€Ø—’Ó!€ð %)Ð �/Ó (Ø7Ð õð
 &>÷ 	õõ<õ
õõ*õð$ d÷ õ0õ*!ð$ t÷ õ õ;÷r$   