+
    lHàjô3  ã                  ód  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIHtHtHt ^ RIHt ^ RIHt ]P*                  ! R4      t ! R R4      tR	 R
 ltR R ltR tR R ltR tR R ltR%R R lltR R ltR R lt RRRR/R R llt!RR/R R llt"R  t#R!R"/R# R$ llt$R# )&af  Background-loop plumbing for tools.mcp_tool: cross-process discovery file lock, scheduling
coroutines onto the MCP loop from caller threads (with profile HOME override and dashboard OAuth
flow propagation) and the loop's exception handler. Origin state (``_lock``, ``_mcp_loop``) is
read through ``_core`` so ``mock.patch("tools.mcp_tool.X")`` keeps working.)ÚannotationsN)ÚAnyÚ	CoroutineÚOptional)Ú_core)Úmcp_tool_lifecycleztools.mcp_toolc                  ó2   € ] tR t^tRtR R ltR R ltRtR# )Ú_LockCookiez Holds a cross-process file lock; ``release()`` drops it. The file object MUST stay open while
held: both fcntl and portalocker locks are tied to the descriptor.c               ó    € V ^8„  d   QhRRRR/# )é   Úfhr   ÚreturnÚNone© )Úformats   "Ú8/home/ubuntu/.hermes/hermes-agent/tools/mcp_tool_loop.pyÚ__annotate__Ú_LockCookie.__annotate__   s   € ÷ ñ ˜3ð  4ñ ó    c                	ó   € Wn         R # ©N©Ú_fh)Úselfr   s   &&r   Ú__init__Ú_LockCookie.__init__   s   € ØŽr   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r      s   € ÷ ñ ˜ñ r   c                	ó:  € V P                   f   R # \        P                  ! \        4      ;_uu_ 4        \        P
                  R8X  d:   ^ R IpVP                  V P                   P                  4       VP                  4       M^ R I
pVP                  V P                   4       R R R 4       \        P                  ! \        4      ;_uu_ 4        V P                   P                  4        R R R 4       R V n         R #   + '       g   i     L^; i  + '       g   i     L,; i)NÚposix)r   Ú
contextlibÚsuppressÚ	ExceptionÚosÚnameÚfcntlÚflockÚfilenoÚLOCK_UNÚportalockerÚunlockÚclose)r   r%   r)   s   &  r   ÚreleaseÚ_LockCookie.release   s¥   € Ø�8‰8ÒÙä× Ò ¤×+Õ+Ü�w‰w˜'Ô!ÛØ—‘˜DŸH™HŸO™OÓ-¨u¯}©}Õ=ã"Ø×"Ñ" 4§8¡8Ô,÷ ,ô × Ò ¤×+Õ+Ø�H‰H�N‰NÔ÷ ,àˆŽ÷ ,×+ú÷ ,×+ús   ³A.C7ÃD
Ã7D	Ä
D	r   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r,   Ú__static_attributes__r   r   r   r	   r	      s   † ñJõ÷ñ r   r	   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   Úboolr   )r   s   "r   r   r   .   s   € ÷ ñ ˜Cð  Dñ r   c                óö  € \         P                  R8X  dC   ^ RIp VP                  V P	                  4       VP
                  VP                  ,          4       R# ^ RIp VP                  WP
                  VP                  ,          4       R#   \         dK   pTP                  \        P                  \        P                  \        P                  39   d    Rp?R# h Rp?ii ; i  TP                   d     R# i ; i)zµNon-blocking exclusive lock (fcntl on POSIX, portalocker elsewhere). False when another process
holds it; unexpected errors propagate so the caller can treat locking as unavailable.r   NFT)r#   r$   r%   r&   r'   ÚLOCK_EXÚLOCK_NBÚOSErrorÚerrnoÚEACCESÚEAGAINÚEWOULDBLOCKr)   ÚlockÚLockException)r   r%   Úer)   s   &   r   Ú_acquire_lock_on_fhrA   .   s¼   € ô 
‡w�w�'ÔÛð	Ø�K‰K˜Ÿ	™	› U§]¡]°U·]±]Õ%BÔCñ
 ÛðØ×Ñ˜×0Ñ0°;×3FÑ3FÕFÔGñ øô ô 	Ø�w‰wœ5Ÿ<™<¬¯©´u×7HÑ7HÐIÔIÝØûð	ûð ×$Ñ$ô Úðús/   ›;B Á,C# ÂC Â>CÃCÃC Ã#C8Ã7C8c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r   B   s   € ÷ ñ ¨ñ r   c                 óð  € ^ RI Hp   ^ RIHpHp V! 4       e   \        V! 4       R,          4      pM6V P                  f   \        V! 4       R,          4      V n        V P                  p\        VRRR7      p \        T4      pT'       d   \        T4      # TP                  4        R#   \         d    \        P                  u # i ; i  \         d$    TP                  4        \        P                  u # i ; i)z‚``_LockCookie`` (acquired), ``None`` (held by another process) or ``_LOCK_UNAVAILABLE``
(locking broken: run discovery unguarded).©Úmcp_tool)Úget_hermes_homeÚget_hermes_home_overrideNz.mcp-discovery.lockÚwzutf-8)Úencoding)ÚtoolsrE   Úhermes_constantsrF   rG   ÚstrÚ_MCP_DISCOVERY_LOCK_PATHÚopenr"   r   Ú_LOCK_UNAVAILABLErA   r+   r	   )Ú_originrF   rG   Ú	lock_pathr   Úacquireds         r   Ú_try_acquire_mcp_discovery_lockrS   B   sÒ   € õ *ð
'ßNÙ#Ó%Ò1Ü™OÓ-Ð0EÕEÓF‰Ià×/Ñ/Ò7Ü36±Ó7HÐK`Õ7`Ó3a�Ô0Ø×8Ñ8ˆIÜ�)˜S¨7Ô3ˆð'Ü& rÓ*ˆ÷ Ü˜2‹ÐØ‡H�H„JÙøô ô 'Ü×&Ñ&Ò&ð'ûô ô 'Ø
�‰Œ
Ü×&Ñ&Ò&ð'ús$   ˆA-B& Á6C Â&CÃCÃ+C5Ã4C5c                óš   € VP                  R4      p\        V\        4      '       d   R\        V4      9   g   V P	                  V4       R# R# )z‡Suppress the benign 'Event loop is closed' RuntimeError httpx finalizers raise against the
dead loop during shutdown; forward the rest.Ú	exceptionzEvent loop is closedN)ÚgetÚ
isinstanceÚRuntimeErrorrL   Údefault_exception_handler)ÚloopÚcontextÚexcs   && r   Ú_mcp_loop_exception_handlerr]   _   s?   € ð �+‰+�kÓ
"€CÜ�sœL×)Ò)Ð.DÌÈCËÔ.PØ×&Ñ& wÖ/ñ /Qr   c               ó    € V ^8„  d   QhRRRR/# )r   Úcoror   r   r   )r   s   "r   r   r   g   s   € ÷ ñ  9ð °ñ r   c                óˆ   a aaa€  ^ RI HpHoHo V! 4       oS'       g   S # V VVV3R lpV! 4       #   \         d    Ro L)i ; i)z‡Carry the caller's context-local HERMES_HOME override into ``coro`` (task-local on the MCP
loop, so concurrent scopes don't interfere).)rG   Úreset_hermes_home_overrideÚset_hermes_home_overrideNc               “  ó`   <"  € S! S4      p  SG R j  x€L
 S! V 4       #  L  S! T 4       i ; i5ir   r   )Útokenr_   Úhome_overridera   rb   s    €€€€r   Ú_scopedÚ)_wrap_with_home_override.<locals>._scopedr   s0   øé € Ù(¨Ó7ˆð	.Ø—:á& uÕ-ñ øá& uÕ-üs    ƒ	.�! ’“! –	.Ÿ! ¡
+«.)rK   rG   ra   rb   r"   )r_   rG   rf   re   ra   rb   s   f  @@@r   Ú_wrap_with_home_overriderh   g   sJ   û€ ðßsÑsÙ0Ó2ˆ÷ Øˆ÷.ð .ñ ‹9Ðøô ô ØŠðús   †1 ±AÁ Ac                óx   a aa€  ^ RI HoHp V! 4       oSf   S # V VV3R lpV! 4       #   \         d    Ro L$i ; i)zBPropagate a dashboard OAuth flow onto the dedicated MCP loop task.)Údashboard_oauth_flowÚget_dashboard_oauth_flowNc               “  ó‚   <"  € S! S4      ;_uu_ 4        S G R j  x€L
 uuR R R 4       #  L  + '       g   i     R # ; i5ir   r   )r_   rj   Úflows   €€€r   rf   Ú0_wrap_with_dashboard_oauth_flow.<locals>._scoped†   s,   øé € Ù! $×'Õ'Ø—:÷ (Ò'Ù÷ (×'Ð'üs    ƒ?”+š)›+ž?©+«<	¶	?)Útools.mcp_dashboard_oauthrj   rk   r"   )r_   rk   rf   rj   rm   s   f  @@r   Ú_wrap_with_dashboard_oauth_flowrp   |   sD   ú€ ðß\Ù'Ó)ˆð ‚|Øˆ÷ñ ‹9Ðøô ô ØŠðús   …) ©9¸9c               ó   € V ^8„  d   QhRR/# )r   r   z#Optional[asyncio.AbstractEventLoop]r   )r   s   "r   r   r   �   s   € ÷ Dñ DÐ:ñ Dr   c                 óÆ   € \         P                  ;_uu_ 4        \         P                  p RRR4       X e   V P                  4       '       d   V # R#   + '       g   i     L.; i)z=The MCP loop when it is up, else None (read under ``_lock``).N)r   Ú_lockÚ	_mcp_loopÚ
is_running)rZ   s    r   Ú_running_looprv   �   s=   € ä	��‹Ü�‰ˆ÷ 
àÒ#¨¯©×(9Ò(9ˆ4ÐC¸tÐC÷ 
�ús   ™AÁA 	c               ó   € V ^8„  d   QhRR/# )r   ÚtimeoutÚfloatr   )r   s   "r   r   r   ”   s   € ÷ #'ñ #'¨uñ #'r   c                óˆ  € ^ RI Hp ^ RIHp \	        4       pVf8   \
        P                  ! V 4      '       d   V P                  4        \        R4      h\        \        \        V 4      '       d   V ! 4       MT 4      4      pV! WT\        RR7      pVf   \        R4      h\        P                  ! 4       pVf   RMWq,           p V! 4       '       d   VP                  4        \!        R4      hVf   R	MV\        P                  ! 4       ,
          p	V	^ 8:  dH   VP                  4        \#        R
\        P                  ! 4       V,
          R R\%        V4      R R24      h VP'                  \)        R	V	4      R7      #   \*        P,                  P"                   d.    TP/                  4       '       d   TP'                  4       u #  EK  i ; i)u»   Schedule a coroutine (or zero-arg factory â€” avoids leaking a never-awaited coroutine when the
loop is down) on the MCP loop and block until done, polling so user interrupts are honored.)Úis_interrupted©Úsafe_schedule_threadsafeNzMCP event loop is not runningzMCP scheduling failed)ÚloggerÚlog_messagez/MCP event loop unavailable (failed to schedule)zUser sent a new messagegš™™™™™¹?zMCP call timed out after z.1fzs (configured timeout: zs)©rx   )Útools.interruptr{   Úagent.async_utilsr}   rv   ÚasyncioÚiscoroutiner+   rX   rp   rh   Úcallabler~   ÚtimeÚ	monotonicÚcancelÚInterruptedErrorÚTimeoutErrorry   ÚresultÚminÚ
concurrentÚfuturesÚdone)
Úcoro_or_factoryrx   r{   r}   rZ   r_   ÚfutureÚ
start_timeÚdeadlineÚ	remainings
   &&        r   Ú_run_on_mcp_loopr•   ”   s€  € õ /Ý:ä‹?€DØ‚|Ü×Ò˜×/Ò/Ø×!Ñ!Ô#ÜÐ:Ó;Ð;ô +Ô+CÜ% o×6Ò6‰Ô¸Oó,Mó N€Dá% d¼ÐMdÔe€FØ‚~ÜÐLÓMÐMÜ—’Ó!€JØ’‰t¨JÕ,@€HØ
Ù×ÒØ�M‰MŒOÜ"Ð#<Ó=Ð=Ø#Ò+‘C°¼D¿NºNÓ<LÕ1Lˆ	Ø˜Œ>Ø�M‰MŒOÜÐ!:¼4¿>º>Ó;KÈjÕ;XÐY\Ð:]ð ^7Ü7<¸W³~ÀcÐ6JÈ"ð Nó Oð Oð	'Ø—=‘=¬¨S°)Ó)<�=Ó=Ð=øÜ×!Ñ!×.Ñ.ô 	'ð �{‰{�}Š}Ø—}‘}“Ò&ó ð	'ús   ÅE5 Å54GÆ*GÇ Gc               ó    € V ^8„  d   QhRRRR/# )r   Úserverr   r   r5   r   )r   s   "r   r   r   º   s   € ÷ ñ ˜cð  dñ r   c                ó  € \        V RR4      pVf   R# \        P                  p\        V\        P
                  4      '       d8   Ve4   VP                  4       '       d   VP                  VP                  4       R# VP                  4        R# )zÝAsk a server task to rebuild its transport, thread-safely: the event lives on the MCP loop,
so set via ``call_soon_threadsafe`` when it runs (direct ``.set()`` otherwise). False when the
server has no reconnect machinery.Ú_reconnect_eventNFT)	Úgetattrr   rt   rW   rƒ   ÚEventru   Úcall_soon_threadsafeÚset)r—   ÚeventrZ   s   &  r   Ú_signal_reconnectrŸ   º   sk   € ô �FÐ.°Ó5€EØ‚}ÙÜ�?‰?€DÜ�%œŸ™×'Ò'¨DÒ,<ÀÇÁ×ARÒARØ×!Ñ! %§)¡)Ô,ñ ð 	�	‰	ŒÙr   c               ó    € V ^8„  d   QhRRRR/# )r   Úserver_namerL   r   r5   r   )r   s   "r   r   r   É   s   € ÷ <ñ < cð <¨dñ <r   c                óî   € ^ RI Hp \        P                  ;_uu_ 4        \        P                  P                  V! V 4      4      pRRR4       XRJ;'       d    \        V4      #   + '       g   i     L'; i)zBAsk a currently-live MCP server to rebuild after external re-auth.)Ú_resolve_server_keyN)Útools.mcp_tool_scoper£   r   rs   Ú_serversrV   rŸ   )r¡   r£   r—   s   &  r   Úreconnect_mcp_serverr¦   É   sN   € å8Ü	��‹Ü—‘×#Ñ#Ñ$7¸Ó$DÓEˆ÷ 
à˜Ð×;Ð;Ô"3°FÓ";Ð;÷ 
�ús   Ÿ&A$Á$A4	Úold_sessionrx   g      .@c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úsrvr   r§   rx   ry   r   r5   r   )r   s   "r   r   r   Ñ   s*   € ÷ ñ ¨ð ¸Sð ÐRWð Ðcgñ r   c          
     ó°  € \        ^\        \        \        V4      R4      R,          4      4      p\        V4       F„  p\	        V RR4      p\	        V RR4      p \        VR4      '       d   \        VP                  4       4      MRpVe   WQJd   V'       d    R# WC^,
          8  g   Kn  \        P                  ! R4       K†  	  R#   \         d    Rp LNi ; i)	a  Poll until the server exposes a usable, ready session (during a reconnect ``srv.session`` is
briefly None or stale; retrying blindly burns breaker strikes). With ``old_session`` the observed
session must differ. Iteration-bounded, not deadline-bounded: tests freeze ``time.monotonic``.g        g      Ð?ÚsessionNÚ_readyÚis_setTF)ÚmaxÚintry   Úrangerš   Úhasattrr5   r­   r"   r†   Úsleep)r©   r§   rx   Ú
iterationsÚir«   ÚreadyÚis_readys   &$$     r   Ú_wait_for_server_session_readyr·   Ñ   s¶   € ô �QœœC¤ g£°Ó4°tÕ;Ó<Ó=€JÜ�:ÖˆÜ˜#˜y¨$Ó/ˆÜ˜˜X tÓ,ˆð	Ü/6°u¸h×/GÒ/G”t˜EŸL™L›NÔ+ÈTˆHð Ò 7Ó#=Ç(ÚØ˜A�~ÖÜ�JŠJ�tÖñ ñ øô ô 	ØŠHð	ús   Á-CÃCÃCc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   r¡   rL   r©   r   Úop_descriptionrx   ry   r   r5   r   )r   s   "r   r   r   ä   s8   € ÷ Yñ Y¨Cð Y°cð YÈcð YÐ\að YÐmqñ Yr   c               óð   a€ \         P                  pVe   VP                  4       '       g   R# R V3R llp\        SRR4      p\        P                  RW4       VP                  V4       \        SWcR7      # )z¾Request a transport rebuild and wait for the fresh session. ``_ready`` is cleared on the loop
BEFORE ``_reconnect_event`` is set, else the readiness poll returns at once on the dead session.NFc               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   Ú0_signal_reconnect_and_wait.<locals>.__annotate__ë   s   € ÷ "ñ " ñ "r   c                 óÆ   <€ \        SR R4      \        SRR4      r\        V R4      '       d   V P                  4        \        VR4      '       d   VP                  4        R# R# )r¬   Nr™   Úclearr�   )rš   r±   r¾   r�   )rµ   Úreconnect_eventr©   s     €r   Ú_request_reconnectÚ6_signal_reconnect_and_wait.<locals>._request_reconnectë   sR   ø€ Ü!(¨¨h¸Ó!=¼wÀsÐL^Ð`dÓ?eˆÜ�5˜'×"Ò"Ø�K‰KŒMÜ�? E×*Ò*Ø×ÑÖ!ñ +r   r«   z2MCP server '%s': %s requesting transport reconnect)r§   rx   )r   rt   ru   rš   r~   Úinforœ   r·   )r¡   r©   r¹   rx   rZ   rÀ   r§   s   &f$$   r   Ú_signal_reconnect_and_waitrÃ   ä   sg   ø€ ô �?‰?€DØ‚|˜4Ÿ?™?×,Ò,Ù÷"ð "ô ˜#˜y¨$Ó/€KÜ
‡K�KÐDÀkÔbØ×ÑÐ0Ô1Ü)¨#¸;ÔXÐXr   c                 óÒ  € ^ RI Hp  \        P                  ;_uu_ 4        V P                  e,   V P                  P                  4       '       d    RRR4       R# \        P                  ! 4       ;qn        VP                  \        4       \        P                  ! VP                  RRR7      V n        V P                  P                  4        RRR4       R#   + '       g   i     R# ; i)z²Start the background loop thread if not running. The loop/thread handles live on the ORIGIN
module (tests read and reset ``tools.mcp_tool._mcp_loop``), so they are written there.rD   Nzmcp-event-loopT)Útargetr$   Údaemon)rJ   rE   r   rs   rt   ru   rƒ   Únew_event_loopÚset_exception_handlerr]   Ú	threadingÚThreadÚrun_foreverÚ_mcp_threadÚstart)rP   rZ   s     r   Ú_ensure_mcp_looprÎ   ø   sœ   € õ *Ü	��‹Ø×ÑÒ(¨W×->Ñ->×-IÑ-I×-KÒ-KØ÷ 
‰ô $+×#9Ò#9Ó#;Ð;ˆÔ Ø×"Ñ"Ô#>Ô?Ü'×.Ò.°d×6FÑ6FÐM]ÐfjÔkˆÔØ×Ñ×!Ñ!Ô#÷ 
��Šús   Ÿ.CÁCÁA2CÃC&	Úonly_if_idleFc               ó    € V ^8„  d   QhRRRR/# )r   rÏ   r5   r   r   )r   s   "r   r   r     s   € ÷ /ñ / Dð /°Tñ /r   c                óÎ  € ^ RI Hp \        P                  ;_uu_ 4        V '       dM   \        P                  '       g   \        P
                  '       d!   \        P                  R4        RRR4       R# VP                  VP                  r2R;Vn        Vn	        RRR4       Xf   R# RpVP                  4       '       dg   ^ RIHp V! \        P                  ! 4       V\        R\        P                   R7      pVe*    VP#                  \        P$                  ^,           R	7       MLMKVP-                  4       '       g6    VP/                  \        P0                  ! \        P$                  R	7      4       Vf2   VP                  4       '       d   VP3                  VP4                  4       Xe>   VP7                  ^R	7       VP9                  4       '       d   \        P)                  R4        VP;                  4        \        P>                  ! RR7       R#   + '       g   i     EL€; i  \&         d/    \        P)                  R
\        P$                  ^,           4        Lì\*         d"   p\        P)                  RT4        Rp?ELRp?ii ; i  \*         d"   p\        P)                  RT4        Rp?ELARp?ii ; i  \<         d!   p\        P)                  RT4        Rp?LèRp?ii ; i)z3Stop the background event loop and join its thread.rD   zKLeaving MCP event loop running; active servers are registered or connectingNFTr|   z"MCP loop drain: failed to schedule)r~   r   Ú	log_levelr€   z0Timed out waiting for MCP loop drain after %.1fsz!Error draining MCP loop tasks: %sz)Error draining stopped MCP loop tasks: %sz.MCP event loop thread did not stop within 5.0sz*Unable to close MCP event loop cleanly: %s)Úinclude_active) rJ   rE   r   rs   r¥   Ú_server_connectingr~   Údebugrt   rÌ   ru   r‚   r}   Ú
_lifecycleÚ_drain_and_stop_mcp_loopÚloggingÚWARNINGr‹   Ú_MCP_LOOP_DRAIN_TIMEOUTrŠ   ÚwarningÚBaseExceptionÚ	is_closedÚrun_until_completeÚ_drain_mcp_loop_tasksrœ   ÚstopÚjoinÚis_aliver+   r"   Ú_kill_orphaned_mcp_children)rÏ   rP   rZ   Úthreadr‘   r}   r\   s   $      r   Ú_stop_mcp_looprå     s   € å)Ü	��‹ßœUŸ^Ÿ^˜^¬u×/G×/GÐ/GÜ�L‰LÐfÔgØ÷ 
‰ð ×(Ñ(¨'×*=Ñ*=ˆfØ26Ð6ˆÔ˜GÔ/÷ 
ð ‚|Ùð €Fð ‡�×ÒÝ>á)Ü×/Ò/Ó1°4ÄØ<ÌÏÉôYˆð ÒðIØ—‘¤e×&CÑ&CÀaÕ&G�ÕHð ð �^‰^×Òð	MØ×#Ñ#¤J×$DÒ$DÌU×MjÑMjÔ$kÔlð ‚~˜$Ÿ/™/×+Ò+Ø×!Ñ! $§)¡)Ô,ØÒØ�‰˜AˆÔØ�?‰?×ÒÜ�N‰NÐKÔLðJØ�
‰
Œô ×*Ò*¸$Õ?Ù÷Y 
�ˆûô.  ô vÜ—‘ÐQÔSX×SpÑSpÐstÕStÖuÜ ô IÜ—‘ÐBÀC×HÒHûðIûô
 ô 	MÜ�N‰NÐFÈ×LÒLûð	Mûô ô JÜ�‰ÐCÀS×IÑIûðJúsp   ŸH¾HÁHÁ4%HÃ<'H$ Ä<4J
 Ç'J9 ÈH!	È$6JÉJÉ%JÉ&JÊJÊ
J6ÊJ1Ê1J6Ê9K$ËKËK$)é   )%r2   Ú
__future__r   rƒ   Úconcurrent.futuresr�   r    r:   rØ   r#   rÉ   r†   Útypingr   r   r   Útools.mcp_tool_commonr   rJ   r   rÖ   Ú	getLoggerr~   r	   rA   rS   r]   rh   rp   rv   r•   rŸ   r¦   r·   rÃ   rÎ   rå   r   r   r   Ú<module>rì      s·   ðñOõ
 #ã Û Û Û Û Û 	Û Û ß +Ñ +Ý 'Ý 2à	×	Ò	Ð+Ó	,€÷ñ õ.õ(ò:0õò*õ"D÷#'õLõ<ðÀ4ð ÐZ^÷ ð&YÐdh÷ Yò(
$ð/¨5÷ /ñ /r   