Ë
    ãß²j�U  ã                  ó  — d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
 ddlmZmZ  ej                  e«      Zdd	d
ddœZdZ eh d£«      Z G d„ de«      Zd[d„Zd„ Zd„ Zd\d„Zd]d^d„Zd_d„Zd`d„Z ed«      dad„«       Z ed«      dad„«       Z ed«      dad„«       Z  ed «      dad!„«       Z! ed"«      dad#„«       Z"d$„ Z#d%d&d'dd(d)d*œidgd+œd,œed-fd.d/d'd(d)d*œd(g d0¢d1d2œd(d3d*œd4d5d*œd6œdd7gd+œd,œed8fd9d:d'd(d;d*œd(d<d*œd(d=d*œd(d>d*œd?d@d'd(dAd*œd4dBd*œdCœdDgd+œdEœdFœg d+œd,œe"dGfdHdId'd(dJd*œdKdLd*œdMœg d+œd,œe dNfdOdPd'd(dQd*œd(dRd*œd(dSd*œdTœg d+œd,œe!dUffZ$e$D ]"  \  Z%Z&Z' ejP                  e%d   dVe%e&e#dWe'¬X«       Œ$ ddYl	m)Z) ddZl	m*Z* y)bu´  yuanbao_tools.py - å…ƒå®�å¹³å�°å·¥å…·é›† (the "hermes-yuanbao" toolset).

get_group_info / query_group_members / search_sticker / send_sticker / send_dm. Sticker
flow mirrors chatbot-web's sticker-search/sticker-send: the LLM should search_sticker for
a sticker_id (or pass the Chinese name), then send_sticker â€” never bare Unicode emoji.
The active adapter singleton lives in ``gateway.platforms.yuanbao.YuanbaoAdapter.get_active``.
é    )ÚannotationsN)Úsuppress)ÚPath)ÚTuple)ÚregistryÚtool_resultÚunknownÚuserÚ
yuanbao_aiÚbot)r   é   é   é   z\To @mention a user, you MUST use the format: space + @ + nickname + space (e.g. " @Alice ").>   ú.bmpú.gifú.jpgú.pngú.jpegú.webpc                  ó$   ‡ — e Zd ZdZdˆ fd„Zˆ xZS )Ú_YbErrorzLTool-level failure; ``payload`` is the error envelope returned to the model.c                ó<   •— t         ‰| �  |«       d|dœ|¥| _        y )NF)ÚsuccessÚerror)ÚsuperÚ__init__Úpayload)ÚselfÚmsgÚextraÚ	__class__s      €ú8/home/ubuntu/.hermes/hermes-agent/tools/yuanbao_tools.pyr   z_YbError.__init__#   s!   ø€ Ü‰Ñ˜ÔØ#(°3Ñ@¸%Ð@ˆ�ó    )r   Ústr)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__classcell__)r!   s   @r"   r   r       s   ø„ ÙV÷Añ Ar#   r   c                ó   ‡ — ˆ fd„}|S )ue   Handler decorator: ``fn(args)`` â†’ tool_result; ``_YbError`` â†’ its envelope; else logged envelope.c                óF   •‡ — t        j                  ‰ «      ˆ ˆfd„«       }|S )Nc              ›  ó6  •K  — 	 t         ‰| «      ƒ d {  –—† «      S 7 Œ# t        $ r}t        |j                  «      cY d }~S d }~wt        $ rG}t        j                  d‰«       t        t        t        |«      «      j                  «      cY d }~S d }~ww xY w­w)Nz[yuanbao_tools] %s error)r   r   r   Ú	ExceptionÚloggerÚ	exceptionr$   )ÚargsÚkwÚexcÚfnÚlabels      €€r"   Úhandlerz'_yb_tool.<locals>.deco.<locals>.handler+   sq   øè ø€ ð?Ü"©¨D«§>Ó2Ð2 >ùÜò 0Ü" 3§;¡;Ó/Õ/ûÜò ?Ü× Ñ Ð!;¸UÔCÜ"¤8¬C°«HÓ#5×#=Ñ#=Ó>Õ>ûð?üsR   ƒB…  •–  �Bž   	B©A½B¾BÁBÁ<BÂBÂBÂBÂB)Ú	functoolsÚwraps)r3   r5   r4   s   ` €r"   Údecoz_yb_tool.<locals>.deco*   s%   ù€ Ü	�‰˜Ó	ô	?ó 
ð	?ð ˆr#   © )r4   r8   s   ` r"   Ú_yb_toolr:   (   s   ø€ ô
ð €Kr#   c                 óx   — t        t        «      5  ddlm}  | j	                  «       cddd«       S # 1 sw Y   yxY w)zOLazy import to avoid ImportError when gateway.platforms.yuanbao is unavailable.r   ©ÚYuanbaoAdapterN)r   ÚImportErrorÚgateway.platforms.yuanbaor=   Ú
get_activer<   s    r"   Ú_get_active_adapterrA   8   s3   € ä	”+Ó	ñ +Ý<Ø×(Ñ(Ó*÷+÷ +ñ +ð ús   �0°9c                 ó4   — t        «       x} €t        d«      ‚| S )Nz Yuanbao adapter is not connected)rA   r   )Úadapters    r"   Ú_adapterrD   @   s!   € Ü&Ó(Ð(ˆÐ1ÜÐ9Ó:Ð:Ø€Nr#   Únamec                ój   — t        t        «      5  ddlm}  || d«      cd d d «       S # 1 sw Y   yxY w)Nr   )Úget_session_envÚ )r   r-   Úgateway.session_contextrG   )rE   rG   s     r"   Ú_session_envrJ   F   s1   € Ü	”)Ó	ñ )Ý;Ù˜t RÓ(÷)÷ )ñ )ð ús   �)©2c                óF   — | j                  d| j                  d|«      «      S )NÚnicknameÚ	nick_name)Úget)ÚmÚdefaults     r"   Ú_nickrQ   M   s   € Ø�5‰5�˜QŸU™U ;°Ó8Ó9Ð9r#   Ú
group_codec              ƒ  ó~   K  — | j                  |«      ƒ d {  –—† }|€t        d«      ‚|j                  dg «      S 7 Œ#­w)Nz#get_group_member_list returned NoneÚmembers)Úget_group_member_listr   rN   )rC   rR   Úraws      r"   Ú_membersrW   Q   s@   è ø€ Ø×-Ñ-¨jÓ9×
9€CØ
€{ÜÐ<Ó=Ð=Ø�7‰7�9˜bÓ!Ð!ð :ús   ‚=—;˜$=c           
   ƒ  óD  K  — |st        d«      ‚|st        d«      ‚|j                  «       j                  «       }t        | |«      ƒ d{  –—† D �cg c]<  }||j	                  d«      xs |j	                  d«      xs dj                  «       v r|‘Œ> }}|st        d|› d|› d	�«      ‚t        |«      d
kD  r;t        d|› d�|D �cg c]   }|j	                  dd«      t        |«      dœ‘Œ" c}¬«      ‚|d   }|j	                  dd«      t        ||«      fS 7 ŒÉc c}w c c}w ­w)zšResolve ``name`` to (user_id, nickname) via the group member list; >1 partial match raises
    with ``candidates`` for disambiguation instead of guessing.z3group_code is required when user_id is not providedz-name is required when user_id is not providedNrL   rM   rH   zNo member matching "z" found in group ú.r   zMultiple members match "z". Please specify which one.Úuser_id©rZ   rL   )Ú
candidatesr   )r   ÚstripÚlowerrW   rN   ÚlenrQ   )rC   rR   rE   ÚfiltrO   Úmatcheds         r"   Ú_resolve_dm_recipientrb   X   s1  è ø€ ñ ÜÐLÓMÐMÙÜÐFÓGÐGØ�:‰:‹<×ÑÓ€DÜ (¨°*Ó =×=ö S�QØ˜1Ÿ5™5 Ó,ÒH°·±°kÓ0BÒHÀb×OÑOÓQÑQò ð S€Gð SáÜÐ-¨d¨VÐ3DÀZÀLÐPQÐRÓSÐSÜ
ˆ7ƒ|�aÒÜØ& t fÐ,HÐIØY`ÖaÐTU A§E¡E¨)°RÓ$8ÄeÈAÃhÓOÒaô
ð 	
ð 	�‰
€AØ�5‰5�˜BÓ¤ q¨$£Ð/Ð/ð >úò Sùò bùs1   ‚AD Á
DÁD ÁADÂ2D Ã%D
Ã),D Ä
D Úget_group_infoc           	   ƒ  ó@  K  — | j                  dd«      }|st        d«      ‚t        «       j                  |«      ƒ d{  –—† }|€t        d«      ‚d||j                  dd«      |j                  dd	«      |j                  d
d«      |j                  dd«      dœddœS 7 Œ]­w)u9   æŸ¥è¯¢ç¾¤åŸºæœ¬ä¿¡æ�¯ï¼ˆç¾¤å��ã€�ç¾¤ä¸»ã€�æˆ�å‘˜æ•°ï¼‰ã€‚rR   rH   úgroup_code is requiredNzquery_group_info returned NoneTÚ
group_nameÚmember_countr   Úowner_idÚowner_nicknamer[   u+   The group is called "æ´¾ (Pai)" in the app.)r   rR   rf   rg   ÚownerÚnote)rN   r   rD   Úquery_group_info)r0   rR   Úgis      r"   rc   rc   m   s    è ø€ ð —‘˜,¨Ó+€JÙÜÐ/Ó0Ð0Ü‹z×*Ñ*¨:Ó6×	6€BØ	€zÜÐ7Ó8Ð8à zÀÇÁÈÐVXÓAYØŸ™˜~¨qÓ1ØŸV™V J°Ó3ÀÇÁÐHXÐZ\ÓA]Ñ^Ø=ñ	ð ð 
7ús   ‚<B¾B¿ABÚquery_group_membersc              ƒ  óž  ‡
K  — | j                  dd«      | j                  dd«      }}| j                  dd«      }|st        d«      ‚t        t        «       |«      ƒ d{  –—† D �cg c]U  }|j                  dd«      t	        |«      t
        j                  |j                  d	|j                  d
d«      «      d«      dœ‘ŒW }}|st        d«      ‚| j                  dd«      rdt        ini Š
d ˆ
fd„}|dk(  r;|D �cg c]  }|d
   dv sŒ|‘Œ }}|st        d«      ‚ |ddt        |«      › d�|«      S |dk(  ro|rm|j                  «       j                  «       }|D �cg c]  }||d   j                  «       v sŒ|‘Œ }	}|	r |ddt        |	«      › d|› d�|	«      S  |dd|› d�|«      S  |ddt        |«      › d�|«      S 7 �Œ]c c}w c c}w c c}w ­w)!u§   ç»Ÿä¸€çš„ç¾¤æˆ�å‘˜æŸ¥è¯¢ï¼ˆå¯¹é½� TS query_session_membersï¼‰ã€‚
    action: find (æŒ‰æ˜µç§°æ¨¡ç³Šæ�œç´¢; æ—  name æ—¶ç­‰å�Œ list_all) / list_bots / list_all (é»˜è®¤).rR   rH   rE   ÚactionÚlist_allre   NrZ   Ú	user_typeÚroler   r	   )rZ   rL   rs   zNo members found in this group.ÚmentionFÚmention_hintc                ó   •— | ||dœ‰¥S )N)r   r   rT   r9   )Úokr   rT   Úhints      €r"   Ú_listingz%query_group_members.<locals>._listing�   s   ø€ Ø c°gÑFÀÐFÐFr#   Ú	list_bots>   r   r   zNo bots found in this group.TzFound z bot(s).ÚfindrL   z member(s) matching "z".zNo match for "z". All members listed below.z member(s).)rw   Úboolr   r$   rT   ÚlistÚreturnÚdict)
rN   r   rW   rD   rQ   Ú_USER_TYPE_LABELÚMENTION_HINTr_   r]   r^   )r0   rR   rE   rp   rO   Úall_membersry   Úbotsr`   ra   rx   s             @r"   rn   rn   ~   sð  øè ø€ ð —x‘x ¨bÓ1°4·8±8¸FÀBÓ3G�€JØ�X‰X�h 
Ó+€FÙÜÐ/Ó0Ð0ô  ¤£
¨JÓ7×7öð ð —E‘E˜) RÓ(´e¸A³hÜ!×%Ñ% a§e¡e¨K¸¿¹¸vÀqÓ9IÓ&JÈIÓVó	Xð€Kð ñ
 ÜÐ8Ó9Ð9à-1¯X©X°iÀÔ-GˆNœLÑ)ÈR€DõGð �ÒØ&ÖM�a¨!¨F©)Ð7LÒ*L’ÐMˆÐMÙÜÐ9Ó:Ð:Ù˜ ¤s¨4£y k°Ð:¸DÓAÐAà�Ò™DØ�z‰z‹|×!Ñ!Ó#ˆØ)ÖK˜¨T°Q°z±]×5HÑ5HÓ5JÒ-J’1ÐKˆÐKÙÙ˜D F¬3¨w«<¨.Ð8MÈdÈVÐSUÐ"VÐX_Ó`Ð`Ù˜ °¨vÐ5QÐRÐT_Ó`Ð`á�D˜F¤3 {Ó#3Ð"4°KÐ@À+ÓNÐNð/ 8ûòùò Nùò LùsK   ƒAGÁF;ÁGÁ%AF>Â?:GÃ9GÄGÄ
AGÅGÅ4GÅ8AGÆ>GÚsearch_stickerc              ƒ  óŒ  K  — ddl m} | j                  dd«      | j                  dd«      }}	 t        dt	        d|rt        |«      nd«      «      } ||xs d|¬	«      }d
|xs dt        |«      |D ��cg c]#  }dD �ci c]  }||j                  |d«      “Œ c}‘Œ% c}}dœS # t        t        f$ r d}Y Œdw xY wc c}w c c}}w ­w)ue   åœ¨å†…ç½®è´´çº¸è¡¨ä¸­æŒ‰å…³é”®è¯�æ¨¡ç³Šæ�œç´¢ï¼Œè¿”å›ž Top-N å€™é€‰ï¼ˆç©º query è¿”å›žå‰� N æ�¡ï¼‰ã€‚r   )Úsearch_stickersÚqueryrH   Úlimité
   r   é2   )rˆ   T)Ú
sticker_idrE   ÚdescriptionÚ
package_id)r   r‡   ÚcountÚresults)	Ú!gateway.platforms.yuanbao_stickerr†   rN   ÚmaxÚminÚintÚ	TypeErrorÚ
ValueErrorr_   )r0   r†   r‡   rˆ   Ú
safe_limitÚmatchesÚsÚks           r"   r„   r„   £   sË   è ø€ õ Bà—8‘8˜G RÓ(¨$¯(©(°7¸BÓ*?ˆ5€EðÜ˜œC ±%¤C¨¤J¸RÓ@ÓAˆ
ñ ˜ešk r°Ô<€Gà %¢+¨2¼¸G»à$÷&Øð /bÖb¨�Q˜Ÿ™˜a ›‘_Ôbó &ñð øô ”zÐ"ò ØŠ
ðüò
 cùó &ùsL   ‚+C®#B" Á#CÁ4	B>Á=B9ÂB>ÂCÂ"B6Â3CÂ5B6Â6CÂ9B>Â>CÚsend_stickerc              ƒ  óª  K  — ddl m}m}m} | j	                  dd«      xs dj                  «       xs t        d«      }|st        d«      ‚t        «       }| j	                  dd«      xs dj                  «       }|s |«       }n$|j                  «       r ||«      ndxs  ||«      }|€t        d	|›d
�«      ‚|j                  ||j	                  dd«      | j	                  dd«      xs d¬«      ƒ d{  –—† }t        |dd«      st        t        |dd«      «      ‚d||j	                  dd«      |j	                  dd«      dœt        |dd«      ddœS 7 Œ]­w)u$  å�‘ chat_idï¼ˆç¼ºçœ�å�–å½“å‰�ä¼šè¯� HERMES_SESSION_CHAT_IDï¼‰å�‘é€�ä¸€å¼ å†…ç½®è´´çº¸ï¼ˆTIMFaceElemï¼‰ã€‚
    ``sticker``: å��ç§°ï¼ˆå¦‚ "å…­å…­å…­"ï¼‰æˆ– sticker_idï¼ˆå¦‚ "278"ï¼‰ï¼›ä¸ºç©ºæ—¶éš�æœºå�‘é€�ã€‚
    ``chat_id``: ``direct:{account_id}`` / ``group:{group_code}`` / è£¸ account_idã€‚r   )Úget_sticker_by_idÚget_sticker_by_nameÚget_random_stickerÚchat_idrH   ÚHERMES_SESSION_CHAT_IDz8chat_id is required (no active yuanbao session detected)ÚstickerNzSticker not found: z:. Use search_sticker first to discover available stickers.rE   Úreply_to)rŸ   Ústicker_namer¢   r   Fr   zsend_sticker failedTr‹   )r‹   rE   Ú
message_idz~Sticker delivered to the chat. If you have additional text to say, reply now; otherwise end your turn without generating text.)r   rŸ   r¡   r¤   rk   )r�   rœ   r�   rž   rN   r]   rJ   r   rD   Úisdigitrš   Úgetattr)	r0   rœ   r�   rž   ÚtargetrC   rV   Ústicker_objÚresults	            r"   rš   rš   µ   s\  è ø€ ÷
 mÑlà�h‰h�y "Ó%Ò+¨×2Ñ2Ó4Ò^¼ÐE]Ó8^€FÙÜÐQÓRÐRÜ‹j€Gà�8‰8�I˜rÓ"Ò( b×
/Ñ
/Ó
1€CÙÙ(Ó*‰à14·±´Ñ(¨Ô-ÀDÒeÑM`ÐadÓMeˆØÐÜÐ,¨S¨GÐ3mÐnÓoÐoà×'Ñ'°À[Ç_Á_ÐU[Ð]_ÓE`Ø15·±¸*ÀbÓ1IÒ1QÈTð (ó S÷ S€Fä�6˜9 eÔ,Ü”w˜v wÐ0EÓFÓGÐGà FØ"-§/¡/°,ÀÓ"CÈ[Ï_É_Ð]cÐegÓMhÑiÜ˜f l°DÓ9ð Qñ	ð ð	Sús   ‚C1EÃ3EÃ4AEÚsend_dmc           
   ƒ  ó`  K  — | j                  dd«      }|s1t        d«      x}j                  d«      r|j                  dd«      d   }g }| j                  d«      xs g D ]   }t	        |t
        «      r=|j                  |j                  dd«      t        |j                  d	d
«      «      f«       ŒPt	        |t        t        f«      sŒgt        |«      dk\  sŒv|j                  t        |d   «      t        |d   «      f«       Œ¢ ddlm} |j                  | j                  dd«      «      \  }}|j                  |t        |xs g «      z   «      }|s|st!        d«      ‚t#        «       }| j                  dd«      }	| j                  dd«      xs dj%                  «       |	j%                  «       }}
|
st'        |||	«      ƒ d{  –—† \  }
}|
st!        d«      ‚d|
› �}d}g }|rW|j%                  «       rG|j)                  |
||¬«      ƒ d{  –—† }|j*                  s|j                  |j,                  xs d«       |D ]…  \  }}t/        |«      j0                  j3                  «       t4        v r|j6                  n|j8                  } ||||¬«      ƒ d{  –—† }|j*                  rŒg|j                  |j,                  xs d«       Œ‡ |€t!        d«      ‚|r&|j*                  st!        dj;                  |«      «      ‚d|› d�}|r|ddj;                  |«      › d�z  }d|
||j<                  |dœS 7 �Œh7 �Œ$7 ŒŸ­w) a®  Send a DM to a group member, with optional media. group_code defaults to the session's
    "group:<code>" chat_id. Without ``user_id`` the member list is searched by ``name`` (partial,
    case-insensitive; >1 match returns candidates). media_files items are {"path", "is_voice"} dicts or
    (path, is_voice) pairs; ``MEDIA:<path>`` tags in the text count too. Partial media failures are
    reported in ``note``, not as failure.rR   rH   r    zgroup:ú:r   Úmedia_filesÚpathÚis_voiceFr   r   )ÚBasePlatformAdapterÚmessagez"message or media_files is requiredrE   rZ   NzCould not resolve user_idzdirect:)rR   ztext send failedzmedia send failedz%No deliverable text or media remainedz; zDM sent to "z" successfully.z (partial failure: ú)T)r   rZ   rL   r¤   rk   )rN   rJ   Ú
startswithÚsplitÚ
isinstancer   Úappendr|   r}   Útupler_   r$   Úgateway.platforms.baser°   Úextract_mediaÚfilter_media_delivery_pathsr   rD   r]   rb   rª   r   r   r   Úsuffixr^   Ú_IMAGE_EXTSÚsend_image_fileÚsend_documentÚjoinr¤   )r0   rR   rŸ   r­   Úitemr°   Úembedded_mediar±   rC   rE   Úresolved_user_idÚresolved_nicknameÚlast_resultÚerrorsÚ
media_pathÚ	_is_voiceÚsendrk   s                     r"   rª   rª   Õ   s  è ø€ ð —‘˜,¨Ó+€JÙ¤lÐ3KÓ&LÐL˜7×XÑXÐYaÔbØ—]‘] 3¨Ó*¨1Ñ-ˆ
à€KØ—‘˜Ó'Ò-¨2ò >ˆÜ�dœDÔ!Ø×Ñ §¡¨°Ó 4´d¸4¿8¹8ÀJÐPUÓ;VÓ6WÐXÕYÜ˜œt¤U˜mÕ,´°T³¸a³Ø×Ñ¤ D¨¡G£¬d°4¸±7«mÐ<Õ=ð	>õ ;Ø1×?Ñ?ÀÇÁÈÐTVÓ@WÓXÑ€N�GØ%×AÑAÀ+ÔPTÐUcÒUiÐgiÓPjÑBjÓk€Ká™;ÜÐ;Ó<Ð<Ü‹j€Gà�8‰8�F˜BÓ€DØ+/¯8©8°I¸rÓ+BÒ+HÀb×*OÑ*OÓ*QÐSW×S]ÑS]ÓS_Ð'ÐÙÜ4IÈ'ÐS]Ð_cÓ4d×.dÑ+ÐÐ+ÙÜÐ2Ó3Ð3àÐ(Ð)Ð*€GØ€KØ€FÙ�7—=‘=”?Ø#ŸO™OÐ,<¸gÐR\˜OÓ]×]ˆØ×"Ò"Ø�M‰M˜+×+Ñ+ÒAÐ/AÔBà!,ò DÑˆ
�IÜ*.¨zÓ*:×*AÑ*A×*GÑ*GÓ*IÌ[Ñ*Xˆw×&Ò&Ð^e×^sÑ^sˆÙ  ¨*ÀÔL×LˆØ×"Ó"Ø�M‰M˜+×+Ñ+ÒBÐ/BÕCð	Dð ÐÜÐ>Ó?Ð?Ù�k×)Ò)Ü�t—y‘y Ó(Ó)Ð)àÐ+Ð,¨OÐ<€DÙØÐ% d§i¡i°Ó&7Ð%8¸Ð:Ñ:ˆØÐ(8ÐFWØ%×0Ñ0¸$ñ@ð @ð5 /eùð ^ùð MúsL   ‚CL.ÃL.ÃC)L.Æ>L&Æ?AL.ÈL)ÈBL.ÊL,ÊL.ÊB	L.Ì)L.Ì,L.c                 ó:   — t        d«      dk(  xs t        «       duS )uN   Toolset availability check â€” True when running in a yuanbao gateway session.ÚHERMES_SESSION_PLATFORMÚyuanbaoN)rJ   rA   r9   r#   r"   Ú_check_yuanbaorÌ     s"   € äÐ1Ó2°iÑ?ÒdÔCVÓCXÐ`dÐCdÐdr#   Úyb_query_group_infoul   Query basic info about a group (called 'æ´¾/Pai' in the app), including group name, owner, and member count.ÚobjectÚstringz)The unique group identifier (group_code).)ÚtyperŒ   )rÐ   Ú
propertiesÚrequired)rE   rŒ   Ú
parametersu   ðŸ‘¥Úyb_query_group_membersu:  Query members of a group (called 'æ´¾/Pai' in the app). Use this tool when you need to @mention someone, find a user by name, list bots (including Yuanbao AI), or list all members. IMPORTANT: You MUST call this tool before @mentioning any user, because you need the exact nickname to construct the @mention format.)r{   rz   rq   u¤   find â€” search a user by name (use when you need to @mention or look up someone); list_bots â€” list bots and Yuanbao AI assistants; list_all â€” list all members.)rÐ   ÚenumrŒ   z€User name to search (partial match, case-insensitive). Required for 'find'. Use the name the user mentioned in the conversation.Úbooleanz{Set to true when you need to @mention/at someone in your reply. The response will include the exact @mention format to use.)rR   rp   rE   rt   rp   u   ðŸ“‹Ú
yb_send_dmu`  Send a private/direct message (DM) to a user in a group, with optional media files. This tool automatically looks up the user by name in the group member list and sends the message. Use this when someone asks to privately message / ç§�ä¿¡ / DM a user. Supports text, images, and file attachments. You can also provide user_id directly if already known.uˆ   The group where the target user belongs. Extract from chat_id: 'group:328306697' â†’ '328306697'. Required when user_id is not provided.zdTarget user's display name (partial match, case-insensitive). Required when user_id is not provided.zEThe message text to send as a DM. Can be empty if only sending media.z}Target user's account ID. If provided, skips the member lookup. Usually obtained from a previous yb_query_group_members call.Úarrayz¤Optional list of media files to send along with the DM. Images (.jpg/.png/.gif/.webp/.bmp) are sent as image messages; other files are sent as document attachments.z.Absolute local file path of the media to send.z5Whether this file is a voice message (default false).)r®   r¯   r®   )rÐ   rŒ   Úitems)rR   rE   r±   rZ   r­   u   âœ‰ï¸�Úyb_search_stickerui  Search the built-in Yuanbao sticker (TIM face / è¡¨æƒ…åŒ…) catalogue by keyword. Returns the top matching candidates with sticker_id, name, and description. Use this BEFORE yb_send_sticker to discover the right sticker_id. Sticker = è´´çº¸ = TIM face â€” NOT a message reaction. Prefer sending a sticker over bare Unicode emoji when reacting/expressing emotion.uw   Search keyword (Chinese or English, e.g. '666', 'æ¯”å¿ƒ', 'cool', 'å�ƒç“œ'). Empty string returns the first N stickers.Úintegerz8Max number of candidates to return (default 10, max 50).)r‡   rˆ   u   ðŸ”�Úyb_send_stickeruµ  Send a built-in sticker (TIMFaceElem / è´´çº¸è¡¨æƒ…) to the current Yuanbao chat. Call yb_search_sticker first if you don't know the sticker_id/name. Sticker = è´´çº¸ = TIM face â€” NOT a message reaction. CRITICAL: Whenever the user asks you to send a sticker / è´´çº¸ / è¡¨æƒ…åŒ…, you MUST use this tool. DO NOT draw a PNG via execute_code / Pillow / matplotlib and then call send_image_file â€” that produces a fake 'sticker' image instead of a real TIM face and is the WRONG path. If no suitable sticker_id is known, call yb_search_sticker first. When the recent thread shows users sending stickers, prefer matching that tone by replying with a sticker instead of (or in addition to) text.u�   Sticker name (e.g. 'å…­å…­å…­', 'æ¯”å¿ƒ', 'ok') or numeric sticker_id (e.g. '278'). Empty string sends a random built-in sticker.zvTarget chat. Defaults to the current session. Format: 'direct:{account_id}', 'group:{group_code}', or bare account_id.z5Optional ref_msg_id to quote-reply (group chat only).)r¡   rŸ   r¢   u   ðŸŽ¨zhermes-yuanbaoT)rE   ÚtoolsetÚschemar5   Úcheck_fnÚis_asyncÚemoji)ÚList)ÚOptional)r4   r$   )rE   r$   r~   r$   )rH   )rO   r   rP   r$   r~   r$   )rR   r$   r~   r}   )rR   r$   rE   r$   r~   zTuple[str, str])r~   r   )+r(   Ú
__future__r   r6   ÚloggingÚ
contextlibr   Úpathlibr   Útypingr   Útools.registryr   r   Ú	getLoggerr%   r.   r€   r�   Ú	frozensetr¼   r-   r   r:   rA   rD   rJ   rQ   rW   rb   rc   rn   r„   rš   rª   rÌ   Ú_TOOLSÚ_schemaÚ_handlerÚ_emojiÚregisterrâ   rã   r9   r#   r"   ú<module>rñ      s�  ðñõ #ã Û Ý Ý Ý ç 0à	ˆ×	Ñ	˜8Ó	$€à  V°ÀÑGÐ ð6ð ñ ÒJÓK€ôAˆyô Aóò òóô:ó"ó0ñ* 
Ð
Óòó ðñ  
Ð
Ó ò!Oó !ð!OñH 
Ð
Óòó ðñ" 
ˆ.Óòó ðñ> 
ˆ)Óò7@ó ð7@òteð *ðAð !à Ø (Ø'Rñ#ðð *˜Nñ	ñ	
ð" 	Øð'ð. -ðXð !ð !)Ø'Rñ#ð
 !)Ú Að=ñ	ð !)ðhñð !*ðZñ ñ+ð: *¨8Ð4ñ? ñ*	
ðV 	Øð[.ðb !ðJð !ð !)ðEñ#ð !)ðEñð !)Ø'nñ ð
 !)ð\ñ ð !(ðLð
 %-ð -5Ø3cñ)"ð
 -6Ø3jñ-"ñ	+ð *0¨ñ"ñ$ñ71ðd ñi5ñ?	
ð@ 	ØðECðL (ðeð !ð !)ðIñð !*Ø'aññð ññ	
ð6 	Øð;ðB &ð	%ð !ð !)ðZñ ð !)ðgñ ð !)Ø'^ñ!ñð( ñ-ñ&	
ðN 	ØðS*ðQS
€ðj "(ò Ñ€GˆX�vØ€H×ÑØ�V‰_Ð&6¸wÐPXØ¨$°föðõ Þ r#   