
    Jjy                       U d Z ddlmZ ddlZddlmZ ddlmZ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Zddl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mZmZmZ 	 ddlmZ dZn# e$ r d	ZdZY nw xY wddlZdd
lm Z! ej"        #                    d e$ e!e%          &                                j'        d                              ddl(m)Z)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2  e
j3        e4          Z5dZ6dZ7dZ8dZ9dZ:dZ;dZ<dZ=dZ>dZ?h dZ@ ejA        d          ZBdZCh dZD ejE                    ZFdeGd<    ejH                    ZI ejH                    ZJ eK            ZLdeGd<    eK            ZMdeGd <    eK            ZNdeGd!<   d[d$ZOd\d(ZPd]d)ZQd\d*ZRd^d_d,ZSd`d-ZTdad/ZUdbd1ZVd2dddddd3dcd=ZWddd>ZX G d? d@          ZYd^dedCZZd^d	dDdfdFZ[dgdHZ\dhdJZ]didKZ^didLZ_didMZ`didNZadidOZbdidPZcdidQZd G dR dSe,          ZedjdVZfdkdXZgdldYZhdldZZidS )ma  Raft channel platform adapter.

Starts a local wake endpoint, spawns ``raft agent bridge`` as a child process,
and injects content-free wake hints into Hermes' normal gateway session pipeline.
Token and port are auto-generated when not provided via env/config.
The bridge remains responsible for Raft message cursors and body materialization;
the agent uses the Raft CLI according to the Raft manual.
    )annotationsN)deque)datetimetimezone)AnyDequeDictListOptional)webTF)Path   )PlatformPlatformConfig)BasePlatformAdapterMessageEventMessageType
SendResultmerge_pending_message_event)build_session_key	127.0.0.1z/wakedefaulti @  i  i   zraft-activity.v1zraft-activity-drain.v1zx-raft-bridge-token>   bodytextcontentmessagepreviewsnippetmessagesz^[a-zA-Z0-9._:@/ -]+$x   >   schemastatuseventIdtoolName	sessionId	toolInput	truncated
durationMs
errorClass
occurredAt
toolOutputhookEventNametoolInputTruncatedtoolOutputTruncatedz'weakref.WeakSet[RaftAdapter]'_ACTIVE_ADAPTERSzset[str]_RAFT_SESSION_IDS_RAFT_TURN_IDS_RAFT_PROMPT_TURN_IDSreturnboolc                 D    t           sdS t          j        d          sdS dS )ui  Check if Raft channel dependencies are available.

    Intentionally silent on failure — this is a passive probe registered as
    the platform's ``check_fn``. It is called on every
    ``load_gateway_config()`` (message handling, display lookups, agent
    turns), so logging here floods the logs for every user without the
    ``raft`` CLI installed. The caller (``gateway/platform_registry.py``
    ``create_adapter()``) emits its own warning when requirements are not met
    and an adapter is actually requested. This matches the convention used by
    other platform adapters (e.g. ``teams/adapter.py``).
    FraftT)AIOHTTP_AVAILABLEshutilwhich     D/home/rurouni/.hermes/hermes-agent/plugins/platforms/raft/adapter.pycheck_raft_requirementsr=   d   s-      u< u4r;   valuer   strc                    t          | pt                                                    pt          }|                    d          sd| }|S )N/)r?   DEFAULT_PATHstrip
startswith)r>   paths     r<   _path_valuerF   w   sI    u$%%++--=D??3 4zzKr;   c                `   t          | t                    rj|                                 D ]T\  }}t          |                                                                          t          v r dS t          |          r dS Un.t          | t                    rt          d | D                       S dS )NTc              3  4   K   | ]}t          |          V  d S N)_has_content_field).0items     r<   	<genexpr>z%_has_content_field.<locals>.<genexpr>   s+      >>%d++>>>>>>r;   F)

isinstancedictitemsr?   rC   lower_CONTENT_FIELD_NAMESrJ   listany)r>   keynesteds      r<   rJ   rJ   ~   s    % ? ;;== 	 	KC3xx~~%%''+???tt!&)) tt	
 
E4	 	  ?>>>>>>>>5r;   c                B    t          t          | d|           pd          S )Nr>    )r?   getattr)r>   s    r<   _platform_valuerZ      s!    wugu--3444r;   Optional[str]c                    t          | t                    s|S | rt          |           t          k    r|S t                              |           s|S | S rI   )rN   r?   len_MAX_SCALAR_LENGTH_SAFE_SCALAR_REmatch)r>   r   s     r<   _safe_scalarra      sW    eS!!  CJJ!333  '' Lr;   c                     t          j        t          j                                                                      dd          S )Nz+00:00Z)r   nowr   utc	isoformatreplacer:   r;   r<   _now_isorh      s0    <%%//1199(CHHHr;   Optional[tuple[str, bool]]c                    | d S t          | t                    r| }n*	 t          j        | dd          }n# t          $ r Y d S w xY w|sd S t          |          t          k    r|d t                   dfS |dfS )NFT)ensure_ascii	sort_keys)rN   r?   jsondumps	Exceptionr]   ACTIVITY_CONTENT_CAP)r>   r   s     r<   _content_stringrq      s    }t% 	:e%4HHHDD 	 	 	44	 t
4yy''')))*D00;s   6 
AAOptional[int]c                    t          | t          t          f          rt          | t                    rd S t          |           }|dk     rd S |S )Nr   )rN   intfloatr4   )r>   durations     r<   _duration_msrw      sL    ec5\** j.E.E t5zzH!||tOr;   ok)r"   	tool_name
tool_inputtool_outputerror_classduration_mshook_event_name
session_idr"   ry   rz   r{   r|   r}   Dict[str, Any]c                   t           dt          j                     t          |d          pd| |dk    rdndt	                      d}t          |          }	|	r|	|d<   t          |          }
|
r|
|d<   t          |          }|||d<   d	}t          |          }|r|\  |d
<   }|rd|d<   d}t          |          }|r|\  |d<   }|rd|d<   d}|rd|d<   |S )Nzhermes-unknownerrorrx   )r!   r#   r%   r,   r"   r*   r$   r)   r(   Fr&   Tr-   r+   r.   r'   )ACTIVITY_EVENT_SCHEMAuuiduuid4ra   rh   rw   rq   )r~   r   r"   ry   rz   r{   r|   r}   eventsafe_tool_namesafe_error_classsafe_duration_msr'   input_valueinput_truncatedoutput_valueoutput_truncateds                    r<   _make_activity_eventr      sE    (+TZ\\++!*i88EI(#w..''Djj E "),,N +*j#K00 /.l#K00#.lI!*--K .9+kO 	*.E&'I";//L 0<-l- 	+/E'(I "!kLr;   c                   t          | t                    st          d          |                     d          t          k    rt          d          t          |           t          z
  }|r&t          dt          |          d          d          dD ]7}t          |                     |                    st          d| d	          8|                     d
          dvrt          d          |                     d          1t          |                     d                    st          d          |                     d          1t          |                     d                    st          d          |                     d          1t          |                     d                    t          d          dD ]R}|                     |          ;t          |                     |          t                    st          d| d          St          |           }|                    d          t          |d                   |d<   dD ]y}|                    |          }|t          |t                    st          d| d          t          |          t          k    r|d t                   ||<   d|d<   d|| d<   z|S )Nz activity event must be an objectr!   z!unsupported activity event schemazactivity event field r   z is not allowed)r#   r%   r,   r*   zactivity event z  must be a safe non-empty stringr"   >   rx   r   z&activity event status must be ok|errorr$   z-activity event toolName must be a safe stringr)   z/activity event errorClass must be a safe stringr(   z7activity event durationMs must be a non-negative number)r'   r-   r.   z must be a boolean)r&   r+   z must be a stringTr'   	Truncated)rN   rO   
ValueErrorgetr   set_ACTIVITY_ALLOWED_FIELDSsortedra   rw   r4   r?   r]   rp   )r>   r   rU   r   r   s        r<   _validate_activity_eventr      s   eT"" =;<<<yy333<===%jj33G VT1CTTTUUUF V VEIIcNN++ 	VTsTTTUUU	Vyy/11ABBByy(eii
>S>S1T1T(HIIIyy*<		,@W@W3X3X*JKKKyy*|EIIl<S<S/T/T/\RSSSI H H99S>>%j3.N.N%FsFFFGGGKKEyy**5+>??l* 	, 	,))C..?'3'' 	GEsEEEFFFw<<... !6"6!67E#J!%E+'+ES###$Lr;   c                  H    e Zd ZdZefddZdd	ZdddZedd            Z	dS )ActivityQueuez@Bounded at-most-once queue for Raft external activity telemetry.caprt   c                    t          dt          |pt                              | _        t	                      | _        d| _        t          j                    | _	        d S )N   r   )
maxrt   DEFAULT_ACTIVITY_QUEUE_CAP_capr   _events_dropped_since_drain	threadingLock_lock)selfr   s     r<   __init__zActivityQueue.__init__  sG    3s@&@AABB	.3gg$%!^%%


r;   r   r   r3   Nonec                ^   t          |          }| j        5  | j                            |           t	          | j                  | j        k    rF| j                                         | xj        dz  c_        t	          | j                  | j        k    Fd d d            d S # 1 swxY w Y   d S )Nr   )r   r   r   appendr]   r   popleftr   )r   r   	validateds      r<   pushzActivityQueue.push  s    ,U33	Z 	/ 	/L	***dl##di//$$&&&))Q.)) dl##di//	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/ 	/s   A>B""B&)B&   
max_eventsc                t   t          dt          |pd                    }| j        5  g }| j        rYt	          |          |k     rF|                    | j                                                   | j        rt	          |          |k     F| j        }d| _        d d d            n# 1 swxY w Y   t          ||dS )Nr   r   r   )r!   eventsdropped)	r   rt   r   r   r]   r   r   r   ACTIVITY_DRAIN_SCHEMA)r   r   limitr   r   s        r<   drainzActivityQueue.drain  s    As:,--..Z 	* 	*+-F, 63v;;#6#6dl2244555 , 63v;;#6#6/G()D%	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 	* 06gVVVs   A1B$$B(+B(c                l    | j         5  t          | j                  cd d d            S # 1 swxY w Y   d S rI   )r   r]   r   r   s    r<   sizezActivityQueue.size'  s{    Z 	% 	%t|$$	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%s   )--N)r   rt   r   r   r3   r   )r   )r   rt   r3   r   )r3   rt   )
__name__
__module____qualname____doc__r   r   r   r   propertyr   r:   r;   r<   r   r     s        JJ"< & & & & &/ / / /W W W W W % % % X% % %r;   r   turn_idr   c                    t          |           }t          |          }t          5  |rt                              |           |rt                              |           d d d            d S # 1 swxY w Y   d S rI   )ra   _RAFT_CONTEXT_LOCKr0   addr1   )r   r   safe_session_idsafe_turn_ids       r<   _remember_raft_contextr   -  s    ":..O((L	 - - 	3!!/222 	-|,,,	- - - - - - - - - - - - - - - - - -s   9A,,A03A0forget_sessionr   c               *   t          |           }t          |          }t          5  |r4t                              |           t                              |           |r|rt
                              |           d d d            d S # 1 swxY w Y   d S rI   )ra   r   r1   discardr2   r0   )r   r   r   r   r   s        r<   _forget_raft_contextr   7  s    ":..O((L	 7 7 	8""<000!)),777 	7o 	7%%o6667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7s   ABBBkwargsc                    t          |                     d                    dk    r8t          |                     d          |                     d                     dS t          |                     d                    }t          |                     d                    }t          5  t          |r	|t          v p
|o|t          v           cd d d            S # 1 swxY w Y   d S )Nplatformr6   r   r   T)rZ   r   r   ra   r   r4   r1   r0   )r   r   r   s      r<   _is_raft_contextr   B  s   vzz*--..&88vzz,77I9N9NOOOt"6::l#;#;<<O

9 5 566L	 
 
<ln< JHO7H$H
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   *#CC!Cr   c                    t           5  t          t                    }d d d            n# 1 swxY w Y   |D ]}|                    |            d S rI   )_ACTIVE_ADAPTERS_LOCKrS   r/   report_activity)r   adaptersadapters      r<   _report_activityr   O  s    	 * *())* * * * * * * * * * * * * * * ' '&&&&' 's   )--c                    t          d
i | sd S 	 ddlm}  |dg           n,# t          $ r t                              dd           Y nw xY wt          t          d|                     d          	                     d S )Nr   )register_env_passthroughRAFT_PROFILEz6[raft] failed to register RAFT_PROFILE env passthroughTexc_infoSessionStartr   r~   r   r:   )	r   tools.env_passthroughr   ro   loggerdebugr   r   r   )r   r   s     r<   _on_session_startr   V  s    %%f%% ^BBBBBB  .!12222 ^ ^ ^MX\]]]]]^*zz,//	
 	
 	
    s   # &AAc                 l   t          di | sd S t          |                     d                    }|rPt          5  |t          v r	 d d d            d S t                              |           d d d            n# 1 swxY w Y   t          t          d|                     d                               d S )Nr   UserPromptSubmitr   r   r:   )r   ra   r   r   r2   r   r   r   )r   r   s     r<   _on_pre_llm_callr   g  s(   %%f%% 

9 5 566L 4 	4 	4444	4 	4 	4 	4 	4 	4 	4 	4 "%%l333	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 	4 .zz,//	
 	
 	
    s   A8A88A<?A<c            
         t          di | sd S t          t          d|                     d          |                     d          |                     d                               d S )N
PreToolUser   ry   args)r~   r   ry   rz   r:   r   r   r   r   r   s    r<   _on_pre_tool_callr   x  s{    %%f%% (zz,//jj--zz&))		
 	
 	
    r;   c                     t          di | sd S |                     d          dv s|                     d          rdnd}|dk    rdnd}t          t          ||                     d          ||                     d	          |                     d
          |                     d          p|                     d          |                     d          p	|dk    rdnd |                     d                               d S )Nr"   >   r   blocked
error_typer   rx   PostToolUseFailurePostToolUser   ry   r   error_messageresulttool_failurer}   )r~   r   r"   ry   rz   r{   r|   r}   r:   )r   r   r   r   )r   r"   	hook_names      r<   _on_post_tool_callr     s   %%f%% 

8,,0DDD

S_H`H`DWWfjF(.'(9(9$$}I%zz,//jj--zz&))

?33Kvzz(7K7K

<00cvQXGXGX^^^b

=11		
 		
 		
    r;   c                     t          di | sd S t          t          d|                     d                               d S )NStopr   r   r:   r   r   s    r<   _on_post_llm_callr     s]    %%f%% "zz,//	
 	
 	
    r;   c            
     z   t          d
i | sd S |                     d          s|                     d          du rJt          t          d|                     d          d|                     d          rdnd                     t	          |                     d          |                     d	                     d S )Ninterrupted	completedFr   r   r   
incomplete)r~   r   r"   r|   r   r:   )r   r   r   r   r   r   s    r<   _on_session_endr     s    %%f%% zz-   
FJJ{$;$;u$D$D  &!::l33-3ZZ-F-FXMML	  	
 	
 	
 L116::i3H3HIIIIIr;   c                     t          di | sd S t          t          d|                     d                               t	          |                     d          |                     d          d           d S )N
SessionEndr   r   r   Tr   r:   )r   r   r   r   r   r   s    r<   _on_session_finalizer     s    %%f%% (zz,//	
 	
 	
   L116::i3H3HY]^^^^^^r;   c                       e Zd ZdZd. fdZed/d            Zdd	d0dZd1dZd2dZ	d1dZ
	 	 d3d4dZd5dZd6d!Zd6d"Zd6d#Zd6d$Zd7d&Zd8d(Zd9 fd+Zed/d,            Zd:d-Z xZS );RaftAdapterz5Local HTTP endpoint for Raft channel bridge delivery.configr   c                   t                                          |t          d                     |j        pi }t	          |                    dt                              | _        t          |                    dt                              | _
        t          |                    dt                              | _        t	          |                    dd                    | _        t	          |                    dt                    pt                    | _        t          |                    dt"                              | _        d | _        d | _        t+                      | _        d S )	Nr6   hostportrE   bridge_tokenrX   runtime_sessionmax_body_bytes)superr   r   extrar?   r   DEFAULT_HOST_hostrt   DEFAULT_PORT_portrF   rB   _path_bridge_tokenDEFAULT_RUNTIME_SESSION_runtime_sessionDEFAULT_MAX_BODY_BYTES_max_body_bytes_runner_bridge_processr   _activity_queue)r   r   r  	__class__s      r<   r   zRaftAdapter.__init__  s   &!1!1222"eii==>>
eii==>>
%eii&E&EFF
"%eii&C&C"D"D%(II')@AA '&&
 &
 %(II&(>??%
 %
 ;?,r;   r3   r?   c                    | j         S rI   )r  r   s    r<   r  zRaftAdapter.runtime_session  s    $$r;   F)is_reconnectr  r4   c                 K   | j         s3t          j        d          | _         t                              d           t          j        | j                  }|j        	                    d| j
                   |j                            | j        | j                   |j                            d| j                   |j        	                    d| j                   | j        dk    rdd l}	 |                    |j        |j                  5 }|                    d           |                    d	| j        f           d d d            n# 1 swxY w Y   t                              d
| j                   dS # t.          t0          f$ r Y nw xY wt          j        |          | _        | j                                         d {V  t          j        | j        | j        | j                  }|                                 d {V  | j        }|dk    r=|j        r6|j        j         r*|j        j         d         !                                d         }| "                                 tF          5  tH          %                    |            d d d            n# 1 swxY w Y   t                              d| j        || j                   | &                    |           dS )N    z"[raft] Auto-generated bridge token)client_max_sizez/health	/activity/activity/drainr   r   r   zF[raft] Port %d already in use. Set platforms.raft.extra.port in configFz([raft] Raft channel listening on %s:%d%sT)'r  secrets	token_hexr   infor   Applicationr  routeradd_get_handle_healthadd_postr  _handle_wake_handle_activity_handle_activity_drainr  socketAF_INETSOCK_STREAM
settimeoutconnectr   ConnectionRefusedErrorOSError	AppRunnerr  setupTCPSiter	  start_serversocketsgetsockname_mark_connectedr   r/   r   _spawn_bridge)r   r  app_socketsocksite
bound_ports          r<   r,  zRaftAdapter.connect  s%     ! 	>!(!22!6!6DKK<=== od.BCCC
9d&9:::
DJ(9:::
K)>???
,d.IJJJ:??$$$$
^^GOW5HII <TOOA&&&LL+tz!:;;;< < < < < < < < < < < < < < < \J   u*G4    }S))l  """""""""{4<TZ@@jjllZ
??t|?0D?-a0<<>>qAJ" 	' 	'  &&&	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	'>
JX\Xbccc:&&&tsH   , E7 2E
>E7 
EE7 E#E7 7F
F*JJJr   c                Z  K   |                                   | j        r&| j                                         d {V  d | _        t          5  t                              |            d d d            n# 1 swxY w Y   |                                  t                              d           d S )Nz[raft] Disconnected)	_stop_bridger  cleanupr   r/   r   _mark_disconnectedr   r  r   s    r<   
disconnectzRaftAdapter.disconnect  s      < 	 ,&&(((((((((DL" 	+ 	+$$T***	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+!!!)*****s   A22A69A6r  rt   c           	     D   t          j        d          }|st                              d           d S t          j                            dd          }|st                              d           d S d| j         d| | j         }|d|d	d
ddd|g	}i t          j        d| j	        i}	 t          j        ||t          j                  | _        t                              d| j        j        ||           d S # t           $ r t                              d           Y d S w xY w)Nr6   uP   [raft] raft CLI not found in PATH; bridge not spawned — wake-only polling moder   rX   z/[raft] RAFT_PROFILE not set; bridge not spawnedzhttp://:z	--profileagentbridgez--wake-adapterzwake-channelz--wake-channel-endpointRAFT_CHANNEL_TOKEN)envstdinz3[raft] Spawned bridge pid=%d profile=%s endpoint=%sz[raft] Failed to spawn bridge)r8   r9   r   warningosenvironr   r	  r  r  
subprocessPopenDEVNULLr  r  pidro   	exception)r   r  raft_binprofileendpointcmdrG  s          r<   r7  zRaftAdapter._spawn_bridge  sI   <'' 	NNmnnnF*..44 	NNLMMMF<TZ<<$<
<<k7Xn%x	
 GF143EFF	>#-#3J$6$ $ $D  KKMtOcOgiprz{{{{{ 	> 	> 	><======	>s   (AC7 7$DDc                   | j         }|d S d | _         	 |                                 |                    d           t                              d|j                   d S # t          j        $ r8 |                                 t          	                    d|j                   Y d S t          $ r t                              d           Y d S w xY w)N   )timeoutz)[raft] Bridge process terminated (pid=%d)z3[raft] Bridge process killed after timeout (pid=%d)z[raft] Error stopping bridge)r  	terminatewaitr   r  rO  rL  TimeoutExpiredkillrI  ro   rP  )r   procs     r<   r>  zRaftAdapter._stop_bridge+  s    #<F#	=NNIIaI   KKCTXNNNNN( 	\ 	\ 	\IIKKKNNPRVRZ[[[[[[ 	= 	= 	=;<<<<<<	=s   A
A   AC&#CCNchat_idr   reply_tor[   metadataOptional[Dict[str, Any]]r   c                Z   K   t                               d           t          d          S )Nz;[raft] adapter send is a no-op; agent delivers via raft CLIT)success)r   r   r   )r   r]  r   r^  r_  s        r<   sendzRaftAdapter.send:  s,       	RSSS$''''r;   r   c                   K   d| ddS )Nzraft/r6   )nametyper:   )r   r]  s     r<   get_chat_infozRaftAdapter.get_chat_infoD  s      )))6:::r;   request'web.Request''web.Response'c           	     ^   K   t          j        dd| j        | j        j        dddd          S )Nrx   r6   r  r  )	queueSizerS  drainEndpoint)r"   r   runtimeSessionactivity)r   json_responser  r  r   )r   rh  s     r<   r#  zRaftAdapter._handle_healthG  sJ       ""&"7!%!5!: +%6 		 	
 
 	
r;   c                N  K   |                      |j                            t          d                    st	          j        dddd          S |j        pd}|| j        k    rt	          j        dddd	          S 	 |                                 d {V }nR# t          j	        $ r t	          j        dddd	          cY S t          $ r t	          j        dd
dd          cY S w xY wt          |          | j        k    rt	          j        dddd	          S i }|                                rt	 t          j        |          }n.# t          j        $ r t	          j        dddd          cY S w xY wt!          |t"                    st	          j        dddd          S |}t%          |          rt	          j        dddd          S |                     |           d {V }|st	          j        dd| j        dd          S t	          j        d| j        dd          S )NrX   Funauthorizedrx   r     r"   r   payload_too_large  bad_request  invalid_jsoninvalid_payloadcontent_not_allowed	not_ready)rx   r   rn  i  T)rx   rn     )_validate_bridge_tokenheadersr   BRIDGE_TOKEN_HEADERr   rp  content_lengthr  readHTTPRequestEntityTooLargero   r]   rC   rm   loadsJSONDecodeErrorrN   rO   rJ   _accept_waker  )r   rh  r  raw_bodypayloadparsedaccepteds          r<   r%  zRaftAdapter._handle_wakeU  s     **7?+>+>?RTV+W+WXX 	Y$EN%K%KTWXXXX /41D000$E<O%P%PY\]]]]	X$\\^^++++++HH, 	^ 	^ 	^ $E<O%P%PY\]]]]]] 	X 	X 	X$EM%J%JSVWWWWWW	Xx==4/// $E<O%P%PY\]]]]"$>> 	]H--' ] ] ]()O)OX[\\\\\\]fd++ `(@Q)R)R[^____G g&& 	`$E<Q%R%R[^____**733333333 	$(&*&; 
      "&"7  
 
 
 	
s*   =B (C'"C'&C'2E (E21E2c                  K   |                      |j                            t          d                    st	          j        dddd          S |j        pd}|| j        k    rt	          j        dddd	          S 	 |                                 d {V }nf# t          j	        $ r t	          j        dddd	          cY S t          $ r0}t	          j        dt          |          dd
          cY d }~S d }~ww xY wt          |                    d                    | j        k    rt	          j        dddd	          S 	 t          j        |          }| j                            |           nf# t          j        $ r t	          j        dddd
          cY S t          $ r0}t	          j        dt          |          dd
          cY d }~S d }~ww xY wt	          j        ddid          S )NrX   Frr  rs  rt  ru  r   rv  rw  ry  zutf-8rz  rx   Tr~  )r  r  r   r  r   rp  r  r  r   r  ro   r?   r]   encoderm   r  r  r   r  )r   rh  r  raw_textexcr  s         r<   r&  zRaftAdapter._handle_activity  sj     **7?+>+>?RTV+W+WXX 	Y$EN%K%KTWXXXX /41D000$E<O%P%PY\]]]]	S$\\^^++++++HH, 	^ 	^ 	^ $E<O%P%PY\]]]]]] 	S 	S 	S$ECHH%E%EcRRRRRRRRR	Sxw''((4+??? $E<O%P%PY\]]]]	Sj**G %%g....# 	Y 	Y 	Y$EN%K%KTWXXXXXX 	S 	S 	S$ECHH%E%EcRRRRRRRRR	S  $c::::sH   =B (C;	C;%C60C;6C;.E2 2(G	G%%G
GGc                n  K   |                      |j                            t          d                    st	          j        dddd          S 	 t          |j                            dd                    }n# t          $ r d	}Y nw xY wt	          j        | j	        
                    |                    S )
NrX   Frr  rs  rt  ru  r   200r   )r  r  r   r  r   rp  rt   queryr   r  r   )r   rh  r   s      r<   r'  z"RaftAdapter._handle_activity_drain  s      **7?+>+>?RTV+W+WXX 	Y$EN%K%KTWXXXX	W]..ue<<==JJ 	 	 	JJJ	 !5!;!;J!G!GHHHs   (A9 9BBtokenc                L    | j         r|sdS t          j        || j                   S )NF)r  hmaccompare_digest)r   r  s     r<   r  z"RaftAdapter._validate_bridge_token  s/    ! 	 	5"5$*<===r;   r  c                  K   | j         st                              d           dS t          |                    d          p|                    d          py|                    d          pd|                    d          pO|                    d          p:|                    d          p%d	t          t          j                    d
z                       }|                     | j        dddd          }t          | 
                                t          j        |||d          }	 |                     |           d {V  n+# t          $ r t                              d           Y dS w xY wdS )Nz@[raft] Wake received before gateway message handler was attachedFr#   	attemptId	messageIddelivery_idwake_ididz
raft-wake-i  zRaft channeldmzraft-bridgezRaft Bridge)r]  	chat_name	chat_typeuser_id	user_nameT)r   message_typesourceraw_message
message_idinternalz"[raft] Failed to inject wake event)_message_handlerr   rI  r?   r   rt   timebuild_sourcer  r   _wake_promptr   TEXThandle_messagero   rP  )r   r  r  r  r   s        r<   r  zRaftAdapter._accept_wake  s     $ 	NN]^^^5KK	"" 6{{;''6{{;''6 {{=))6 {{9%%	6
 {{4  6 6C	d 23355
 
 "")$!# # 
 
 ""$$$)"
 
 
	%%e,,,,,,,,,, 	 	 	ABBB55	 ts   (E $E,+E,r   r   c                  K   | j         sdS t          |j        | j        j                            dd          | j        j                            dd                    }|| j        v r3t                              d|           t          | j
        ||           dS t                                          |           d{V  dS )zBAccept Raft wake hints without interrupting an active Hermes turn.Ngroup_sessions_per_userTthread_sessions_per_userF)r  r  z&[raft] Wake queued for busy session %s)r  r   r  r   r  r   _active_sessionsr   r   r   _pending_messagesr  r  )r   r   session_keyr  s      r<   r  zRaftAdapter.handle_message  s      $ 	F'L$(K$5$9$9:SUY$Z$Z%)[%6%:%:;UW\%]%]
 
 
 $///LLA;OOO'(>USSSFgg$$U+++++++++++r;   c                     	 dS )NzRaft wake hint received. New Raft messages may be pending. If you have not read the Raft manual in this session, run `raft manual get raft-cli-overview` before using Raft commands.r:   r:   r;   r<   r  zRaftAdapter._wake_prompt  s    N	
 	
r;   c                    	 | j                             |           d S # t          $ r  t                              dd           Y d S w xY w)Nz/[raft] activity event dropped during validationTr   )r  r   ro   r   r   )r   r   s     r<   r   zRaftAdapter.report_activity  se    	[ %%e,,,,, 	[ 	[ 	[LLJUYLZZZZZZ	[s    &AA)r   r   r3   r?   )r  r4   r3   r4   r3   r   )r  rt   r3   r   )NN)
r]  r?   r   r?   r^  r[   r_  r`  r3   r   )r]  r?   r3   r   )rh  ri  r3   rj  )r  r?   r3   r4   )r  r   r3   r4   )r   r   r3   r   r   )r   r   r   r   r   r   r  r,  rA  r7  r>  rc  rg  r#  r%  r&  r'  r  r  r  staticmethodr  r   __classcell__)r  s   @r<   r   r     s       ??/ / / / / /$ % % % X% 5: - - - - - -^+ + + +> > > >6= = = =& #'-1( ( ( ( (; ; ; ;
 
 
 
5
 5
 5
 5
n; ; ; ;>I I I I> > > >
" " " "H, , , , , ,$ 
 
 
 \
[ [ [ [ [ [ [ [r;   r   r   r   c                    | j         pi }t          |                    d          p|                    d                    S )Nenabledr  )r  r4   r   )r   r  s     r<   _is_connectedr    s9    LBE		)$$A		.(A(ABBBr;   Optional[dict]c                 6    t          j        d          sdS ddiS )zSeed PlatformConfig.extra from env vars during gateway config load.

    Auto-enables when RAFT_PROFILE is set (the adapter needs it anyway).
    r   Nr  T)rJ  getenvr:   r;   r<   _env_enablementr    s&    
 9^$$ ttr;   c                    ddl m} m}m}m}m}m} ddlm}m	}  | d            |d          }|r, |d| d            |dd	          s |d
| d           dS  |d            |d            |d           t                        |d|pd          }	|	s |d           dS  |d|	                                           t                        |d            |d           dS )a$  Interactive ``hermes gateway setup`` flow for the Raft platform.

    Lazy-imports CLI helpers so the plugin stays importable in gateway runtime
    and test contexts. The flow persists ``RAFT_PROFILE`` to the Hermes env
    file so the Raft adapter auto-enables after a gateway restart.
    r   )print_header
print_infoprint_successprint_warningpromptprompt_yes_no)get_env_valuesave_env_valueRaftr   z#Raft: already configured (profile: )zReconfigure Raft?FzKeeping RAFT_PROFILE=.Nz,Connect Hermes to Raft as an external agent.z2Create the External Agent in Raft first, then run:zQ  raft agent login --server <server-url> --agent <agent-id> --profile-slug <slug>zRaft profile slugrX   )r   z2Raft profile slug is required; skipping Raft setupzRaft configuration savedzFRestart the gateway for changes to take effect: hermes gateway restart)hermes_cli.cli_outputr  r  r  r  r  r  hermes_cli.configr  r  printrC   )
r  r  r  r  r  r  r  r  existing_profilerR  s
             r<   interactive_setupr    s                   @???????L$}^44 
L9ILLLMMM}0%88 	JB/?BBBCCCFJ=>>>JCDDDJbccc	GGGf(2B2HbIIIG JKKKN>7==??333	GGGM,---JWXXXXXr;   c                P   |                      ddd t          t          dgdt          t          dd                    t          j                            dd          	          
           | 	                    dt                     | 	                    dt                     | 	                    dt                     | 	                    dt                     | 	                    dt                     | 	                    dt                     | 	                    dt                      dS )u:   Plugin entry point — called by the Hermes plugin system.r6   r  c                     t          |           S rI   )r   )cfgs    r<   <lambda>zregister.<locals>.<lambda>=  s    K$4$4 r;   r   z,Install the Raft CLI from https://raft.buildu   🔔a&  You are connected to Raft via an external-agent channel. Run `raft --profile {profile} profile show` to confirm which agent profile is active. Run `raft --profile {profile} manual get raft-cli-overview` to learn available Raft commands. Always pass `--profile {profile}` to every raft CLI call.zyour-agent-profile)rR  )re  labeladapter_factorycheck_fnis_connectedrequired_envinstall_hintsetup_fnenv_enablement_fnemojiplatform_hinton_session_startpre_llm_callpre_tool_callpost_tool_callpost_llm_callon_session_endon_session_finalizeN)register_platformr=   r  r  r  formatrJ  rK  r   register_hookr   r   r   r   r   r   r   )ctxs    r<   registerr  8  s   44("$%C")H &8LMM&
N
N!    $ (*;<<<n&6777o'8999&(:;;;o'8999&888+-ABBBBBr;   )r3   r4   )r>   r   r3   r?   )r>   r   r3   r4   rI   )r>   r   r   r[   r3   r[   r  )r>   r   r3   ri   )r>   r   r3   rr   )r~   r?   r   r   r"   r?   ry   r   rz   r   r{   r   r|   r   r}   r   r3   r   )r>   r   r3   r   )r   r   r   r   r3   r   )r   r   r   r   r   r4   r3   r   )r   r   r3   r4   r   )r   r   r3   r   )r   r   r3   r4   )r3   r  r  )jr   
__future__r   asynciocollectionsr   r   r   r  rm   loggingrJ  rer  r8   rL  r   r  r   weakreftypingr   r   r	   r
   r   aiohttpr   r7   ImportErrorsyspathlibr   _PathrE   insertr?   __file__resolveparentsgateway.configr   r   gateway.platforms.baser   r   r   r   r   gateway.sessionr   	getLoggerr   r   r  r
  rB   r  r  r   rp   r   r   r  rR   compiler_   r^   r   WeakSetr/   __annotations__r   r   r   r   r0   r1   r2   r=   rF   rJ   rZ   ra   rh   rq   rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r:   r;   r<   <module>r     s     # " " " " "        ' ' ' ' ' ' ' '    				 				              3 3 3 3 3 3 3 3 3 3 3 3 3 3   
CCC 


 ! ! ! ! ! ! 33uuX..008;<< = = = 3 3 3 3 3 3 3 3              . - - - - -		8	$	$#     * 0 +     "*566      4C7?3D3D  D D D D&	(( #Y^%% !cee  # # # #355        "%#%%  ' ' ' '   &   	 	 	 	5 5 5 5    I I I I   "    , , , , , ,^$ $ $ $N% % % % % % % %B- - - - -7Y^ 7 7 7 7 7 7

 

 

 

' ' ' '   "   "
 
 
 
   &   J J J J	_ 	_ 	_ 	_}[ }[ }[ }[ }[% }[ }[ }[@
C C C C
   'Y 'Y 'Y 'YTC C C C C Cs   A$ $	A0/A0