Ë
    „ÝjÖ  ã                  óÖ   — d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZmZ ddlmZ  G d	„ d
e«      Zdd„Z G d„ d«      Z G d„ d«      Z G d„ d«      Z G d„ d«      Zy)u  Persistenter Zustand unter dem konfigurierten state-Verzeichnis.

Ein Mechanismus fÃ¼r alles: JSON-Datei + exklusive Dateisperre (fcntl.flock
auf eine eigene .lock-Datei) + atomarer Ersatz (temp + fsync + os.replace).
flock sperrt je offener Dateibeschreibung; jede Transaktion Ã¶ffnet die
Sperrdatei neu, damit sperrt sie auch Threads desselben Prozesses
gegeneinander und andere Prozesse (z. B. parallele Bridge-Aufrufe).

BeschÃ¤digte Zustandsdateien fÃ¼hren zu StateError (fail-closed), nie zu
einem stillen Neuanfang.
é    )ÚannotationsN)Úcontextmanager)ÚPath)ÚIteratorÚOptionalé   )ÚModec                  ó    ‡ — e Zd Zdˆ fd„Zˆ xZS )Ú
StateErrorc                ó2   •— t         ‰| �  |«       || _        y ©N)ÚsuperÚ__init__Úcode)Úselfr   Ú	__class__s     €ú2/home/aria/aria-v3-dev/python/aria_router/state.pyr   zStateError.__init__   s   ø€ Ü‰Ñ˜ÔØˆ�	ó    )r   Ústr)Ú__name__Ú
__module__Ú__qualname__r   Ú__classcell__)r   s   @r   r   r      s   ø„ ÷ñ r   r   c                ód   — | j                  ddd¬«       | j                  «       st        d«      ‚| S )NiÀ  T)ÚmodeÚparentsÚexist_okÚSTATE_DIR_INVALID)ÚmkdirÚis_dirr   )Úpaths    r   Úensure_private_dirr"      s.   € Ø‡J�J�E 4°$€JÔ7Ø�;‰;Œ=ÜÐ,Ó-Ð-Ø€Kr   c                  ó>   — e Zd Zdd„Zedd„«       Zd	d„Zd	d„Zd
d„Zy)ÚLockedJsonFilec                ó’   — t        |«      | _        | j                  j                  | j                  j                  dz   «      | _        y )Nz.lock)r   r!   Ú	with_nameÚnameÚ	lock_path©r   r!   s     r   r   zLockedJsonFile.__init__'   s0   € Ü˜“JˆŒ	ØŸ™×,Ñ,¨T¯Y©Y¯^©^¸gÑ-EÓFˆ�r   c              #  ó¸  K  — t        | j                  j                  «       t        j                  | j
                  t        j                  t        j                  z  d«      }	 t        j                  |t        j                  «       | j                  «       }|–— | j                  |«       	 t        j                  |t        j                  «       t        j                  |«       y # t        j                  |«       w xY w# 	 t        j                  |t        j                  «       t        j                  |«       w # t        j                  |«       w xY wxY w­w©Né€  )r"   r!   ÚparentÚosÚopenr(   ÚO_RDWRÚO_CREATÚfcntlÚflockÚLOCK_EXÚ_readÚ_writeÚLOCK_UNÚclose)r   Úlock_fdÚdatas      r   ÚtransactionzLockedJsonFile.transaction+   sÍ   è ø€ ä˜4Ÿ9™9×+Ñ+Ô,Ü—'‘'˜$Ÿ.™.¬"¯)©)´b·j±jÑ*@À%ÓHˆð		"Ü�K‰K˜¤§¡Ô/Ø—:‘:“<ˆDØŠJØ�K‰K˜Ôð"Ü—‘˜G¤U§]¡]Ô3ä—‘˜Õ!ø”—‘˜Õ!ûð"Ü—‘˜G¤U§]¡]Ô3ä—‘˜Õ!ø”—‘˜Õ!ÿsI   ‚A EÁ#A	D Â-$C' ÃEÃ'C>Ã>EÄEÄ$D=Ä'EÄ=EÅEÅEc                ó„  — t        | j                  j                  «       t        j                  | j
                  t        j                  t        j                  z  d«      }	 t        j                  |t        j                  «       | j                  «       	 t        j                  |t        j                  «       t        j                  |«       S # t        j                  |«       w xY w# 	 t        j                  |t        j                  «       t        j                  |«       w # t        j                  |«       w xY wxY wr+   )r"   r!   r-   r.   r/   r(   r0   r1   r2   r3   ÚLOCK_SHr5   r7   r8   )r   r9   s     r   Úread_snapshotzLockedJsonFile.read_snapshot:   s·   € Ü˜4Ÿ9™9×+Ñ+Ô,Ü—'‘'˜$Ÿ.™.¬"¯)©)´b·j±jÑ*@À%ÓHˆð	"Ü�K‰K˜¤§¡Ô/Ø—:‘:“<ð"Ü—‘˜G¤U§]¡]Ô3ä—‘˜Õ!ø”—‘˜Õ!ûð"Ü—‘˜G¤U§]¡]Ô3ä—‘˜Õ!ø”—‘˜Õ!ýs0   Á!3C) Â$CÃC&Ã)D?Ã+$D%ÄD?Ä%D<Ä<D?c                ó”  — 	 t        | j                  dd¬«      5 }|j                  «       }d d d «       j                  «       si S 	 t        j                  |«      }t        |t        «      st        d«      ‚|S # 1 sw Y   ŒNxY w# t        $ r i cY S t        $ r}t        d«      |‚d }~ww xY w# t        $ r}t        d«      |‚d }~ww xY w)NÚrúutf-8©ÚencodingÚSTATE_UNREADABLEÚSTATE_CORRUPT)r/   r!   ÚreadÚFileNotFoundErrorÚOSErrorr   ÚstripÚjsonÚloadsÚ
ValueErrorÚ
isinstanceÚdict)r   ÚhandleÚrawÚexcr:   s        r   r5   zLockedJsonFile._readF   s¿   € ð	:Ü�d—i‘i ¨wÔ7ð $¸6Ø—k‘k“m�÷$ð �y‰yŒ{ØˆIð	7Ü—:‘:˜c“?ˆDô ˜$¤Ô%Ü˜_Ó-Ð-Øˆ÷$ð $ûä ò 	ØŠIÜò 	:ÜÐ/Ó0°cÐ9ûð	:ûô ò 	7Ü˜_Ó-°3Ð6ûð	7úsK   ‚B šA8«B ÁB- Á8BÁ=B ÂB*ÂB*ÂB%Â%B*Â-	CÂ6CÃCc           	     óæ  — | j                   j                  d| j                   j                  › dt        j                  «       › dt        j                  «       › d�«      }t        j                  |t        j                  t        j                  z  t        j                  z  d«      }	 t        j                  |dd¬«      5 }t        j                  ||dd¬	«       |j                  «        t        j                  |j!                  «       «       d d d «       t        j"                  || j                   «       y # 1 sw Y   Œ*xY w# t$        $ r' 	 t        j&                  |«       ‚ # t(        $ r Y ‚ w xY ww xY w)
Nú.z.tmpr,   ÚwrA   rB   T)ú,ú:)Ú	sort_keysÚ
separators)r!   r&   r'   r.   ÚgetpidÚ	threadingÚ	get_identr/   ÚO_WRONLYr1   ÚO_TRUNCÚfdopenrJ   ÚdumpÚflushÚfsyncÚfilenoÚreplaceÚBaseExceptionÚunlinkrG   )r   r:   ÚtmpÚfdrO   s        r   r6   zLockedJsonFile._writeX   s  € Ø�i‰i×!Ñ! A d§i¡i§n¡nÐ%5°Q´r·y±y³{°mÀ1ÄY×EXÑEXÓEZÐD[Ð[_Ð"`ÓaˆÜ�W‰W�Sœ"Ÿ+™+¬¯
©
Ñ2´R·Z±ZÑ?ÀÓGˆð	Ü—‘˜2˜s¨WÔ5ð *¸Ü—	‘	˜$ °$À:ÕNØ—‘”Ü—‘˜Ÿ™›Ô)÷*ô �J‰J�s˜DŸI™IÕ&÷	*ð *ûô
 ò 	ðÜ—	‘	˜#”ð øô %ò ØØðúð	úsI   Â&E  Â>AD4Ä(E  Ä4D=Ä9E  Å 	E0Å
E ÅE0Å 	E,Å)E0Å+E,Å,E0N©r!   r   )ÚreturnzIterator[dict])ri   rN   )r:   rN   ri   ÚNone)	r   r   r   r   r   r;   r>   r5   r6   © r   r   r$   r$   &   s+   „ óGð ò"ó ð"ó
"óô$r   r$   c                  ó    — e Zd ZdZdd„Zdd„Zy)ÚIdempotencyStorez:Merkt sich verarbeitete Nachrichten (chat_id, message_id).c                ó2   — t        |«      | _        || _        y r   )r$   Ú_fileÚ_ttl)r   r!   Úttl_secondss      r   r   zIdempotencyStore.__init__l   s   € Ü# DÓ)ˆŒ
Øˆ�	r   c           	     óž  — | j                   j                  «       5 }|j                  di «      }|j                  «       D ��cg c]  \  }}|j	                  dd«      |k  sŒ|‘Œ c}}D ]  }||= Œ |j	                  |«      }	|	�d|	j	                  d«      fcddd«       S ||| j
                  z   dœ||<   	 ddd«       yc c}}w # 1 sw Y   yxY w)	u9   True, wenn der SchlÃ¼ssel neu ist und jetzt belegt wurde.ÚentriesÚexpiresr   NFÚjob_id)ru   rt   )TN)ro   r;   Ú
setdefaultÚitemsÚgetrp   )
r   Úkeyru   Únowr:   rs   ÚkÚvÚstaleÚexistings
             r   ÚclaimzIdempotencyStore.claimp   sÉ   € à�Z‰Z×#Ñ#Ó%ð 	¨Ø—o‘o i°Ó4ˆGØ(/¯©«×U¡  1¸1¿5¹5ÀÈAÓ;NÐQTÓ;Tš!ÓUò #�Ø˜E‘Nð#à—{‘{ 3Ó'ˆHØÐ#Ø˜hŸl™l¨8Ó4Ð4÷	ñ 	ð '-¸¸t¿y¹y¹ÑIˆG�C‰LØ÷	ð 	ùãU÷	ð 	ús)   ›&CÁB=ÁB=Á#1CÂCÂ=CÃCN)r!   r   rq   Úint)ry   r   ru   r   rz   Úfloatri   ztuple[bool, Optional[str]])r   r   r   Ú__doc__r   r   rk   r   r   rm   rm   i   s   „ ÙDó ô
r   rm   c                  ó(   — e Zd ZdZdd„Zdd„Zdd„Zy)	Ú	ModeStorez-Modellmodus je Chat (/auto, /codex, /claude).c                ó$   — t        |«      | _        y r   )r$   ro   r)   s     r   r   zModeStore.__init__€   s   € Ü# DÓ)ˆ�
r   c                óü   — | j                   j                  «       }|j                  di «      j                  |t        j                  j
                  «      }	 t        |«      S # t        $ r}t        d«      |‚d }~ww xY w)NÚmodesrE   )ro   r>   rx   r	   ÚAUTOÚvaluerL   r   )r   Úchat_idr:   r‰   rQ   s        r   rx   zModeStore.getƒ   se   € Ø�z‰z×'Ñ'Ó)ˆØ—‘˜ "Ó%×)Ñ)¨'´4·9±9·?±?ÓCˆð	7Ü˜“;ÐøÜò 	7Ü˜_Ó-°3Ð6ûð	7ús   Á
A! Á!	A;Á*A6Á6A;c                óÖ   — t        |t        «      st        d«      ‚| j                  j	                  «       5 }|j
                  |j                  di «      |<   d d d «       y # 1 sw Y   y xY w)NÚINVALID_MODEr‡   )rM   r	   rL   ro   r;   r‰   rv   )r   rŠ   r   r:   s       r   ÚsetzModeStore.set‹   sW   € Ü˜$¤Ô%Ü˜^Ó,Ð,Ø�Z‰Z×#Ñ#Ó%ð 	?¨Ø48·J±JˆD�O‰O˜G RÓ(¨Ñ1÷	?÷ 	?ñ 	?ús   ¶ AÁA(Nrh   )rŠ   r   ri   r	   )rŠ   r   r   r	   ri   rj   )r   r   r   r‚   r   rx   r�   rk   r   r   r„   r„   }   s   „ Ù7ó*ó7ô?r   r„   c                  ó*   — e Zd ZdZddd„Zdd„Zd	d„Zy)
Ú
NonceStorez9Verbrauchte Clearance-Nonces (Replay-Schutz), persistent.c                ó2   — t        |«      | _        || _        y r   )r$   ro   Ú
_retention)r   r!   Úretention_secondss      r   r   zNonceStore.__init__•   s   € Ü# DÓ)ˆŒ
Ø+ˆ�r   c                ó6  — | j                   j                  «       5 }|j                  di «      }|j                  «       D ��cg c]  \  }}|| j                  z   |k  sŒ|‘Œ c}}D ]  }||= Œ ||v r
	 d d d «       y|||<   	 d d d «       yc c}}w # 1 sw Y   y xY w)NÚusedFT)ro   r;   rv   rw   r‘   )	r   ÚnonceÚ
expires_atrz   r:   r”   ÚnÚexpr}   s	            r   ÚconsumezNonceStore.consume™   sŸ   € Ø�Z‰Z×#Ñ#Ó%ð 	¨Ø—?‘? 6¨2Ó.ˆDØ*.¯*©*«,×V¡  3¸#ÀÇÁÑ:OÐRUÓ:Uš!ÓVò  �Ø˜‘Kð à˜‰}Ø÷	ð 	ð %ˆD�‰KØ÷	ð 	ùãV÷	ð 	ús)   ›&BÁB	ÁB	Á BÁ:BÂ	BÂBc                óZ   — || j                   j                  «       j                  di «      v S )Nr”   )ro   r>   rx   )r   r•   s     r   Úwas_usedzNonceStore.was_used£   s'   € Ø˜Ÿ
™
×0Ñ0Ó2×6Ñ6°v¸rÓBÐBÐBr   N)i  )r!   r   r’   r€   )r•   r   r–   r�   rz   r�   ri   Úbool)r•   r   ri   rœ   )r   r   r   r‚   r   r™   r›   rk   r   r   r�   r�   ’   s   „ ÙCô,óôCr   r�   )r!   r   ri   r   )r‚   Ú
__future__r   r2   rJ   r.   rZ   Ú
contextlibr   Úpathlibr   Útypingr   r   Úcorer	   ÚRuntimeErrorr   r"   r$   rm   r„   r�   rk   r   r   ú<module>r£      se   ðñ
õ #ã Û Û 	Û Ý %Ý ß %å ô�ô ó÷@ñ @÷Fñ ÷(?ñ ?÷*Cò Cr   