
    
Bj                        U d Z ddlmZ ddlmZ  e       Zeed<    ede      Zeed<    ede      Z	eed	<    ed
e      Z
eed<    ede      Zeed<    ede      Zeed<    ede      Zeed<    ede      Zeed<    ede      Zeed<    ede      Zeed<    ede      Zeed<    ede      Zeed<   ee	e
eeeeeeeedZ	 	 	 	 	 	 	 d,dededed ed!ed"ed#ed$efd%Zd&ed$d'fd(Zd-d)ed*ed$efd+Zy').a   
Session-scoped context variables for the Hermes gateway.

Replaces the previous ``os.environ``-based session state
(``HERMES_SESSION_PLATFORM``, ``HERMES_SESSION_CHAT_ID``, etc.) with
Python's ``contextvars.ContextVar``.

**Why this matters**

The gateway processes messages concurrently via ``asyncio``.  When two
messages arrive at the same time the old code did:

    os.environ["HERMES_SESSION_THREAD_ID"] = str(context.source.thread_id)

Because ``os.environ`` is *process-global*, Message A's value was
silently overwritten by Message B before Message A's agent finished
running.  Background-task notifications and tool calls therefore routed
to the wrong thread.

``contextvars.ContextVar`` values are *task-local*: each ``asyncio``
task (and any ``run_in_executor`` thread it spawns) gets its own copy,
so concurrent messages never interfere.

**Backward compatibility**

The public helper ``get_session_env(name, default="")`` mirrors the old
``os.getenv("HERMES_SESSION_*", ...)`` calls.  Existing tool code only
needs to replace the import + call site:

    # before
    import os
    platform = os.getenv("HERMES_SESSION_PLATFORM", "")

    # after
    from gateway.session_context import get_session_env
    platform = get_session_env("HERMES_SESSION_PLATFORM", "")
    )
ContextVar)Any_UNSETHERMES_SESSION_PLATFORM)default_SESSION_PLATFORMHERMES_SESSION_CHAT_ID_SESSION_CHAT_IDHERMES_SESSION_CHAT_NAME_SESSION_CHAT_NAMEHERMES_SESSION_THREAD_ID_SESSION_THREAD_IDHERMES_SESSION_USER_ID_SESSION_USER_IDHERMES_SESSION_USER_NAME_SESSION_USER_NAMEHERMES_SESSION_KEY_SESSION_KEYHERMES_SESSION_ID_SESSION_ID!HERMES_CRON_AUTO_DELIVER_PLATFORM_CRON_AUTO_DELIVER_PLATFORM HERMES_CRON_AUTO_DELIVER_CHAT_ID_CRON_AUTO_DELIVER_CHAT_ID"HERMES_CRON_AUTO_DELIVER_THREAD_ID_CRON_AUTO_DELIVER_THREAD_ID)r   r	   r   r   r   r   r   r   r   r   r   platformchat_id	chat_name	thread_iduser_id	user_namesession_keyreturnc           	      "   t         j                  |       t        j                  |      t        j                  |      t        j                  |      t
        j                  |      t        j                  |      t        j                  |      g}|S )a(  Set all session context variables and return reset tokens.

    Call ``clear_session_vars(tokens)`` in a ``finally`` block to restore
    the previous values when the handler exits.

    Returns a list of ``Token`` objects (one per variable) that can be
    passed to ``clear_session_vars``.
    )r   setr
   r   r   r   r   r   )r   r   r   r    r!   r"   r#   tokenss           </home/ubuntu/.hermes/hermes-agent/gateway/session_context.pyset_session_varsr)   Q   st    $ 	h'W%y)y)W%y)%F M    r'   Nc                 z    t         t        t        t        t        t
        t        fD ]  }|j                  d        y)a+  Mark session context variables as explicitly cleared.

    Sets all variables to ``""`` so that ``get_session_env`` returns an empty
    string instead of falling back to (potentially stale) ``os.environ``
    values.  The *tokens* argument is accepted for API compatibility with
    callers that saved the return value of ``set_session_vars``, but the
    actual clearing uses ``var.set("")`` rather than ``var.reset(token)``
    to ensure the "explicitly cleared" state is distinguishable from
    "never set" (which holds the ``_UNSET`` sentinel).
     N)r   r
   r   r   r   r   r   r&   )r'   vars     r(   clear_session_varsr.   n   s7     	 	 		r*   namer   c                     ddl }t        j                  |       }||j                         }|t        ur|S |j	                  | |      S )u  Read a session context variable by its legacy ``HERMES_SESSION_*`` name.

    Drop-in replacement for ``os.getenv("HERMES_SESSION_*", default)``.

    Resolution order:
    1. Context variable (set by the gateway for concurrency-safe access).
       If the variable was explicitly set (even to ``""``) via
       ``set_session_vars`` or ``clear_session_vars``, that value is
       returned — **no fallback to os.environ**.
    2. ``os.environ`` (only when the context variable was never set in
       this context — i.e. CLI, cron scheduler, and test processes that
       don't use ``set_session_vars`` at all).
    3. *default*
    r   N)os_VAR_MAPgetr   getenv)r/   r   r1   r-   values        r(   get_session_envr6      sC     
,,t
C
	L99T7##r*   )r,   r,   r,   r,   r,   r,   r,   )r,   )__doc__contextvarsr   typingr   objectr   __annotations__r   r
   r   r   r   r   r   r   r   r   r   r2   strlistr)   r.   r6    r*   r(   <module>r?      s  $L # 
 h  !++Df U : U)*BFS * S!+,FPV!W J W!+,FPV!W J W)*BFS * S!+,FPV!W J W%&:FKj K$%8&IZ I +55Xbh*i Z i)34V`f)g J g+56Zdj+k j k  1. 2 2. 2&$)D(B*F    	
    
:t  .$# $ $S $r*   