+
    kHàjÍI  ã                  ó®  € 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HtHtHt ^ RIHtHt ^ RIHtHtHt ^ RIHtHt ^ RIHtHtHt ^ RIHtH t!H"t" ^ R	I#H$t$  ^ RI%t%^ R
I%H&t& Rt']PR                  ! ]*4      t+Rt,Rt-Rt.Rt/Rt0Rt1R6R R llt2R R lt3R R lt4R R lt5R t6R R lt7 ! R R]4      t8]Pr                  ! R ]Pt                  4      R!3]Pr                  ! R"]Pt                  4      R!3]Pr                  ! R#]Pt                  4      R!3]Pr                  ! R$]Pt                  4      R!3]Pr                  ! R%4      R&3]Pr                  ! R'4      R!3]Pr                  ! R(]Pv                  4      R&3]Pr                  ! R)4      R!3]Pr                  ! R*4      R+33	t<R, R- lt=R.RR/RR0R/R1 lt>]! R24      t?R3t@R4 R5 ltAR#   ]( d    Rt'Rt%Rt& ELci ; i)7u  SMS (Twilio) platform adapter.

Outbound SMS via the Twilio REST API; inbound via an aiohttp webhook server.

Env vars â€” shared with the telephony skill: TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN,
TWILIO_PHONE_NUMBER (E.164 from-number). Gateway-specific: SMS_WEBHOOK_PORT (8080),
SMS_WEBHOOK_HOST (127.0.0.1), SMS_WEBHOOK_URL (public URL for Twilio signature
validation â€” required), SMS_INSECURE_NO_SIGNATURE (true disables validation â€” dev only),
SMS_ALLOWED_USERS (comma-separated E.164), SMS_ALLOW_ALL_USERS, SMS_HOME_CHANNEL (cron).
)ÚannotationsN)ÚAnyÚDictÚOptional)ÚPlatformÚPlatformConfig)Úgateway_trust_envÚBasePlatformAdapterÚ
SendResult)ÚMessageEventÚMessageType)Úredact_phoneÚsend_chunksÚstrip_markdown)Úenv_is_connectedÚget_scoped_secretÚ
send_error)ÚStandaloneSendPolicy)ÚwebTFz*https://api.twilio.com/2010-04-01/Accountsi@  i�  z	127.0.0.1i   z;<?xml version="1.0" encoding="UTF-8"?><Response></Response>c               ó   € V ^8„  d   QhRR/# )é   ÚstatusÚint© )Úformats   "ÚB/home/ubuntu/.hermes/hermes-agent/plugins/platforms/sms/adapter.pyÚ__annotate__r   3   s   € ÷ Zñ Z˜Cñ Zó    c                ó<   € \         P                  ! \        RV R7      # )uJ   Empty TwiML reply â€” replies go out via the REST API, never inline TwiML.zapplication/xml)ÚtextÚcontent_typer   )r   ÚResponseÚ_EMPTY_TWIML)r   s   &r   Ú_twiml_responser#   3   s   € ä�<Š<œ\Ð8IÐRXÔYÐYr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úaccount_sidÚstrÚ
auth_tokenÚreturnr   )r   s   "r   r   r   8   s!   € ÷ ñ ˜Sð ¨cð °cñ r   c                ó~   € \         P                  ! V  RV 2P                  R4      4      P                  R4      pRV 2# )z(HTTP Basic auth header value for Twilio.Ú:ÚasciizBasic )Úbase64Ú	b64encodeÚencodeÚdecode)r%   r'   Úencodeds   && r   Ú_basic_authr1   8   sA   € ä×Ò + ¨a°
¨|Ð<×CÑCÀGÓLÓM×TÑTÐU\Ó]€GØ�G�9ÐÐr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r%   r&   r'   r(   Útupler   )r   s   "r   r   r   >   s&   € ÷ uñ u Cð u°Sð u¸Uñ ur   c                ó4   € \          RV  R2R\        W4      /3# )z2(Messages.json URL, auth headers) for the account.Ú/z/Messages.jsonÚAuthorization)ÚTWILIO_API_BASEr1   )r%   r'   s   &&r   Ú_messages_endpointr8   >   s&   € äÐ˜a ˜}¨NÐ;¸oÌ{Ð[fÓOsÐ=tÐtÐtr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úfrom_numberr&   Ú	to_numberÚbodyr   )r   s   "r   r   r   C   s!   € ÷ ñ ˜cð ¨cð ¸ñ r   c                óœ   € \         P                  ! 4       pVP                  RV 4       VP                  RV4       VP                  RV4       V# )z5Twilio Messages.json form payload (aiohttp FormData).ÚFromÚToÚBody)ÚaiohttpÚFormDataÚ	add_field)r:   r;   r<   Ú	form_datas   &&& r   Ú_twilio_formrE   C   sF   € ä× Ò Ó"€IØ×Ñ˜ Ô,Ø×Ñ˜˜iÔ(Ø×Ñ˜ Ô%ØÐr   c                 ó\   € \         P                  ! RR \         P                  ! ^R7      /V B # )Útimeout)Útotalr   )rA   ÚClientSessionÚClientTimeout)Úkwargss   ,r   Ú_new_sessionrL   L   s&   € Ü× Ò ÑS¬×)>Ò)>ÀRÔ)HÐSÈFÑSÐSr   c               ó   € V ^8„  d   QhRR/# )r   r(   Úboolr   )r   s   "r   r   r   P   s   € ÷ jñ j ñ jr   c                 óŠ   € \         ;'       d7    \        \        R4      ;'       d    \        RR4      P                  4       4      # )z0Check if SMS adapter dependencies are available.ÚTWILIO_ACCOUNT_SIDÚTWILIO_AUTH_TOKENÚ )ÚAIOHTTP_AVAILABLErN   Ú_get_scoped_secretÚstripr   r   r   Úcheck_sms_requirementsrV   P   sC   € ä÷ jð j¤ÜÐ/Ó0×hÐhÔ5GÐH[Ð]_Ó5`×5fÑ5fÓ5hó"jð jr   c                  óÌ   a € ] tR t^Vt$ RtRtR]R&   ]tRt	R V 3R llt
RR/R	 R
 lltR R ltRR R lltR R ltR R ltR R ltR R lt]R R l4       tR R ltRtV ;t# )Ú
SmsAdapterz_Twilio SMS <-> Hermes: one session per inbound number; replies always from TWILIO_PHONE_NUMBER.TrN   Úserves_profile_prefixc               ó   € V ^8„  d   QhRR/# )r   Úconfigr   r   )r   s   "r   r   ÚSmsAdapter.__annotate___   s   € ÷ Cñ C˜~ñ Cr   c                	ó˜  <€ \         SV `  V\        P                  4       \	        R R4      V n        \	        RR4      P                  4       V n        \	        RR4      V n        \        \	        R\        \        4      4      4      V n        \	        R\        4      V n        \	        RR4      P                  4       V n        RV n        RV n        R# )rP   rR   rQ   ÚTWILIO_PHONE_NUMBERÚSMS_WEBHOOK_PORTÚSMS_WEBHOOK_HOSTÚSMS_WEBHOOK_URLN)ÚsuperÚ__init__r   ÚSMSrT   Ú_account_sidrU   Ú_auth_tokenÚ_from_numberr   r&   ÚDEFAULT_WEBHOOK_PORTÚ_webhook_portÚDEFAULT_WEBHOOK_HOSTÚ_webhook_hostÚ_webhook_urlÚ_runnerÚ_http_session)Úselfr[   Ú	__class__s   &&€r   rc   ÚSmsAdapter.__init___   s¦   ø€ Ü‰Ñ˜¤§¡Ô.Ü!3Ð4HÈ"Ó!MˆÔä 2Ð3FÈÓ K× QÑ QÓ SˆÔô "4Ð4IÈ2Ó!NˆÔÜ"%Ô&8Ð9KÌSÔQeÓMfÓ&gÓ"hˆÔÜ"4Ð5GÔI]Ó"^ˆÔÜ!3Ð4EÀrÓ!J×!PÑ!PÓ!RˆÔØˆŒØ>BˆÖr   Úis_reconnectFc               ó    € V ^8„  d   QhRRRR/# )r   rr   rN   r(   r   )r   s   "r   r   r\   o   s   € ÷ &ñ &¨Tð &¸dñ &r   c             ƒ  	óÒ  "  € \        R R4      P                  4       R8H  pRpV P                  '       g   RpMV P                  '       g   V'       g   RpV'       dA   \        P                  V^,          4       V P                  V^ ,          V^,          RR7       R# V'       d3   V P                  '       g!   \        P                  RV P                  4       \        P                  ! \        R7      pVP                  P                  RV P                  4       VP                  P                  R	R
 4       ^ RIHp V! WV P$                  V P                  R4      G Rj  x€L
 V n        \)        \+        4       R7      V n        RV n        V P&                  e@   \        P1                  RV P$                  V P                  \3        V P                  4      4       V P5                  R4       R#  L‰5i)ÚSMS_INSECURE_NO_SIGNATURErR   ÚtrueNF)Ú	retryableu§   [sms] SMS_INSECURE_NO_SIGNATURE=true â€” Twilio signature validation is DISABLED. Any client that can reach port %d can inject messages. Do NOT use this in production.)Úclient_max_sizez/webhooks/twilioz/healthc                ó0   € \         P                  ! R R7      # )Úok)r   )r   r!   )Ú_s   &r   Ú<lambda>Ú$SmsAdapter.connect.<locals>.<lambda>Š   s   € ´·²À$Õ0Gr   )Úbind_listener©Ú	trust_envTz8[sms] Twilio webhook server listening on %s:%d, from: %s)Úsms_missing_phone_numberu9   [sms] TWILIO_PHONE_NUMBER not set â€” cannot send replies)Úsms_missing_webhook_urla+  [sms] Refusing to start: SMS_WEBHOOK_URL is required for Twilio signature validation. Set it to the public URL configured in your Twilio console (e.g. https://example.com/webhooks/twilio). For local development without validation, set SMS_INSECURE_NO_SIGNATURE=true (NOT recommended for production).)rT   Úlowerrg   rl   ÚloggerÚerrorÚ_set_fatal_errorÚwarningri   r   ÚApplicationÚ_TWILIO_WEBHOOK_MAX_BODY_BYTESÚrouterÚadd_postÚ_handle_webhookÚadd_getÚ gateway.platforms.shared_ingressr~   rk   rm   rL   r   rn   Ú_runningÚinfor   Ú_wire_plugin_handlers)ro   rr   Úinsecure_no_sigÚfatalÚappr~   s   &$    r   ÚconnectÚSmsAdapter.connecto   s{  é € Ü,Ð-HÈ"ÓM×SÑSÓUÐY_Ñ_ˆØˆØ× × Ð Øk‰EØ×"×"Ð"¯?ðTˆE÷ Ü�L‰L˜˜q�Ô"Ø×!Ñ! %¨¥(¨E°!­HÀÐ!ÔFÙß 4×#4×#4Ð#4Ü�N‰Nð1ð ×"Ñ"ô	$ô �oŠoÔ.LÔMˆØ�
‰
×ÑÐ.°×0DÑ0DÔEØ�
‰
×Ñ˜9Ñ&GÔHåBÙ*¨4°d×6HÑ6HÈ$×J\ÑJ\Ð^pÓq×qˆŒÜ)Ô4EÓ4GÔHˆÔØˆŒØ�<‰<Ò#Ü�K‰KØJØ×"Ñ" D×$6Ñ$6¼ÀT×EVÑEVÓ8WôYð 	×"Ñ" 4Ô(Ùñ rùs3   ‚AG'Á	G'Á	G'ÁAG'Â#G'Â5B&G'ÅG%ÅB
G'c               ó   € V ^8„  d   QhRR/# ©r   r(   ÚNoner   )r   s   "r   r   r\   —   s   € ÷ *ñ * $ñ *r   c              ƒ  	ó:  "  € V P                   '       d*   V P                   P                  4       G R j  x€L
  R V n         V P                  '       d*   V P                  P                  4       G R j  x€L
  R V n        RV n        \
        P                  R4       R #  Ld L+5i)NFz[sms] Disconnected)rn   Úcloserm   Úcleanupr�   r„   r�   )ro   s   &r   Ú
disconnectÚSmsAdapter.disconnect—   su   é € Ø××ÐØ×$Ñ$×*Ñ*Ó,×,Ð,Ø!%ˆDÔØ�<�<ˆ<Ø—,‘,×&Ñ&Ó(×(Ð(ØˆDŒLØˆŒÜ�‰Ð(Ö)ñ -ñ )ùs'   ‚0B²B³BÁBÁ-BÁ.*BÂBc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   Úchat_idr&   ÚcontentÚreply_tozOptional[str]ÚmetadatazOptional[dict[str, Any]]r(   r
   r   )r   s   "r   r   r\   £   s4   € ÷ &ñ &Øð&Ø%(ð&Ø4Að&ØTlð&à	ñ&r   c              ƒ  	ó$  a aaaa"  € \        S P                  S P                  4      w  ooS P                  ;'       g    \	        \        4       R 7      oR VVV VV3R llp \        S P                  S P                  V4      S P                  4      V4      G Rj  x€L
 S P                  '       g#   S'       d   SP                  4       G Rj  x€L
  # # #  L8 L	  S P                  '       g$   S'       d   SP                  4       G Rj  x€L 
  i i i ; i5i)r   c               ó    € V ^8„  d   QhRRRR/# )r   Úchunkr&   r(   r
   r   )r   s   "r   r   Ú%SmsAdapter.send.<locals>.__annotate__©   s   € ÷ 	?ñ 	? 3ð 	?¨:ñ 	?r   c           	   “  ó  <"  €  SP                  S	\        SP                  SV 4      SR 7      ;_uu_4       GRj  x€L
 pVP                  4       G Rj  x€L
 pVP                  R8¼  dv   VP                  R\        V4      4      p\        P                  R\        S4      VP                  V4       \        RRVP                   RV 2R7      uuRRR4      GRj  x€L
  # \        R	VP                  R
R4      R7      uuRRR4      GRj  x€L
  #  LÑ L» L8 L  + GRj  x€L 
 '       g   i     R# ; i  \         dA   p\        P                  R\        S4      T4       \        R\        T4      R7      u Rp?# Rp?ii ; i5i))ÚdataÚheadersNé�  Úmessagez[sms] send failed to %s: %s %sFzTwilio z: )Úsuccessr…   TÚsidrR   )r­   Ú
message_idz[sms] send error to %s: %s)ÚpostrE   rg   Újsonr   Úgetr&   r„   r…   r   r
   Ú	Exception)
r¦   Úrespr<   Ú	error_msgÚer    rª   ro   ÚsessionÚurls
   &    €€€€€r   Ú	_send_oneÚ"SmsAdapter.send.<locals>._send_one©   s  øé € ð
?Ø"Ÿ<™<¨´,¸t×?PÑ?PÐRYÐ[`Ó2aÐkr˜<×s×sÔsÐw{Ø!%§¡£×,�DØ—{‘{ cÔ)Ø$(§H¡H¨Y¼¸D»	Ó$B˜	ÜŸ™Ð%EÄ|ÐT[ÓG\Ð^b×^iÑ^iÐktÔuÜ)°%ÀÈÏÉÈÐUWÐXaÐWbÐ?cÔd÷ t×sÒsô &¨d¸t¿x¹xÈÈrÓ?RÔS÷ t×sÔsÙ,÷ t×s×sÕsûô ô ?Ü—‘Ð9¼<ÈÓ;PÐRSÔTÜ!¨%´s¸1³vÔ>Õ>ûð?üsÂ   ƒE?…5D1 ºD»D1 ¾DÁDÁA7DÃ
D1 ÃDÃD1 ÃE?ÃDÃ9D1 ÄDÄD1 ÄE?ÄD1 ÄDÄD1 ÄD1 ÄD.	ÄDÄ
D.	Ä&D.	Ä(D1 Ä,E?Ä.D1 Ä1E<Ä<5E7Å1E<Å2E?Å7E<Å<E?N)r8   re   rf   rn   rL   r   r   Útruncate_messageÚformat_messageÚMAX_MESSAGE_LENGTHr›   )	ro   r    r¡   r¢   r£   r¹   rª   r·   r¸   s	   ff&&& @@@r   ÚsendÚSmsAdapter.send£   sÔ   üé € ô *¨$×*;Ñ*;¸T×=MÑ=MÓN‰ˆˆWØ×$Ñ$×SÐS¬Ô?PÓ?RÔ(Sˆ÷	?ô 	?ð	&Ü$ T×%:Ñ%:¸4×;NÑ;NÈwÓ;WÐY]×YpÑYpÓ%qÐs|Ó}×}à×%×%Ð%¯'Ø—m‘m“o×%Ñ%ð +2Ð%ñ ~ñ &øð ×%×%Ð%¯'Ø—m‘m“o×%Ò%ð +2Ð%üsZ   ‡ADÁ!8C ÂCÂC ÂDÂ7DÃ
CÃDÃC ÃDÃDÃ1DÄDÄDÄDc               ó    € V ^8„  d   QhRRRR/# )r   r    r&   r(   zdict[str, Any]r   )r   s   "r   r   r\   ¼   s   € ÷ /ñ /¨3ð /°>ñ /r   c              ƒ  	ó   "  € R VRR/# 5i)ÚnameÚtypeÚdmr   )ro   r    s   &&r   Úget_chat_infoÚSmsAdapter.get_chat_info¼   s   é € Ø˜ ¨Ð.Ð.ùs   ‚	c               ó    € V ^8„  d   QhRRRR/# )r   r¡   r&   r(   r   )r   s   "r   r   r\   ¿   s   € ÷ 'ñ ' cð '¨cñ 'r   c                ó   € \        V4      # ©u8   Strip markdown â€” SMS renders it as literal characters.)r   )ro   r¡   s   &&r   r¼   ÚSmsAdapter.format_message¿   s   € ä˜gÓ&Ð&r   c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r   r¸   r&   Úpost_paramsÚdictÚ	signaturer(   rN   r   )r   s   "r   r   r\   Å   s0   € ÷ 	Xñ 	X¨cð 	XÀð 	XÐQTð 	XÐY]ñ 	Xr   c                ó¢   € V P                  WV4      '       d   R# V P                  V4      p\        T;'       d    V P                  WBV4      4      # )zÔValidate ``X-Twilio-Signature`` (HMAC-SHA1, base64).

Twilio may sign the URL with or without the scheme's default port, so
both variants are tried. https://www.twilio.com/docs/usage/security#validating-requests
T)Ú_check_signatureÚ_port_variant_urlrN   )ro   r¸   rÍ   rÏ   Úvariants   &&&& r   Ú_validate_twilio_signatureÚ%SmsAdapter._validate_twilio_signatureÅ   sJ   € ð × Ñ  °9×=Ò=ÙØ×(Ñ(¨Ó-ˆÜ�G×VÐV × 5Ñ 5°gÈIÓ VÓWÐWr   c               ó(   € V ^8„  d   QhRRRRRRRR/# rÌ   r   )r   s   "r   r   r\   Ð   s.   € ÷ Jñ J Cð J°dð JÀsð JÈtñ Jr   c                	ó  a€ V P                   '       g   R # VRP                  V3R l\        SP                  4       4       4       4      ,           p\        P
                  ! V P                   P                  R4      VP                  R4      \        P                  4      p\        P                  ! VP                  4       4      P                  R4      p\        P                  ! VP                  4       VP                  4       4      # )FrR   c              3  óB   <"  € T F  qSV,          ,           x € K  	  R # 5i)Nr   )Ú.0ÚkeyrÍ   s   & €r   Ú	<genexpr>Ú.SmsAdapter._check_signature.<locals>.<genexpr>Ó   s   øé € Ð$bÑGaÀ¨;°sÕ+;×%;Ò%;ÓGaùs   ƒúutf-8)rf   ÚjoinÚsortedÚkeysÚhmacÚnewr.   ÚhashlibÚsha1r,   r-   Údigestr/   Úcompare_digest)ro   r¸   rÍ   rÏ   Údata_to_signÚmacÚcomputeds   &&f&   r   rÑ   ÚSmsAdapter._check_signatureÐ   s´   ø€ Ø××ÐÙØ˜RŸW™WÔ$bÄvÈk×N^ÑN^ÓN`ÔGaÓ$bÓbÕbˆÜ�hŠh�t×'Ñ'×.Ñ.¨wÓ7¸×9LÑ9LÈWÓ9UÔW^×WcÑWcÓdˆÜ×#Ò# C§J¡J£LÓ1×8Ñ8¸ÓAˆô ×"Ò" 8§?¡?Ó#4°i×6FÑ6FÓ6HÓIÐIr   c               ó    € V ^8„  d   QhRRRR/# )r   r¸   r&   r(   z
str | Noner   )r   s   "r   r   r\   Û   s   € ÷ `ñ `˜sð ` zñ `r   c                ó¶  € \         P                  P                  V 4      pRRR^P/P                  VP                  4      pVf   R# VP
                  V8X  d   VP                  pM"VP
                  f   VP                   RV 2pMR# \         P                  P                  VP                  W1P                  VP                  VP                  VP                  34      # )zXURL with the scheme's default port toggled (added/stripped); None for non-default ports.Úhttpsi»  ÚhttpNr*   )ÚurllibÚparseÚurlparser²   ÚschemeÚportÚhostnameÚ
urlunparseÚpathÚparamsÚqueryÚfragment)r¸   ÚparsedÚdefault_portÚnetlocs   &   r   rÒ   ÚSmsAdapter._port_variant_urlÚ   s°   € ô —‘×&Ñ& sÓ+ˆØ  f¨bÐ1×5Ñ5°f·m±mÓDˆØÒÙØ�;‰;˜,Ô&Ø—_‘_‰FØ�[‰[Ò ØŸ™Ð(¨¨,¨Ð8‰FáÜ�|‰|×&Ñ&Ø�]‰]˜F§K¡K°·±ÀÇÁÈfÏoÉoÐ^ó`ð 	`r   c               ó    € V ^8„  d   QhRRRR/# )r   Úrequestzweb.Requestr(   zweb.Responser   )r   s   "r   r   r\   ì   s   € ÷ '!ñ '!¨[ð '!¸\ñ '!r   c           	   ƒ  	óŒ  a"  €  VP                   pVe   V\        8”  d   \        R4      # VP                  4       G R j  x€L
 p\	        V4      \        8”  d   \        R4      # \
        P                  P                  VP                  R4      RR7      oT P                  '       dª   TP                  P                  RR4      pSP                  4        UUu/ uF  w  rgT'       g   K  Yg^ ,          bK  	  pppT'       g   R	M%T P!                  T P                  Y…4      '       d   RMR
p	T	'       d"   \        P#                  RT	4       \        R4      # T3R lR 4       w  r«rÍT
'       d	   T'       g   \        4       # Y P$                  8X  d*   \        P'                  R\)        T
4      4       \        4       # \        P+                  R\)        T
4      \)        T4      TR,          4       T P-                  YªRYªTR7      p\/        T\0        P2                  TSTR7      p\4        P6                  ! T P9                  T4      4      pT P:                  P=                  T4       TP?                  T P:                  P@                  4       \        4       #  ELD  \         d,   p\        P                  RT4       \        R4      u R p?# R p?ii ; iu uppi 5i)Ni�  rÝ   T)Úkeep_blank_valuesz[sms] webhook parse error: %sr«   zX-Twilio-SignaturerR   z!missing X-Twilio-Signature headerzinvalid Twilio signaturez[sms] Rejected: %si“  c              3  ót   <"  € T F-  pSP                  VR .4      ^ ,          P                  4       x € K/  	  R# 5i)rR   N)r²   rU   )rÙ   rÚ   Úforms   & €r   rÛ   Ú-SmsAdapter._handle_webhook.<locals>.<genexpr>  s4   øé € ð 5\Ù6Z¨sˆD�H‰H�S˜2˜$Ó Õ"×(Ñ(×*Ð*Ó6Zùs   ƒ58z&[sms] ignoring echo from own number %sz[sms] inbound from %s -> %s: %s:NéP   NrÄ   )r    Ú	chat_nameÚ	chat_typeÚuser_idÚ	user_namer¯   )r   Úmessage_typeÚsourceÚraw_messager¯   )r>   r?   r@   Ú
MessageSid)!Úcontent_lengthr‰   r#   ÚreadÚlenrï   rð   Úparse_qsr/   r³   r„   r…   rl   rª   r²   ÚitemsrÔ   r‡   rg   Údebugr   r�   Úbuild_sourcer   r   ÚTEXTÚasyncioÚcreate_taskÚhandle_messageÚ_background_tasksÚaddÚadd_done_callbackÚdiscard)ro   rÿ   r  Úrawr¶   Ú
twilio_sigÚkÚvÚflat_paramsÚrejectedr:   r;   r   Úmessage_sidr  ÚeventÚtaskr  s   &&               @r   rŒ   ÚSmsAdapter._handle_webhookì   sK  øé € ð	(Ø$×3Ñ3ˆNØÒ)¨nÔ?]Ô.]Ü& sÓ+Ð+ØŸ™›×&ˆCÜ�3‹xÔ8Ô8Ü& sÓ+Ð+ä—<‘<×(Ñ(¨¯©°GÓ)<ÐPTÐ(ÓUˆDð ××ÐØ Ÿ™×,Ñ,Ð-AÀ2ÓFˆJØ/3¯z©z¬|ÔA©|¡t q¼qœ7˜1 �dš7©|ˆKÑAßCMÑ;Ø#'×#BÑ#BÀ4×CTÑCTÐVa×#nÒ#n™RØ7ð ÷ Ü—‘Ð3°XÔ>Ü& sÓ+Ð+ô5\Ù6Zó5\Ñ1ˆ ç§$Ü"Ó$Ð$Ø×+Ñ+Ô+Ü�L‰LÐAÄ<ÐP[ÓC\Ô]Ü"Ó$Ð$Ü�‰Ð5´|ÀKÓ7PÔR^Ð_hÓRiÐkoÐpsÕktÔuØ×"Ñ"ØÀ$ÐP[Ø"ð #ó $ˆô Ø¤K×$4Ñ$4¸VÐQUÐbmôoˆô ×"Ò" 4×#6Ñ#6°uÓ#=Ó>ˆØ×Ñ×"Ñ" 4Ô(Ø×Ñ˜t×5Ñ5×=Ñ=Ô>ÜÓ Ð òE 'øô
 ô 	(Ü�L‰LÐ8¸!Ô<Ü" 3Ó'Õ'ûð	(üó
 Bùs   ƒK…%J ªK«J ¾J¿"J Á!KÁ"0J ÂKÂ$/KÃJ>Ã$J>Ã1:KÄ,?KÅ,DKÊJ ÊJ;Ê J6Ê0J;Ê1KÊ6J;Ê;	K)	re   rf   rg   rn   rm   r�   rk   ri   rl   )NN)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rY   Ú__annotations__ÚMAX_SMS_LENGTHr½   Úsplits_long_messagesrc   r•   r�   r¾   rÅ   r¼   rÔ   rÑ   ÚstaticmethodrÒ   rŒ   Ú__static_attributes__Ú__classcell__)rp   s   @r   rX   rX   V   sv   ø‡ Ùià"&Ð˜4Ó&à'ÐàÐ÷Cð Cð &°E÷ &õP*÷&õ2/õ'õ	XõJð ô`ó ð`÷"'!ó '!r   rX   z\*\*(.+?)\*\*z\1z	\*(.+?)\*z	__(.+?)__z_(.+?)_z```[a-z]*\n?rR   z`(.+?)`z
^#{1,6}\s+z\[([^\]]+)\]\([^\)]+\)z\n{3,}z

c               ó    € V ^8„  d   QhRRRR/# )r   r¬   r&   r(   r   )r   s   "r   r   r   )  s   € ÷ ñ  Sð ¨Sñ r   c                ób   € \          F  w  rVP                  W 4      p K  	  V P                  4       # rÉ   )Ú_SMS_MARKDOWN_SUBSÚsubrU   )r¬   ÚpatternÚrepls   &  r   Ú_strip_markdown_for_smsr8  )  s(   € ç+‰ˆØ—+‘+˜dÓ,Šñ ,à�=‰=‹?Ðr   Ú	thread_idÚmedia_filesÚforce_documentc             ƒ  ó´  "  € \        \        V RR4      ;'       g    \        RR4      ;'       g    R4      P                  4       p\        '       g   \        R4      # \        RR4      p\        RR4      pV'       d   V'       d	   V'       g   \        R4      # \        V4      p ^ R	IHp	H	p
 V
! V	! 4       4      w  r¼\        Wv4      w  rÞ\        R/ VB ;_uu_4       GRj  x€L
 p\        W�V4      pVP                  ! V3R
VRV/VB ;_uu_4       GRj  x€L
 pVP                  4       G Rj  x€L
 pVP                  R8¼  d[   VP!                  R\        V4      4      p\        RVP                   RV 24      uuRRR4      GRj  x€L
  uuRRR4      GRj  x€L
  # RRRRRVRVP!                  RR4      /uuRRR4      GRj  x€L
  uuRRR4      GRj  x€L
  #  Lù LÇ L± L[ LK L! L  + GRj  x€L 
 '       g   i     M; iRRR4      GRj  x€L 
  R#   + GRj  x€L 
 '       g   i     R# ; i  \"         d   p\        RT 24      u Rp?# Rp?ii ; i5i)zTOut-of-process SMS delivery via the Twilio REST API (standalone_sender_fn contract).Úapi_keyNrQ   rR   z/aiohttp not installed. Run: pip install aiohttprP   r^   zXSMS not configured (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER required))Úresolve_proxy_urlÚproxy_kwargs_for_aiohttpr©   rª   r«   r¬   zTwilio API error (z): r­   TÚplatformÚsmsr    r¯   r®   zSMS send failed: r   )r&   ÚgetattrrT   rU   rS   r   r8  Úgateway.platforms.baser>  r?  r8   rL   rE   r°   r±   r   r²   r³   )Úpconfigr    r¬   r9  r:  r;  r'   r%   r:   r>  r?  Ú_sess_kwÚ_req_kwr¸   rª   r·   rD   r´   r<   rµ   r¶   s   &&&$$$               r   Ú_standalone_sendrG  0  sè  é € ä”W˜W i°Ó6×kÐkÔ:LÐM`ÐbdÓ:e×kÐkÐikÓl×rÑrÓt€JßÓÜÐKÓLÐLÜ$Ð%9¸2Ó>€KÜ$Ð%:¸BÓ?€KßŸj·ÜÐtÓuÐuÜ% gÓ.€Gð3ßVÙ4Ñ5FÓ5HÓIÑˆÜ)¨+ÓB‰ˆÜÑ+ (×+×+Ò+¨wÜ$ [¸7ÓCˆIØ—|’| CÑT¨iÐTÀÐTÈG×T×TÒTÐX\Ø!ŸY™Y›[×(�Ø—;‘; #Ô%Ø $§¡¨´C¸³IÓ >�IÜ%Ð(:¸4¿;¹;¸-ÀsÈ9È+Ð&VÓW÷	 U×TÑT÷ ,×+Ò+ð " 4¨°U¸IÀwÐP\Ð^b×^fÑ^fÐglÐnpÓ^qÐr÷ U×TÑT÷ ,×+Ô+áTÙ(ñ Uñ ,áTñ ,çT×T×TÐTú÷ ,×+×+×+×+Ô+ûô ô 3ÜÐ-¨a¨SÐ1Ó2Õ2ûð3üs[  ‚-I° IÁ2IÂIÂIÂ#;H2 ÃGÃH2 Ã"0HÄGÄHÄG&	Ä*GÄ+A
G&	Å5HÆG
ÆHÆH2 ÆG ÆH2 ÆIÆG&	Æ3HÇ G"
ÇHÇH2 ÇG$ÇH2 ÇIÇH2 ÇHÇG&	ÇHÇ H2 Ç"HÇ$H2 Ç&G?Ç,G/Ç-
G?Ç8G?Ç:HÈH2 ÈHÈH2 ÈIÈH/	ÈHÈ
H/	È'H/	È)H2 È-IÈ/H2 È2IÈ=IÉ
IÉIÉIÉIrP   u³   You are communicating via SMS. Keep responses concise and use plain text only â€” no markdown, no formatting. SMS messages are limited to ~1600 characters, so be brief and direct.c               ó   € V ^8„  d   QhRR/# r˜   r   )r   s   "r   r   r   T  s   € ÷ ñ �Tñ r   c           	     ó>  € ^RI Hp V P                  ! R#/ R\        RR7      bRRbRRbR	\        bR
RbRRbRR$bRR$bR\
        bR\        bR. R%ObRRbRRbR\        bR\        bRRbRRbRRbR\        bRRbR VP                  bR!VP                  bVP                  B  R"# )&u:   Plugin entry point â€” called by the Hermes plugin system.)Úgateway_envÚstandalone_sendT)Útext_directrÂ   rA  ÚlabelzSMS (Twilio)Úadapter_factoryÚdashboard_descriptionz*Send and receive text messages via Twilio.Údocs_urlzhttps://www.twilio.com/consoleÚdashboard_env_varsÚdashboard_required_envÚcheck_fnÚis_connectedÚrequired_envÚinstall_hintzpip install aiohttpÚcron_deliver_env_varÚSMS_HOME_CHANNELÚstandalone_sender_fnÚmax_message_lengthÚpii_safeÚemojiu   ðŸ“±Úallow_update_commandÚplatform_hintÚdisplay_tierÚminimalÚenv_overridesÚenv_enable_credentialsNr   )rP   rQ   )rP   rQ   r^   )rR   rJ  Úregister_platformr   rX   rV   Ú_is_connectedrG  r-  Ú_PLATFORM_HINTÚENV_OVERRIDESÚENV_ENABLE_CREDENTIALSÚAUTHZ)ÚctxrJ  s   & r   Úregisterrj  T  s  € åØ×Òò Ü,¸Õ>ðáðá(ðå:Dðñ Kðñ 2ð	ñ
 Gðñ  Kðõ (ðõ 7Dðó Xðñ +ðñ BTðõ .ðõ CQðñ \`ðñ ðñ ,0ðõ %ðñ ðð "×/Ò/ðð  +×AÒAÀ[×EVÑEVôr   )éÈ   )Br+  Ú
__future__r   r  r,   rã   rá   ÚloggingÚreÚurllib.parserï   Útypingr   r   r   Úgateway.configr   r   rC  r   r	   r
   Úgateway.platforms.eventr   r   Úgateway.platforms.helpersr   r   r   Úgateway.platforms._sharedr   Ú_env_is_connectedr   rT   r   Úgateway.platforms.send_targetsr   rA   r   rS   ÚImportErrorÚ	getLoggerr'  r„   r7   r-  rh   rj   r‰   r"   r#   r1   r8   rE   rL   rV   rX   ÚcompileÚDOTALLÚ	MULTILINEr4  r8  rG  rd  re  rj  r   r   r   Ú<module>r|     sç  ðñ	õ #ã Û Û Û Û Û 	Û ß &Ñ &ç 3ß UÑ Uß =ß OÑ O÷ñ õ @ðÛÝØÐð 
×	Ò	˜8Ó	$€à>€Ø€ØÐ Ø"Ð Ø!'Ð ØL€÷Zõ
õuõ
òTõjô}!Ð$ô }!ðJ ‡Z‚ZÐ  "§)¡)Ó,¨eÐ4°r·z²zÀ,ÐPR×PYÑPYÓ7ZÐ\aÐ6bØ‡Z‚Z�˜bŸi™iÓ(¨%Ð0°2·:²:¸jÈ"Ï)É)Ó3TÐV[Ð2\Ø‡Z‚Z�Ó  "Ð%¨¯
ª
°:Ó(>ÀÐ'FØ‡Z‚Z�˜rŸ|™|Ó,¨bÐ1°B·J²JÐ?XÓ4YÐ[`Ð3aØ‡Z‚Z�	Ó˜FÐ#ð%Ð õð3À4ð 3ÐUYð 3Ðjoô 3ñ4 "Ð"6Ó7€ð
Xð ÷øða	 ô ØÐØ€GØ
ƒCðús   Á$G ÇGÇG