Ë
    âß²jRL  ã                  óÞ   — 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m	Z	m
Z
mZ ddlmZmZmZ ddlmZ  ej$                  d«      Zddd„Zd	Zd
e› de› d ed«      › d�ZdZdZ G d„ d«      Zy)zATelegram DM topic-mode mixin for :class:`hermes_state.SessionDB`.é    )ÚannotationsN)ÚAnyÚDictÚListÚOptional)Ú_PREVIEW_ELIGIBLE_SQLÚ_PREVIEW_RAW_SELECTÚ_sql_session_last_active)ÚStateDbReplacedErrorÚhermes_statec                óH   — t        | xs d«      j                  «       }|r|S dS )uÊ   Empty/missing â†’ ``"default"`` (single namespace for non-multiplexed gateways).
    Multiplexed callers must pass the *routed* profile (``source.profile``), never the
    process-global active profile.Ú Údefault)ÚstrÚstrip)Úprofile_nameÚnames     ú:/home/ubuntu/.hermes/hermes-agent/hermes_state_telegram.pyÚ&_normalize_telegram_topic_profile_namer      s)   € ô ˆ|Ò!˜rÓ"×(Ñ(Ó*€DÙˆ4Ð&˜YÐ&ó    ))Útelegram_dm_topic_modez°profile_name, chat_id, user_id, enabled, activated_at, updated_at, has_topics_enabled, allows_users_to_create_topics, capability_checked_at, intro_message_id, pinned_message_idai  
                    profile_name TEXT NOT NULL DEFAULT 'default',
                    chat_id TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    enabled INTEGER NOT NULL DEFAULT 1,
                    activated_at REAL NOT NULL,
                    updated_at REAL NOT NULL,
                    has_topics_enabled INTEGER,
                    allows_users_to_create_topics INTEGER,
                    capability_checked_at REAL,
                    intro_message_id TEXT,
                    pinned_message_id TEXT,
                    PRIMARY KEY (profile_name, chat_id)
                )Útelegram_dm_topic_bindingszgprofile_name, chat_id, thread_id, user_id, session_key, session_id, managed_mode, linked_at, updated_ata:  
                    profile_name TEXT NOT NULL DEFAULT 'default',
                    chat_id TEXT NOT NULL,
                    thread_id TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    session_key TEXT NOT NULL,
                    session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
                    managed_mode TEXT NOT NULL DEFAULT 'auto',
                    linked_at REAL NOT NULL,
                    updated_at REAL NOT NULL,
                    PRIMARY KEY (profile_name, chat_id, thread_id)
                zÜ
                    SELECT s.*,
                        COALESCE(sp.prompt, s.system_prompt)
                            AS _system_prompt_resolved,
                        COALESCE(
                            (SELECT z¶
                             FROM messages m
                             WHERE m.session_id = s.id AND m.role = 'user' AND m.content IS NOT NULL
                               AND z¥
                             ORDER BY m.timestamp, m.id LIMIT 1),
                            ''
                        ) AS _preview_raw,
                        Úszô AS last_active
                    FROM sessions s
                    LEFT JOIN system_prompts sp
                      ON sp.hash = s.system_prompt_hash
                    WHERE s.source = 'telegram'
                      AND s.user_id = ?
zq                    ORDER BY last_active DESC, s.started_at DESC
                    LIMIT ?
                    a                        AND COALESCE(NULLIF(TRIM(s.profile_name), ''), 'default') = ?
                      AND NOT EXISTS (
                          SELECT 1 FROM telegram_dm_topic_bindings b
                          WHERE b.session_id = s.id
                      )
c                  ó$  — e Zd ZdZd„ Zdd„Zdd„Zdd„Zddddœ	 	 	 	 	 	 	 	 	 	 	 dd	„Zdd
dœ	 	 	 	 	 	 	 dd„Z	ddœdd„Z
ddœ	 	 	 	 	 	 	 dd„Zddœ	 	 	 	 	 d d„Zd!d„Zddœd"d„Zdddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d#d„Zd$d„Zdddœ	 	 	 	 	 	 	 	 	 d%d„Zy)&ÚSessionTelegramTopicsMixinzæTelegram DM topic-mode tables, bindings and lookups. Read paths tolerate absent
    tables (nobody ran ``/topic``) by returning their empty value and never create them;
    pre-v3 tables left by an upgrade are self-healed on read.c                ó  — 	  |«       S # t         j                  $ r}dt        |«      vr|cY d}~S Y d}~nd}~ww xY w	 | j                  «         |«       S # t         j                  t
        f$ r t        j                  dd¬«       |cY S w xY w)u  Run ``read()``; an absent table reads as ``empty``. A pre-v3 table left by an upgrade
        (#103363) raises ``no such column: profile_name`` â€” heal it and retry, otherwise the
        write-only migration is never reached and topic mode silently reads as off forever.zno such column: profile_nameNzFtelegram topic tables are pre-v3 and the heal failed; reading as emptyT)Úexc_info)Úsqlite3ÚOperationalErrorr   Úapply_telegram_topic_migrationÚErrorr   ÚloggerÚwarning)ÚselfÚreadÚemptyÚexcs       r   Ú_topic_readz&SessionTelegramTopicsMixin._topic_readh   s†   € ð	Ù“6ˆMøÜ×'Ñ'ò 	Ø-´S¸³XÑ=Ø•ô >ûð	úð	Ø×/Ñ/Ô1ñ ‹vˆøô —‘Ô3Ð4ò 	Ü�N‰NÐcÐnrˆNÔsØŠLð	ús%   ‚	 ‰:œ5ª:µ:¾A Á2B
Â	B
c                ó6   ‡ ‡‡— ‰ j                  ˆˆ ˆfd„d «      S )Nc                 ó(   •— ‰j                  ‰‰ «      S ©N)Ú	_read_one©Úparamsr$   Úsqls   €€€r   ú<lambda>z<SessionTelegramTopicsMixin._topic_read_one.<locals>.<lambda>y   ó   ø€ ¨¯©°s¸FÓ(C€ r   ©r(   ©r$   r/   r.   s   ```r   Ú_topic_read_onez*SessionTelegramTopicsMixin._topic_read_onex   s   ú€ Ø×ÑÕ CÀTÓJÐJr   c                ó6   ‡ ‡‡— ‰ j                  ˆˆ ˆfd„g «      S )Nc                 ó(   •— ‰j                  ‰‰ «      S r+   )Ú	_read_allr-   s   €€€r   r0   z<SessionTelegramTopicsMixin._topic_read_all.<locals>.<lambda>|   r1   r   r2   r3   s   ```r   Ú_topic_read_allz*SessionTelegramTopicsMixin._topic_read_all{   s   ú€ Ø×ÑÕ CÀRÓHÐHr   c                ó2   ‡ — ˆ fd„}‰ j                  |«       y)a)  Create Telegram DM topic-mode tables on explicit /topic opt-in. Deliberately NOT
        part of startup reconciliation: operators can upgrade and keep the old bot
        behavior until a user runs /topic. Also invoked by ``_topic_read`` to heal a
        pre-v3 table an upgrade left behind (#103363). Schema versions: v1 initial; v2 session_id FK
        ON DELETE CASCADE (pruning clears bindings); v3 ``profile_name`` on both tables so
        multiplexed gateways sharing one state.db isolate topic state per profile.

        See #76423.
        c                óò  •— t         D ]´  \  }}}| j                  d|› d|› d�«       | j                  d|› d�«      D �ch c]  }|d   ’Œ	 }}d|v rŒI|j                  dd	d«      }d
|v rdnd	}| j                  d|› d�«       ‰j                  | j	                  «       ||› d�d|› d|› d�d|› d|› d|› d|› d|› �
«       Œ¶ | j                  d«       | j                  d«       | j                  dd«       y c c}w )NzCREATE TABLE IF NOT EXISTS z (ú)zPRAGMA table_info('z')é   r   zprofile_name, r   Ú
session_idz@ WHERE EXISTS (SELECT 1 FROM sessions s WHERE s.id = session_id)zDROP TABLE IF EXISTS Ú_newÚ_legacyzCREATE TABLE zINSERT INTO z) SELECT 'default', z FROM zrCREATE UNIQUE INDEX IF NOT EXISTS idx_telegram_dm_topic_bindings_session ON telegram_dm_topic_bindings(session_id)z|CREATE INDEX IF NOT EXISTS idx_telegram_dm_topic_bindings_user ON telegram_dm_topic_bindings(profile_name, user_id, chat_id)zgINSERT INTO state_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value)Ú telegram_dm_topic_schema_versionÚ3)Ú_TOPIC_TABLESÚexecuteÚreplaceÚ_rebuild_tableÚcursor)	ÚconnÚtableÚcolumnsÚddlÚrowÚhaveÚlegacy_columnsÚliver$   s	           €r   Ú_dozFSessionTelegramTopicsMixin.apply_telegram_topic_migration.<locals>._doˆ   sL  ø€ Ü'4ò Ñ#��w Ø—‘Ð:¸5¸'ÀÀCÀ5ÈÐJÔKØ*.¯,©,Ð9LÈUÈGÐSUÐ7VÓ*WÖX 3˜˜A›ÐX�ÐXØ! TÑ)Øð ")§¡Ð1AÀ2ÀqÓ!I�Ø]iÐmtÑ]tÑYÐz|�Ø—‘Ð4°U°G¸4Ð@ÔAØ×#Ñ#Ø—K‘K“M 5¨U¨G°7Ð*;¸}ÈUÈGÐSUÐVYÐUZÐZ[Ð=\Ø" 5 '¨¨G¨9Ð4HÈÐHXÐX^Ð_dÐ^eÐelÐmqÐlrÐsõðð& �L‰Lð<ôð �L‰LðPôð �L‰LðHà9õùò3 Ys   ¾C4N)Ú_execute_write)r$   rO   s   ` r   r    z9SessionTelegramTopicsMixin.apply_telegram_topic_migration~   s   ø€ ô 	ðB 	×Ñ˜CÕ r   r   N)r   Úhas_topics_enabledÚallows_users_to_create_topicsc               óÚ   — | j                  «        t        j                  «       }t        |«      }dd„}| j                  d|t	        |«      t	        |«      || ||«       ||«      |f«       y)aŽ  Enable Telegram DM topic mode for one private chat/user. Owns the explicit topic
        migration; SessionDB startup must not create these tables.

        ``profile_name`` namespaces rows under a shared multiplex ``state.db`` (issue #76423). Callers
        handling a multiplexed event must pass the routed profile from ``source.profile``, not the
        process-global active profile.
        c                ó   — | €d S | rdS dS )Nr<   r   © )Úvalues    r   Ú_to_intzFSessionTelegramTopicsMixin.enable_telegram_topic_mode.<locals>._to_intº   s   € Ø ˜=�4ÐA±E¨qÐA¸qÐAr   aÄ  
            INSERT INTO telegram_dm_topic_mode (
                profile_name, chat_id, user_id, enabled, activated_at, updated_at,
                has_topics_enabled, allows_users_to_create_topics,
                capability_checked_at
            ) VALUES (?, ?, ?, 1, ?, ?, ?, ?, ?)
            ON CONFLICT(profile_name, chat_id) DO UPDATE SET
                user_id = excluded.user_id,
                enabled = 1,
                updated_at = excluded.updated_at,
                has_topics_enabled = excluded.has_topics_enabled,
                allows_users_to_create_topics = excluded.allows_users_to_create_topics,
                capability_checked_at = excluded.capability_checked_at
            N)rV   úOptional[bool]ÚreturnzOptional[int])r    Útimer   Ú
_write_sqlr   )r$   Úchat_idÚuser_idr   rQ   rR   ÚnowrW   s           r   Úenable_telegram_topic_modez5SessionTelegramTopicsMixin.enable_telegram_topic_mode«   sn   € ð 	×+Ñ+Ô-Ü�i‰i‹kˆÜ=¸lÓKˆó	Bð 	�‰ð ð ¤ G£¬c°'«l¸CÀÙÐ,Ó-©wÐ7TÓ/UÐWZð\õ	]r   T)r   Úclear_bindingsc               óP   ‡‡‡— t        ‰«      Šˆˆˆfd„}| j                  |«       y)zÎDisable Telegram DM topic mode for one private chat. ``clear_bindings`` also drops
        the chat's bindings so a later re-enable starts clean. Never creates the tables;
        absent tables are a no-op.c           	     ó  •— t        j                  t        j                  «      5  | j	                  dt        j
                  «       ‰t        ‰«      f«       ‰r| j	                  d‰t        ‰«      f«       d d d «       y # 1 sw Y   y xY w)NúdUPDATE telegram_dm_topic_mode SET enabled = 0, updated_at = ? WHERE profile_name = ? AND chat_id = ?zMDELETE FROM telegram_dm_topic_bindings WHERE profile_name = ? AND chat_id = ?)Ú
contextlibÚsuppressr   r   rC   rZ   r   )rG   r\   r`   r   s    €€€r   rO   zCSessionTelegramTopicsMixin.disable_telegram_topic_mode.<locals>._doÕ   sq   ø€ Ü×$Ñ$¤W×%=Ñ%=Ó>ñ 
Ø—‘ð=ä—Y‘Y“[ ,´°G³Ð=ôñ
 "Ø—L‘LØgØ%¤s¨7£|Ð4ô÷
÷ 
ñ 
ús   ¥AA>Á>BN)r   rP   )r$   r\   r   r`   rO   s    ``` r   Údisable_telegram_topic_modez6SessionTelegramTopicsMixin.disable_telegram_topic_modeÍ   s$   ú€ ô >¸lÓKˆö	ð 	×Ñ˜CÕ r   )r   c               óŠ   — t        |«      }| j                  d|t        |«      t        |«      f«      }|�t        |d   «      S dS )zDReturn whether Telegram DM topic mode is enabled for this chat/user.zŸ
                    SELECT enabled FROM telegram_dm_topic_mode
                    WHERE profile_name = ? AND chat_id = ? AND user_id = ?
                    r   F)r   r4   r   Úbool)r$   r\   r]   r   rK   s        r   Úis_telegram_topic_mode_enabledz9SessionTelegramTopicsMixin.is_telegram_topic_mode_enabledã   sO   € ä=¸lÓKˆØ×"Ñ"ð $ð '¬¨G«´c¸'³lÐCóEˆð  #˜Œt�C˜‘F‹|Ð9°EÐ9r   c               ó„   — t        |«      }| j                  d|t        |«      t        |«      f«      }|rt        |«      S dS )z?Return the session binding for a Telegram DM topic, if present.zŸ
                    SELECT * FROM telegram_dm_topic_bindings
                    WHERE profile_name = ? AND chat_id = ? AND thread_id = ?
                    N)r   r4   r   Údict)r$   r\   Ú	thread_idr   rK   s        r   Úget_telegram_topic_bindingz5SessionTelegramTopicsMixin.get_telegram_topic_bindingì   sK   € ô >¸lÓKˆØ×"Ñ"ð $ð '¬¨G«´c¸)³nÐEóGˆñ  Œt�C‹yÐ) TÐ)r   c               óŽ   — t        |«      }| j                  d|t        |«      f«      }|D �cg c]  }t        |«      ‘Œ c}S c c}w )zFAll bindings for one chat, newest first ([] when the table is absent).zhSELECT * FROM telegram_dm_topic_bindings WHERE profile_name = ? AND chat_id = ? ORDER BY updated_at DESC)r   r8   r   rk   )r$   r\   r   ÚrowsrK   s        r   Ú%list_telegram_topic_bindings_for_chatz@SessionTelegramTopicsMixin.list_telegram_topic_bindings_for_chat÷   sG   € ô >¸lÓKˆØ×#Ñ#ØvØœ3˜w›<Ð(ó
ˆð &*Ö*˜c”�S•	Ò*Ð*ùÒ*s   ­Ac               óX   — | j                  dt        |«      f«      }|rt        |«      S dS )zEReverse lookup via the UNIQUE INDEX on session_id; None when unbound.z{
                    SELECT * FROM telegram_dm_topic_bindings
                    WHERE session_id = ?
                    N)r4   r   rk   ©r$   r=   rK   s      r   Ú%get_telegram_topic_binding_by_sessionz@SessionTelegramTopicsMixin.get_telegram_topic_binding_by_session  s6   € à×"Ñ"ð $ô ˜j›/Ð+ó-ˆñ  Œt�C‹yÐ) TÐ)r   c               ó~   ‡‡‡— t        ‰«      t        ‰«      cŠŠt        ‰«      Šdˆˆˆfd„}| j                  |«      S )a  Remove the binding row for one (chat, thread) pair. Called when the Bot API confirms
        a topic was deleted externally (``Thread not found`` after the same-thread retry
        failed); otherwise ``gateway.run._recover_telegram_topic_thread_id`` keeps
        redirecting inbound messages to the dead topic. If this removes the chat's *last*
        binding, ``telegram_dm_topic_mode`` is flipped to ``enabled = 0`` in the same
        transaction, or a user who disabled topics in the Telegram client (not via
        ``/topic off``) stays stuck. Returns the number of rows deleted; absent binding or
        unmigrated tables are silent no-ops (never raise from a cleanup hot path).

        Without this prune, the stale row keeps living in ``telegram_dm_topic_bindings`` and the recovery
        logic in ``gateway.run._recover_telegram_topic_thread_id`` cheerfully redirects future inbound
        messages to the deleted topic, causing tool progress, approvals, and replies to land in the wrong
        place. Issue #31501.
        c                ó�  •— 	 | j                  d‰‰‰f«      j                  xs d}|syt	        j
                  t        j                  «      5  | j                  d‰‰f«      j                  «       }|€'| j                  dt        j                  «       ‰‰f«       d d d «       |S # t        j                  $ r Y yw xY w# 1 sw Y   |S xY w)Nz�
                    DELETE FROM telegram_dm_topic_bindings
                    WHERE profile_name = ? AND chat_id = ? AND thread_id = ?
                    r   z•
                    SELECT 1 FROM telegram_dm_topic_bindings
                    WHERE profile_name = ? AND chat_id = ? LIMIT 1
                    rc   )rC   Úrowcountr   r   rd   re   ÚfetchonerZ   )rG   ÚdeletedÚ	remainingr\   r   rl   s      €€€r   rO   zESessionTelegramTopicsMixin.delete_telegram_topic_binding.<locals>._do  sè   ø€ ðØŸ,™,ð (ð '¨°Ð;ó=÷ >F¹XòKð JKð ñ Øô ×$Ñ$¤W×%=Ñ%=Ó>ñ 
Ø ŸL™Lð *ð '¨Ð0ó2÷ 3;±(³*ð ð Ð$Ø—L‘LðAäŸ™› l°GÐ<ô÷
ð ˆNøô# ×+Ñ+ò Ùðú÷
ð ˆNús   ƒ#B" ÁAB;Â"B8Â7B8Â;C)rY   Úint)r   r   rP   )r$   r\   rl   r   rO   s    ``` r   Údelete_telegram_topic_bindingz8SessionTelegramTopicsMixin.delete_telegram_topic_binding
  s;   ú€ ô ! ›\¬3¨y«>Ðˆ�Ü=¸lÓKˆ÷	ð2 ×"Ñ" 3Ó'Ð'r   Úauto)Úmanaged_moder   c               ó  ‡‡‡‡‡‡‡‡	— | j                  «        t        j                  «       Š	t        ‰«      t        ‰«      t        ‰«      cŠŠŠt        ‰«      t        ‰«      cŠŠt        ‰«      Šˆˆˆ	ˆˆˆˆˆfd„}| j	                  |«       y)zÖBind one Telegram DM topic thread to one Hermes session. A session may be linked to
        only one topic: rebinding the same pair is idempotent; linking the session to a
        different topic raises ValueError.c                óð   •— | j                  d‰	f«      j                  «       }|�7|\  }}}t        |«      t        |«      t        |«      f‰‰‰fk7  rt        d«      ‚| j                  d‰‰‰‰‰
‰	‰‰‰f	«       y )Nzž
                SELECT profile_name, chat_id, thread_id
                FROM telegram_dm_topic_bindings
                WHERE session_id = ?
                z3session is already linked to another Telegram topicah  
                INSERT INTO telegram_dm_topic_bindings (
                    profile_name, chat_id, thread_id, user_id, session_key, session_id,
                    managed_mode, linked_at, updated_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                ON CONFLICT(profile_name, chat_id, thread_id) DO UPDATE SET
                    user_id = excluded.user_id,
                    session_key = excluded.session_key,
                    session_id = excluded.session_id,
                    managed_mode = excluded.managed_mode,
                    updated_at = excluded.updated_at
                )rC   rw   r   Ú
ValueError)rG   Úexisting_sessionÚlinked_profileÚlinked_chatÚlinked_threadr\   r}   r^   r   r=   Úsession_keyrl   r]   s        €€€€€€€€r   rO   z;SessionTelegramTopicsMixin.bind_telegram_topic.<locals>._doD  sž   ø€ Ø#Ÿ|™|ð -ð !�]ó	 $÷ %-¡H£Jð	 ð
  Ð+Ø=MÑ:� ¨]Ü˜Ó'¬¨[Ó)9¼3¸}Ó;MÐNÐS_ÐahÐjsÐRtÒtÜ$Ð%ZÓ[Ð[Ø�L‰Lð ð # G¨Y¸ÀÈjÐZfÐhkÐmpÐqõsr   N)r    rZ   r   r   rP   )
r$   r\   rl   r]   r…   r=   r}   r   rO   r^   s
    ``````` @r   Úbind_telegram_topicz.SessionTelegramTopicsMixin.bind_telegram_topic7  ss   ÿ€ ð 	×+Ñ+Ô-Ü�i‰i‹kˆÜ&)¨'£l´C¸	³NÄCÈÃLÐ#ˆ�˜GÜ"% kÓ"2´C¸
³OÐˆ�ZÜ=¸lÓKˆ÷	só 	sð, 	×Ñ˜CÕ r   c               óB   — | j                  dt        |«      f«      }|duS )uP   True if the session is bound to any Telegram DM topic (absent tables â†’ False).z—
                    SELECT 1 FROM telegram_dm_topic_bindings
                    WHERE session_id = ?
                    LIMIT 1
                    N)r4   r   rr   s      r   Ú#is_telegram_session_linked_to_topicz>SessionTelegramTopicsMixin.is_telegram_session_linked_to_topic\  s/   € à×"Ñ"ð $ô ˜j›/Ð+ó	-ˆð
 ˜$ˆÐr   é
   )r   Úlimitc          	     óê  — t        |«      }| j                  «       5 }	 |j                  t        t        z   t
        z   t        |«      |t        |«      f«      j                  «       }ddd«       D �cg c]  }| j                  |«      ‘Œ c}S # t        j                  $ rB |j                  t        t
        z   t        |«      t        |«      f«      j                  «       }Y Œ{w xY w# 1 sw Y   Œ€xY wc c}w )a  This user's Telegram sessions not bound to a topic. Read-only: if the bindings table
        is absent, every session is unlinked and the profile-unscoped query is used.
        Scoped by ``profile_name`` so multiplexed profiles do not surface each other.

        See #76423.
        N)r   Ú	_read_ctxrC   Ú_UNLINKED_SELECT_HEADÚ_UNLINKED_SCOPE_CLAUSESÚ_UNLINKED_SELECT_TAILr   rz   Úfetchallr   r   Ú	_rich_row)r$   r\   r]   r   rŠ   rG   ro   rK   s           r   Ú(list_unlinked_telegram_sessions_for_userzCSessionTelegramTopicsMixin.list_unlinked_telegram_sessions_for_usere  sÙ   € ô >¸lÓKˆØ�^‰^Óð 		 ðØ—|‘|Ü)Ô,CÑCÔF[Ñ[Ü˜“\ <´°U³Ð<ó÷ ‘(“*ð ÷		ð 04Ö4¨�—‘˜sÕ#Ò4Ð4øô	 ×+Ñ+ò Ø—|‘|Ü)Ô,AÑAÄCÈÃLÔRUÐV[ÓR\ÐC]óç‘(“*ò ðú÷		ð 		üò 5s0   œC$žABÁ1C0ÂAC!ÃC$Ã C!Ã!C$Ã$C-)r/   r   )rY   ÚNone)r\   r   r]   r   r   r   rQ   rX   rR   rX   rY   r“   )r\   r   r   r   r`   rh   rY   r“   )r\   r   r]   r   r   r   rY   rh   )r\   r   rl   r   r   r   rY   úOptional[Dict[str, Any]])r\   r   r   r   rY   úList[Dict[str, Any]])r=   r   rY   r”   )r\   r   rl   r   r   r   rY   rz   )r\   r   rl   r   r]   r   r…   r   r=   r   r}   r   r   r   rY   r“   )r=   r   rY   rh   )
r\   r   r]   r   r   r   rŠ   rz   rY   r•   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r(   r4   r8   r    r_   rf   ri   rm   rp   rs   r{   r†   rˆ   r’   rU   r   r   r   r   c   s�  „ ñAòó KóIó+!ð\ @IÐmqØ6:ñ ]Øð ]Ø(+ð ]Ø;>ð ]Ø^lð ]à'5ð ]ð 
ó ]ðF 4=ÐUYñ!Øð!Ø-0ð!ØNRð!à	ó!ð, ajõ :ð DMñ	*Øð	*Ø*-ð	*Ø=@ð	*à	!ó	*ð 4=ñ	+Øð	+Ø-0ð	+à	ó	+ó*ð bkõ +(ð^ .4Èñ#!Øð#!Ø*-ð#!Ø8;ð#!ØJMð#!àð#!à'*ð#!àCFð#!ð 
ó#!óJð BKÐY[ñ5Øð5Ø(+ð5Ø;>ð5ØSVð5à	ô5r   r   r+   )r   zOptional[str]rY   r   )r™   Ú
__future__r   rd   Úloggingr   rZ   Útypingr   r   r   r   Úhermes_state_commonr   r	   r
   Úhermes_state_errorsr   Ú	getLoggerr"   r   rB   r�   r�   rŽ   r   rU   r   r   ú<module>r       sœ   ðÙ Gå "ã Û Û Û ß ,Ó ,ç dÑ dÝ 4ð 
ˆ×	Ñ	˜>Ó	*€ô'ð$€ðP%ð
 &9Ð$9ð :$ð %:Ð#:ð ;ñ 2°#Ó6Ð7ð 8ðÐ ð&Ð ðÐ ÷V5ò V5r   