+
    kHàj¢ƒ ã                  óB  a € 0 t $ 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t^ RIt^ RIt^ RIHt ^ RIHtHtHtHtHtHt ^ RIHt ^ RIHt ^ RIHt ^ RIH t!H"t#H$t$ ^R	I%H&t&H't( R
 R lt)Rs*R]+R&   R;t,;t-;t.;t/;t0;t1t2]3t4R]+R&   Rs5R]+R&   Ryt6Rt7Rs8R]+R&   ]Pr                  ! 4       t: ! R R4      t;R R lt<R R lt=R R lt>^ RI?H@t@HAtA ]@! R4       ^ RIBHCtC ^ RIDHEtEHFtFHGtGHHtHHItIHJtJHKtK ^ R ILHMtMHNtNHOtO ]	P                   ! R!4      tQ]P¤                  ! R"4      tSR#R$.tTR%tU^tVRzw  tWtXtYtZ][! 0 R{m4      t\R|t]R&t^R}t_]P¤                  ! R'4      R(3]P¤                  ! R)4      R*3]P¤                  ! R+4      R,33t`R-]NPÂ                  3R.]NPÄ                  3R/]NPÆ                  33tdR-]JR03R.]HR13R/]KR233teR3 R4 ltfR5 R6 ltgR7 R8 lthR9 R: ltiR; R< ltjR= R> ltkR? R@ ltl ! RA RB]34      tmRC RD ltn ! RE RF4      toRGRHRIRJRKRLRMRNRORPRQRR/tpRS RT ltqRU RV ltr ! RW RX]F4      tsRY RZ lttR[ R\ ltuR] R^ ltvR_ R` ltwRa Rb ltxR~tyRc Rd ltzRet{Rf Rg lt|]P¤                  ! Rh4      t}]P¤                  ! Ri4      t~RGRjRIRkRKRlRMRmRORnRQRo/tRp Rq lt€RrRRsRRtR/Ru Rv llt�Rw Rx lt‚R# )a«  Google Chat platform adapter.

Inbound: authenticated HTTP callbacks or a Cloud Pub/Sub pull subscription. Outbound:
Chat REST API (synchronous googleapiclient via ``asyncio.to_thread``). The Pub/Sub
callback runs on a background thread, so ``handle_message`` is scheduled thread-safely
onto the loop and never awaited there. Only MESSAGE events reach the agent; membership
events cache the bot id, card clicks are ACK'd only.
)ÚannotationsN)ÚPath)ÚAnyÚCallableÚDictÚListÚOptionalÚTuple)Úurlparse)Út)Úis_multiplex_active)Úget_scoped_secretÚseed_extra_from_envÚ
send_error)Úcard_spec_to_cards_v2Úformat_messagec               ó   € V ^8„  d   QhRR/# ©é   ÚreturnÚbool© )Úformats   "ÚJ/home/ubuntu/.hermes/hermes-agent/plugins/platforms/google_chat/adapter.pyÚ__annotate__r   $   s   € ÷ ñ ¨tñ ó    c                 óÄ   € \        4       ;'       dP    \        \        P                  P	                  R4      ;'       g     \        P                  P	                  R4      4      # )z“True when ADC would read another profile's SA from the process env under
multiplexing (``google.auth.default()`` consults ``os.environ`` directly).Ú GOOGLE_CHAT_SERVICE_ACCOUNT_JSONÚGOOGLE_APPLICATION_CREDENTIALS)r   r   ÚosÚenvironÚgetr   r   r   Ú%_adc_would_borrow_foreign_credentialsr"   $   sG   € ô Ó ÷ ð ¤TÜ
�
‰
�‰Ð9Ó:×nÐn¼b¿j¹j¿n¹nÐMmÓ>nó&ð r   Fr   ÚGOOGLE_CHAT_AVAILABLEr   Ú	HttpErrorÚ_google_modules_loadedi,  Ú_google_id_token_requestc                  ó<   € ] tR t^?tRt]3R R lltRR R lltRtR# )	Ú_CachedGoogleAuthRequestzJCaches successful GET responses (Google cert fetches) for ``ttl_seconds``.c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úrequestr   Úttl_secondsÚintr   ÚNoner   )r   s   "r   r   Ú%_CachedGoogleAuthRequest.__annotate__B   s'   € ÷ Cñ C ð C°#ð CÐ_cñ Cr   c                	ód   € W\         P                  ! 4       uV n        V n        V n        / V n        R # ©N)Ú	threadingÚLockÚ_requestÚ_ttl_secondsÚ_lockÚ_cache)Úselfr*   r+   s   &&&r   Ú__init__Ú!_CachedGoogleAuthRequest.__init__B   s%   € Ø7>ÌYÏ^Ê^ÓM]Ð4ˆŒ�tÔ(¨$¬*Ø@BˆŽr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   ÚurlÚstrÚmethodÚkwargsr   r   r   )r   s   "r   r   r.   F   s(   € ÷ ñ ˜Cð ¨ð Àð Èñ r   c                	ó|  € VP                  4       V3pV^ ,          R8w  d   V P                  ! RRVRV/VB # \        P                  ! 4       pV P                  ;_uu_ 4        V P
                  P                  V4      pV'       d"   V^ ,          V8”  d   V^,          uuRRR4       # RRR4       V P                  ! RRVRV/VB p\        VRR4      ^È8X  dA   V P                  ;_uu_ 4        WPP                  ,           V3V P
                  V&   RRR4       V# V#   + '       g   i     Lz; i  + '       g   i     T# ; i)é    ÚGETr;   r=   NÚstatusr   )	Úupperr3   ÚtimeÚ	monotonicr5   r6   r!   Úgetattrr4   )r7   r;   r=   r>   Ú	cache_keyÚnowÚcachedÚresponses   &&&,    r   Ú__call__Ú!_CachedGoogleAuthRequest.__call__F   sô   € Ø—\‘\“^ SÐ)ˆ	Ø�Q�<˜5Ô Ø—=’=ÑB SÐB°ÐB¸6ÑBÐBÜ�nŠnÓˆØ�Z�Z‹ZØ—[‘[—_‘_ YÓ/ˆFß˜& �) cœ/Ø˜a•y÷ �ZŠZð —=’=ÑB SÐB°ÐB¸6ÑBˆÜ�8˜X tÓ,°Ô3Ø——“Ø*-×0AÑ0AÕ*AÀ8Ð)L�—‘˜IÑ&÷ àˆˆxˆ÷ �Zú÷ –àˆús   Á :DÃ)"D*ÄD'	Ä*D;	)r6   r5   r3   r4   N)rA   )	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú"_GOOGLE_ID_TOKEN_CERTS_TTL_SECONDSr8   rK   Ú__static_attributes__r   r   r   r(   r(   ?   s   † ÙTà8Z÷ C÷ó r   r(   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r   V   s   € ÷ 	(ñ 	( cñ 	(r   c                 óö   € \         ;_uu_ 4        \        f!    ^ RIHp  \        T P                  4       4      s\        uuR R R 4       #   \         d   p\        R4      ThR p?ii ; i  + '       g   i     R # ; i)N)Úrequestsú6google-auth is required for Google Chat HTTP callbacks)Ú_google_id_token_request_lockr&   Úgoogle.auth.transportrW   ÚImportErrorÚRuntimeErrorr(   ÚRequest)Úgoogle_requestsÚexcs     r   Ú_get_google_id_token_requestr`   V   sh   € ç	&Ö	&Ü#Ò+ðfÝMô (@À×@WÑ@WÓ@YÓ'ZÐ$Ü'÷ 
'Ò	&øô ô fÜ"Ð#[Ó\ÐbeÐeûðfú÷	 
'×	&Ð	&ús-   �	A'™AŸA'ÁA$ÁAÁA$Á$A'Á'A8	c               ó$   € V ^8„  d   QhRRRRRR/# )r   Útokenr<   Úaudiencer   údict[str, Any]r   )r   s   "r   r   r   b   s&   € ÷ Yñ Y 3ð Y°#ð Y¸.ñ Yr   c                ó„   €  ^ RI Hp TP	                  T \        4       T4      #   \         d   p\        R4      ThRp?ii ; i)r@   )Úid_tokenrX   N)Úgoogle.oauth2rf   r[   r\   Úverify_oauth2_tokenr`   )rb   rc   rf   r_   s   &&  r   Ú_verify_google_id_tokenri   b   sI   € ð^Ý*ð ×'Ñ'¨Ô/KÓ/MÈxÓXÐXøô ô ^ÜÐSÓTÐZ]Ð]ûð^ús   ‚# £?®:º?c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   j   s   € ÷ ñ ˜dñ r   c                 óL  € \         '       d   \        # Rs  \         U UUu/ uFD  w  rpY'       d!   \        \        P
                  ! V4      V4      M\        P
                  ! V4      bKF  	  ppp p\        4       P                  T4       RsR# u uppp i   \         d    Rs R# i ; i)zOLazily import the google stack (idempotent); True when the optional deps exist.TF)	r%   r#   Ú_GOOGLE_IMPORTSrF   Ú	importlibÚimport_moduler[   ÚglobalsÚupdate)ÚnameÚmoduleÚattrÚloadeds       r   Ú_load_google_modulesru   j   s£   € ÷ ÓÜ$Ð$Ø!Ððõ '6õ
á&5Ñ"�˜dð ÆD”'œ)×1Ò1°&Ó9¸4Ô@Ìi×NeÒNeÐflÓNmÒmÙ&5ð 	ò 
ô ƒI×Ñ�VÔØ ÐÙùô
øô ô Ø %ÐÚðús#   –
B  A
BÁ*B ÂB ÂB#Â"B#)ÚPlatformÚPlatformConfigÚgoogle_chat)ÚMessageDeduplicator)Úgateway_trust_envÚBasePlatformAdapterÚ
SendResultÚcache_audio_from_bytes_asyncÚcache_document_from_bytes_asyncÚcache_image_from_bytes_asyncÚcache_video_from_bytes_async)ÚMessageEventÚMessageTypeÚProcessingOutcomezgateway.platforms.google_chatz:^projects/(?P<project>[^/]+)/subscriptions/(?P<sub>[^/]+)$z(https://www.googleapis.com/auth/chat.botz&https://www.googleapis.com/auth/pubsubé   z
<consumed>z&projects/[^/\s]+/subscriptions/[^/\s]+z,projects/<redacted>/subscriptions/<redacted>zprojects/[^/\s]+/topics/[^/\s]+z%projects/<redacted>/topics/<redacted>z9[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.iam\.gserviceaccount\.comz&<sa>@<project>.iam.gserviceaccount.comzimage/zaudio/zvideo/z.jpgz.oggz.mp4c               ó    € V ^8„  d   QhRRRR/# )r   r_   ÚBaseExceptionr   r   r   )r   s   "r   r   r   ¬   s   € ÷ ?ñ ?�mð ?¨ñ ?r   c                ó2   € \        \        V RR4      RR4      # )z8``resp.status`` of a googleapiclient HttpError, or None.ÚrespNrB   )rF   ©r_   s   &r   Ú_http_statusrŠ   ¬   s   € ä”7˜3 ¨Ó-¨x¸Ó>Ð>r   c               ó    € V ^8„  d   QhRRRR/# )r   r_   r†   r   r   r   )r   s   "r   r   r   ±   s   € ÷ 	ñ 	˜]ð 	¨tñ 	r   c                ó¬  a€ \        V 4      p\        V\        4      '       d
   V\        9   # \	        V 4      P                  4       o\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       gH    RS9   ;'       d;    \        ;QJ d    V3R lR 4       F  '       g   K   R# 	  R# ! V3R lR 4       4      # )zQTrue for transient failures (429, 5xx, transport errors); auth/4xx are permanent.c              3  ó,   <"  € T F	  qS9   x € K  	  R # 5ir0   r   )Ú.0ÚpÚtexts   & €r   Ú	<genexpr>Ú&_is_retryable_error.<locals>.<genexpr>¸   s   øé € Ð;Ñ":˜Q�DŽyÓ":ùó   ƒTFÚ
connectionc              3  ó,   <"  € T F	  qS9   x € K  	  R # 5ir0   r   )rŽ   Úwr�   s   & €r   r‘   r’   ¹   s   øé € Ð$XÑ8W°1¨$¦YÓ8Wùr“   )ÚresetÚrefusedÚaborted)rŠ   Ú
isinstancer,   Ú_RETRYABLE_HTTP_STATUSESr<   ÚlowerÚanyÚ_TRANSPORT_ERROR_PHRASES)r_   rB   r�   s   & @r   Ú_is_retryable_errorrŸ   ±   s    ø€ ä˜#Ó€FÜ�&œ#×ÒØÔ1Ñ1Ð1äˆs‹8�>‰>Ó€Dß‹3Ô;Õ":Ó;�3�3Š3Ô;Õ":Ó;Ó;÷ ð Ø˜Ñ×XÐX§£Ô$XÑ8WÓ$X§¤ðÚ!$ðØ!$Ô$XÑ8WÓ$XÓ!Xðr   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   ½   s   € ÷ "ñ "¨ñ "r   c                 ó   € \        4       # )zdPASSIVE deps probe; must never install. Registry ``check_fn`` uses this via ``_check_for_registry``.)ru   r   r   r   Úcheck_google_chat_requirementsr¢   ½   s   € äÓ!Ð!r   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   Â   s   € ÷ "ñ " ñ "r   c                 óÜ   € \         '       d   R# ^ RIHp Hp . pR F  p V! V4       K  	  V'       d
   V^ ,          hRs\        4       #   T  d   pTP	                  T4        Rp?KK  Rp?ii ; i)a  ACTIVE installer (registry ``ensure_deps_fn``).

PM owns the install; a refusal (lazy installs off, unsupported platform,
network) propagates so the registry logs the reason. Resets the failed-import
cache so ``create_adapter()`` can load modules after install.
T)ÚInstallErrorÚensure_importNF)Úgooglezgoogle-chat)r#   Úpmr¥   r¦   Úappendr%   ru   )r¥   r¦   ÚfailuresÚextrar_   s        r   Úensure_google_chat_depsr¬   Â   sm   € ÷ ÓÙß.ð $&€HÛ*ˆð	!Ù˜%Ö ñ +÷
 Ø�q�kÐØ"ÐÜÓ!Ð!øð ô 	!Ø�O‰O˜C× Ò ûð	!ús   ŸAÁA+ÁA&Á&A+c               ó    € V ^8„  d   QhRRRR/# )r   r;   r<   r   r   r   )r   s   "r   r   r   Ü   s   € ÷ 	Wñ 	W˜sð 	W tñ 	Wr   c                óB  a€  \        V 4      pTP                  ;'       g    RP                  4       oTP                  R8w  g	   S'       g   R# \
        ;QJ d#    T3R l\         4       F  '       g   K   R# 	  R# ! T3R l\         4       4      #   \         d     R# i ; i)zAReturn True iff *url* is https and targets a Google-owned domain.FÚ Úhttpsc              3  ón   <"  € T F*  pSV8H  ;'       g    SP                  R V,           4      x € K,  	  R# 5i)Ú.N)Úendswith)rŽ   ÚhÚhosts   & €r   r‘   Ú(_is_google_owned_host.<locals>.<genexpr>å   s/   øé € ÐVÑ<U°qˆt�q‰y×2Ð2˜DŸM™M¨#°­'Ó2Ô2Ó<Uùs   ƒ5”!5T)r
   Ú	ExceptionÚhostnamerœ   Úschemer�   Ú_TRUSTED_ATTACHMENT_HOSTS)r;   Úparsedrµ   s   & @r   Ú_is_google_owned_hostr¼   Ü   s}   ø€ ðÜ˜#“ˆð �O‰O×!Ð!˜r×(Ñ(Ó*€DØ‡}�}˜Ô§tÙß‹3ÔVÕ<UÓV�3Œ3ÐVŠ3ÐVˆ3ÔVÕ<UÓVÓVÐVøô ô Úðús   ƒB ÂBÂB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                óZ   € V '       g   V # \          F  w  rVP                  W 4      p K  	  V # )zKRedact Pub/Sub resource paths and SA emails from user-facing error strings.)Ú_REDACTIONSÚsub)r�   ÚpatternÚrepls   &  r   Ú_redact_sensitiverÃ   è   s)   € çØˆß$‰ˆØ�{‰{˜4Ó&Šñ %à€Kr   c               ó    € V ^8„  d   QhRRRR/# )r   Úmimer<   r   r‚   r   )r   s   "r   r   r   ñ   s   € ÷  ñ   ð  ¨ñ  r   c                óŠ   € \          F*  w  rV '       g   K  V P                  V4      '       g   K(  Vu # 	  \        P                  # )zHMap a MIME string to a MessageType; non-media falls through to DOCUMENT.)Ú_MIME_MESSAGE_TYPESÚ
startswithr‚   ÚDOCUMENT)rÅ   ÚprefixÚmessage_types   &  r   Ú_mime_for_message_typerÌ   ñ   s6   € ç 3Ñˆß‰4�D—O‘O F×+Ô+ØÒñ !4ô ×ÑÐr   c                  ó6   a € ] tR t^ùtRtRR V 3R llltRtV ;t# )Ú_SACredentialErrorzLInternal: classified SA-credential load failure (``kind`` + optional cause).c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úkindr<   ÚdetailzOptional[BaseException]r   r-   r   )r   s   "r   r   Ú_SACredentialError.__annotate__ü   s"   € ÷ .ñ .˜Sð .Ð*Að .ÈTñ .r   c                	óB   <€ \         SV `  V4       WuV n        V n        R # r0   )Úsuperr8   rÐ   rÑ   )r7   rÐ   rÑ   Ú	__class__s   &&&€r   r8   Ú_SACredentialError.__init__ü   s   ø€ Ü‰Ñ˜ÔØ!%ÐˆŒ	�4–;r   )rÑ   rÐ   r0   )rM   rN   rO   rP   rQ   r8   rS   Ú__classcell__©rÕ   s   @r   rÎ   rÎ   ù   s   ø† ÙV÷.÷ .ð .r   rÎ   c               ó    € V ^8„  d   QhRRRR/# )r   Úsa_valueúOptional[str]r   r   r   )r   s   "r   r   r     s   € ÷ ñ ¨ð ¸#ñ r   c                ó^  € V '       dÉ   V P                  4       P                  R4      '       d    \        P                  ! V 4      pMf\        P                  P                  V 4      '       g   \        R4      h \        V RRR7      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        P                  P                  X\        R	7      # \        4       '       d   \        R
4      h ^ RIHp  TP'                  \        R	7      w  rVT#   \        P                   d   p\        RT4      ThRp?ii ; i  + '       g   i     Lœ; i  \        P                   d   p\        RT4      ThRp?ii ; i  \$         d    \        R4      hi ; i  \(         d   p\        RT4      ThRp?ii ; i)zÀBuild SA credentials from a path / inline JSON, or fall back to ADC.
Raises ``_SACredentialError`` with kind in {inline_invalid, not_found,
file_invalid, adc_foreign, adc_no_auth, adc_failed}.Ú{Úinline_invalidNÚ	not_foundÚrú	utf-8-sig©ÚencodingÚfile_invalid)ÚscopesÚadc_foreignÚadc_no_authÚ
adc_failed)ÚlstriprÈ   ÚjsonÚloadsÚJSONDecodeErrorrÎ   r   ÚpathÚexistsÚopenÚloadÚservice_accountÚCredentialsÚfrom_service_account_infoÚ_CHAT_SCOPESr"   Úgoogle.authÚauthr[   Údefaultr·   )rÚ   Úinfor_   ÚfhÚgoogle_authÚcredentialsÚ_projects   &      r   Ú_load_sa_credentials_fromrý     sn  € ÷ Ø�?‰?Ó×'Ñ'¨×,Ò,ðIÜ—z’z (Ó+‘ô —‘—‘ ×)Ò)Ü$ [Ó1Ð1ðGÜ˜( C°+×>Õ>À"ÜŸ9š9 R›=�D÷ ?ô ×*Ñ*×DÑDÀTÔR^ÐDÓ_Ð_ä,×.Ò.Ü  Ó/Ð/ð0Ý)ð=Ø +× 3Ñ 3¼<Ð 3Ó HÑˆð Ðøô- ×'Ñ'ô IÜ(Ð)9¸3Ó?ÀSÐHûðIú÷ ?×>ûä×'Ñ'ô GÜ(¨¸Ó=À3ÐFûðGûô ô 0Ü  Ó/Ð/ð0ûô ô =Ü  ¨sÓ3¸Ð<ûð=úsq   ¯D Á7E ÂD8Â$E Ã-E5 Ã4F ÄD5Ä#D0Ä0D5Ä8E	ÅE ÅE ÅE2Å E-Å-E2Å5FÆF,ÆF'Æ'F,c                  ób   € ] tR tRtRtR R ltR R ltR R ltR	 R
 ltR R lt	R R lt
RtR# )Ú_ThreadCountStorei"  aŠ  Persisted per-(chat_id, thread_name) inbound counter driving the DM main-flow vs
side-thread heuristic (0: Chat auto-created the thread for a top-level message; >=1:
user engaged an existing thread). Persisted because a restart that wiped counts would
demote active side-threads to main flow and leak context. Format
``{"<chat_id>": {"<thread_name>": <int>}}``; missing/corrupt resets to empty.c               ó   € V ^8„  d   QhRR/# )r   rí   Ú_Pathr   )r   s   "r   r   Ú_ThreadCountStore.__annotate__)  s   € ÷ 5ñ 5˜Uñ 5r   c                	ó    € Wn         / V n        R # r0   )Ú_pathÚ_counts)r7   rí   s   &&r   r8   Ú_ThreadCountStore.__init__)  s   € ØŒ
Ø24ˆŽr   c               ó   € V ^8„  d   QhRR/# ©r   r   r-   r   )r   s   "r   r   r  -  s   € ÷ 2ñ 2�dñ 2r   c           	     óX  € / V n         V P                  P                  4       '       g   R#  V P                  P                  RR7      pVP	                  4       '       d   \
        P                  ! V4      M/ p\        T\        4      '       d   TP                  4       MR F   w  rV\        T\        4      '       g   K  \        T\        4      '       g   K5  TP                  4        UUu/ uF7  w  rx\        T\        4      '       g   K  \        T\         4      '       g   K5  YxbK9  	  p	ppT	'       g   K’  Y�P                   T&   K¢  	  R#   \
        P                  \        3 dF   p\        T\        4      '       d   RMRp\        P                  Y@P                  T4        Rp?R# Rp?ii ; iu uppi )uM   Load counts from disk; missing file â†’ empty, corrupt JSON â†’ empty + warn.Nrá   râ   zD[GoogleChat] thread-count store at %s is corrupt; starting fresh: %sz8[GoogleChat] could not read thread-count store at %s: %sr   )r  r  rî   Ú	read_textÚstriprê   rë   rì   ÚOSErrorrš   Ú
ValueErrorÚloggerÚwarningÚdictÚitemsr<   r,   )
r7   ÚrawÚdatar_   ÚfmtÚchat_idÚthreadsr   ÚcÚcleans
   &         r   rð   Ú_ThreadCountStore.load-  s-  € àˆŒØ�z‰z× Ñ ×"Ò"Ùð	Ø—*‘*×&Ñ&°Ð&Ó<ˆCØ&)§i¡i§k¢k”4—:’:˜c”?°rˆDô 2<¸DÄ$×1GÒ1G §¡¤ÈRÒ!OÑˆGÜ˜'¤3×'Ô'¬J°wÄ×,EÔ,EØ*1¯-©-¬/Ôg©/¡$ !¼ZÈÌ3×=OœÔT^Ð_`Ôbe×Tfœ˜š©/�Ñgß‘5Ø,1—L‘L Ó)ó	 "Pøô ×$Ñ$¤gÐ.ô 	Ü]gÐhkÔmw×]xÒ]xÑYØRð ä�N‰N˜3§
¡
¨CÔ0Ýûð		üó hs/   «1E ÁE Ã%F&ÄF&ÄF&ÅF#Å:FÆF#c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r  r<   Úthread_namer   r,   r   )r   s   "r   r   r  A  s&   € ÷ Añ A˜3ð A¨Sð A°Sñ Ar   c                	óZ   € V P                   P                  V/ 4      P                  V^ 4      # ©r@   )r  r!   )r7   r  r  s   &&&r   r!   Ú_ThreadCountStore.getA  s&   € Ø�|‰|×Ñ ¨Ó,×0Ñ0°¸aÓ@Ð@r   c               ó$   € V ^8„  d   QhRRRRRR/# r  r   )r   s   "r   r   r  D  s!   € ÷ ñ ˜Cð ¨cð °cñ r   c                ó˜   € V P                   P                  V/ 4      pVP                  V^ 4      pV^,           W2&   V P                  4        V# )z=Increment and write through; returns the PRE-increment value.)r  Ú
setdefaultr!   Ú_save)r7   r  r  Úchat_countsÚprevs   &&&  r   ÚincrÚ_ThreadCountStore.incrD  sB   € à—l‘l×-Ñ-¨g°rÓ:ˆØ�‰˜{¨AÓ.ˆØ#'¨!¥8ˆÑ Ø�
‰
ŒØˆr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   r  r   r-   r   )r   s   "r   r   r  L  s!   € ÷ ñ ˜Cð ¨cð °dñ r   c                ó¸   € V P                   P                  V/ 4      pVP                  V^ 4      ^ 8”  d'   W2;;,          ^,          uu&   V P                  4        R# R# )zMUndo one :meth:`incr` for an inbound that was not admitted; never below zero.N)r  r!   r#  )r7   r  r  r$  s   &&& r   ÚdecrÚ_ThreadCountStore.decrL  sG   € à—l‘l×&Ñ& w°Ó3ˆØ�?‰?˜;¨Ó*¨QÔ.Ø×$¨Õ)Ó$Ø�J‰JŽLñ /r   c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   r  S  s   € ÷ kñ k�tñ kr   c                óÜ  €  V P                   P                  P                  RRR7       V P                   P                  V P                   P                  R,           4      pVP                  \        P                  ! V P                  R	R7      RR7       \        P                  ! WP                   4       R#   \         d-   p\        P                  RT P                   T4        Rp?R# Rp?ii ; i)
zFAtomic write; failure is non-fatal (in-memory counts stay consistent).T©ÚparentsÚexist_okz.tmp)Ú
separatorsúutf-8râ   z;[GoogleChat] could not persist thread-count store to %s: %sN)Ú,Ú:)r  ÚparentÚmkdirÚwith_suffixÚsuffixÚ
write_textrê   Údumpsr  r   Úreplacer  r  r  )r7   Útmpr_   s   &  r   r#  Ú_ThreadCountStore._saveS  s¦   € ð	kØ�J‰J×Ñ×#Ñ#¨D¸4Ð#Ô@Ø—*‘*×(Ñ(¨¯©×):Ñ):¸VÕ)CÓDˆCØ�N‰Nœ4Ÿ:š: d§l¡l¸zÔJÐU\ˆNÔ]Ü�JŠJ�sŸJ™JÖ'øÜô 	kÜ�N‰NÐXÐZ^×ZdÑZdÐfi×jÒjûð	kús   ‚B0B4 Â4C+Â?!C&Ã&C+)r  r  N)rM   rN   rO   rP   rQ   r8   rð   r!   r&  r*  r#  rS   r   r   r   rÿ   rÿ   "  s.   † ñUõ5õ2õ(Aõõ÷kñ kr   rÿ   rÞ   z'Inline SA JSON is not valid JSON: {exc}rß   z7Service Account JSON file not found at configured path.rä   z2Service Account JSON file is not valid JSON: {exc}ræ   zÍGoogle Chat ADC skipped for this profile: service-account credentials are set in the process environment but not in this profile's secret scope. Set GOOGLE_CHAT_SERVICE_ACCOUNT_JSON in this profile's .env.rç   z±No Service Account credentials configured. Set GOOGLE_CHAT_SERVICE_ACCOUNT_JSON or GOOGLE_APPLICATION_CREDENTIALS, or install google-auth to use Application Default Credentials.rè   zÆNo Service Account credentials configured and Application Default Credentials are unavailable. Set GOOGLE_CHAT_SERVICE_ACCOUNT_JSON or run ``gcloud auth application-default login``. ADC error: {exc}c               ó$   € V ^8„  d   QhRRRRRR/# )r   r�   r<   Ú	thread_idrÛ   r   rd   r   )r   s   "r   r   r   l  s!   € ÷ ñ �sð  }ð ¸ñ r   c                ó,   € RV /pV'       d   RV/VR&   V# )zC``{"text": ...}`` plus ``thread.name`` when replying into a thread.r�   rq   Úthreadr   )r�   r?  Úbodys   && r   Ú_thread_bodyrC  l  s!   € à" D˜>€DßØ  )Ð,ˆˆX‰Ø€Kr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   rB  rd   r   r   )r   s   "r   r   r   t  s!   € ÷ ñ ˜Cð  ~ð ¸.ñ r   c                ó|   € RV RV/pVP                  R4      ;'       g    / P                  R4      '       d   RVR&   V# )uá   messages.create kwargs. With ``thread.name`` we MUST pass
``messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`` â€” the default silently
ignores thread.name; FALLBACK (vs OR_FAIL) still delivers when the thread is gone.r5  rB  rA  rq   Ú$REPLY_MESSAGE_FALLBACK_TO_NEW_THREADÚmessageReplyOption)r!   )r  rB  r>   s   && r   Ú_create_kwargsrH  t  sD   € ð '¨°¸Ð>€FØ�‰�Ó× Ð ˜b×%Ñ% f×-Ò-Ø'MˆÐ#Ñ$Ø€Mr   c                  óÊ  a € ] tR tRtRt]t^
tRtRt	Rt
R V 3R llt]R R	 l4       t]RˆR
 R ll4       tR R ltR R lt]R R l4       t]R R l4       tR R ltR R ltR R ltR R ltR R ltR R ltR  R! ltR" R# ltR$R%/R& R' lltR( R) ltR* R+ lt]RˆR, R- ll4       tR‰R. R/ lltR0 R1 lt R2 R3 lt!R4 R5 lt"R6 R7 lt#R8 R9 lt$R: R; lt%R‰R< R= llt&R> R? lt'R@ RA lt(RB RC lt)RŠRD RE llt*R‰RF RG llt+R‰RH V 3RI lllt,RJR%/RK RL llt-RM RN lt.RO RP lt/RQ RR lt0]1RS RT l4       t2R‰RU RV llt3RW RX lt4RYRZ/R[ R\ llt5R] R^ lt6R_ R` lt7R‰Ra Rb llt8Rc Rd lt9Re Rf lt:Rg Rh lt;Ri Rj lt<R‹Rk Rl llt=R‰Rm Rn llt>RŠRo Rp llt?R‹Rq Rr llt@RŠRs Rt lltARŠRu Rv lltBR‹Rw Rx lltC]Ry Rz l4       tDR{ R| ltER} R~ ltFR R€ ltGRŠR� R‚ lltHRƒ R„ ltIR… R† ltJR‡tKV ;tL# )ŒÚGoogleChatAdapteri~  a  Google Chat bot adapter: Pub/Sub pull (or HTTP callbacks) + Chat REST API. Env vars
are documented in gateway/config.py (GOOGLE_CHAT_PROJECT_ID, GOOGLE_CHAT_SUBSCRIPTION_NAME,
GOOGLE_CHAT_SERVICE_ACCOUNT_JSON + optional allowlist/home-channel/flow-control keys).g       @g      ^@Ú
__legacy__c               ó   € V ^8„  d   QhRR/# )r   Úconfigrw   r   )r   s   "r   r   ÚGoogleChatAdapter.__annotate__Š  s   € ÷ 1qñ 1q˜~ñ 1qr   c                	ó2  <€ \         SV `  V\        R 4      4       \        4        R;V n        ;V n        ;V n        V n        R;V n        ;V n	        V n
        RV n        RV n        RV n        R;V n        V n        / V n        / V n        / V n        \'        4       V n        RV n        / V n        / / uV n        V n        / V n        ^ RIHp \9        V! 4       R,          4      V n        / V n        / V n        V P@                  PB                  pV PE                  VRR^4      V n#        V PE                  VRRR4      V n$        \K        VPM                  R	4      ;'       g    \O        R
R4      ;'       g    R4      PQ                  4       V n)        \U        VPM                  R4      ;'       g    \O        R4      4      V n+        V PY                  VRR4      V n-        V PY                  VRRV PZ                  4      V n.        V PY                  VRR4      P_                  4       V n0        R# )rx   NF©Úget_hermes_homezgoogle_chat_thread_counts.jsonÚmax_messagesÚGOOGLE_CHAT_MAX_MESSAGESÚ	max_bytesÚGOOGLE_CHAT_MAX_BYTESÚbootstrap_spacesÚGOOGLE_CHAT_BOOTSTRAP_SPACESr¯   Ú	debug_rawÚGOOGLE_CHAT_DEBUG_RAWÚhttp_events_urlÚGOOGLE_CHAT_HTTP_EVENTS_URLÚhttp_events_audienceÚ GOOGLE_CHAT_HTTP_EVENTS_AUDIENCEÚ!http_events_service_account_emailÚ-GOOGLE_CHAT_HTTP_EVENTS_SERVICE_ACCOUNT_EMAILi   )1rÔ   r8   rv   ru   Ú_subscriberÚ	_chat_apiÚ_credentialsÚ_streaming_pull_futureÚ_project_idÚ_subscription_pathÚ_bot_user_idÚ_supervisor_taskÚ_loopÚ
_scope_ctxÚ_user_chat_apiÚ_user_credentialsÚ_user_creds_by_emailÚ_user_chat_api_by_emailÚ_last_sender_by_chatry   Ú_dedupÚ_shutting_downÚ_typing_messagesÚ_clarify_stateÚ_rate_limit_hitsÚ_last_inbound_threadÚhermes_constantsrQ  rÿ   Ú_thread_count_storeÚ_typing_card_inflightÚ_orphan_typing_messagesrM  r«   Ú_int_settingÚ_max_messagesÚ
_max_bytesr<   r!   Ú_get_scoped_secretr  Ú_bootstrap_spacesr   Ú
_debug_rawÚ_str_settingÚ_http_events_urlÚ_http_events_audiencerœ   Ú"_http_events_service_account_email)r7   rM  Ú_get_hermes_homer«   rÕ   s   &&  €r   r8   ÚGoogleChatAdapter.__init__Š  s  ø€ ä‰Ñ˜¤¨-Ó!8Ô9ô 	ÔØ^bÐbˆÔÐb˜4œ>Ðb¨DÔ,=ÀÔ@[ØIMÐMˆÔÐM˜4Ô2°TÔ5FØ8<ˆÔØ:>ˆŒ
ð :>ˆŒð 8<Ð;ˆÔ˜dÔ4Ø46ˆÔ!Ø79ˆÔ$à46ˆÔ!Ü)Ó+ˆŒØ#ˆÔØ02ˆÔØ57¸Ð2ˆÔ˜TÔ2ð 57ˆÔ!ÝHÜ#4Ñ5EÓ5GÐJjÕ5jÓ#kˆÔ ð @BˆÔ"à=?ˆÔ$ð —‘×!Ñ!ˆØ!×.Ñ.¨u°nÐF`ÐbcÓdˆÔØ×+Ñ+¨E°;Ð@WÐYiÓjˆŒÜ!$Ø�I‰IÐ(Ó)×iÐiÔ-?Ð@^Ð`bÓ-c×iÐiÐgió"kßkpÑkpÓkrð 	Ôä˜uŸy™y¨Ó5×dÐdÔ9KÐLcÓ9dÓeˆŒØ $× 1Ñ 1°%Ð9JÐLiÓ jˆÔØ%)×%6Ñ%6ØÐ)Ð+MÈt×OdÑOdó&fˆÔ"à26×2CÑ2CØÐ6Ð8gó3ißinÑinÓipð 	Ö/r   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r«   rd   Úkeyr<   Úenv_namer÷   r,   r   r   )r   s   "r   r   rN  ¾  s0   € ÷ ñ ˜Nð °ð Àð Ècð ÐVYñ r   c                	ó¤   €  \        V P                  V4      ;'       g    \        V\        V4      4      4      #   \        \
        3 d    Tu # i ; ir0   )r,   r!   r|  r<   r  Ú	TypeError)r«   r†  r‡  r÷   s   &&&&r   ry  ÚGoogleChatAdapter._int_setting½  sG   € ð	Ü�u—y‘y “~×SÐSÔ);¸HÄcÈ'ÃlÓ)SÓTÐTøÜœIÐ&ô 	ØŠNð	ús   ‚9 Ÿ9 ¹AÁAc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r   r«   rd   r†  r<   r‡  Úfallbackr   r   )r   s   "r   r   rN  Å  s7   € ÷ Xñ X˜Nð X°ð XÀð XÈsð XÐ\_ñ Xr   c                	ó|   € V P                  V4      ;'       g    \        VR 4      ;'       g    TP                  4       # ©r¯   )r!   r|  r  )r«   r†  r‡  rŒ  s   &&&&r   r  ÚGoogleChatAdapter._str_settingÄ  s1   € à—	‘	˜#“×NÐNÔ"4°X¸rÓ"B×NÐNÀh×UÑUÓWÐWr   c               ó   € V ^8„  d   QhRR/# rU   r   )r   s   "r   r   rN  É  s   € ÷ ñ  cñ r   c                ó´  € V P                   P                  P                  R4      ;'       g    \        R4      p \	        V4      pT'       g   \        P                  R4       T#   \
         di   p\        TP                  ,          P                  TP                  R7      pTP                  R8X  d   \        T4      h\        T4      TP                  hRp?ii ; i)uÕ  SA credentials: ``extra['service_account_json']`` â†’ GOOGLE_APPLICATION_CREDENTIALS â†’ ADC.

Priority: 1. Explicit ``extra['service_account_json']`` (path or inline JSON) 2. 3. Application
Default Credentials via ``google.auth.default()`` â€” works on Cloud Run / GCE / GKE with a workload
identity attached, or locally via ``gcloud auth application-default login``. Lets operators run the
gateway in GCP without managing SA key files. Pattern lifted from PR #14965.
Úservice_account_jsonr   r‰   rß   NzI[GoogleChat] No SA JSON configured; using Application Default Credentials)rM  r«   r!   r|  rý   rÎ   Ú_SA_ERROR_MESSAGESrÐ   r   rÑ   ÚFileNotFoundErrorr  r  rø   )r7   Úsa_pathrû   ÚerrÚmessages   &    r   Ú_load_sa_credentialsÚ&GoogleChatAdapter._load_sa_credentialsÉ  s¯   € ð —+‘+×#Ñ#×'Ñ'Ð(>Ó?×wÐwÔCUÐVvÓCwˆð	6Ü3°GÓ<ˆK÷ Ü�K‰KÐcÔdØÐøô "ô 	6Ü(¨¯©Õ2×9Ñ9¸c¿j¹jÐ9ÓIˆGØ�x‰x˜;Ô&Ü'¨Ó0Ð0Ü˜WÓ%¨3¯:©:Ð5ûð		6ús   ºA$ Á$CÁ/A#CÃCc               ó   € V ^8„  d   QhRR/# )r   r   ztuple[str, Optional[str]]r   )r   s   "r   r   rN  Ý  s   € ÷ 
ñ 
Ð";ñ 
r   c                ó”  € V P                   P                  P                  R4      ;'       g    RP                  4       pV P                   P                  P                  R4      ;'       g    RP                  4       pV P                   P                  P                  R4      ;'       g    RP                  4       pV'       da   \        P                  V4      pV'       g   \        R4      hVP                  R4      pV'       d   WQ8w  d   \        R4      hT;'       g    TV3# V'       d   VR3# V'       g   \        R	4      h\        R
4      h)zŽReturn (project_id, subscription_path); the latter is None for HTTP inbound.
Raises ValueError with a sanitized message on any config problem.Ú
project_idr¯   Úsubscription_namerZ  zRGOOGLE_CHAT_SUBSCRIPTION_NAME must match 'projects/<project>/subscriptions/<sub>'.Úprojectzjproject_id in GOOGLE_CHAT_PROJECT_ID does not match the project embedded in GOOGLE_CHAT_SUBSCRIPTION_NAME.Nz<GOOGLE_CHAT_PROJECT_ID (or GOOGLE_CLOUD_PROJECT) is not set.zGOOGLE_CHAT_SUBSCRIPTION_NAME (or GOOGLE_CHAT_SUBSCRIPTION) is not set. Set GOOGLE_CHAT_HTTP_EVENTS_URL for HTTP callback mode.)rM  r«   r!   r  Ú_SUBSCRIPTION_PATH_REÚmatchr  Úgroup)r7   rœ  ÚsubscriptionrZ  r   Úsubscription_projects   &     r   Ú_validate_configÚ"GoogleChatAdapter._validate_configÝ  s  € ð —k‘k×'Ñ'×+Ñ+¨LÓ9×?Ð?¸R×FÑFÓHˆ
ØŸ™×)Ñ)×-Ñ-Ð.AÓB×HÐHÀb×OÑOÓQˆØŸ;™;×,Ñ,×0Ñ0Ð1BÓC×IÐIÀr×PÑPÓRˆßÜ)×/Ñ/°Ó=ˆEßÜ Ð!uÓvÐvØ#(§;¡;¨yÓ#9Ð ßÐ2Ô@Ü ð Aóð ð ×5Ð5Ð!5°|ÐCÐCßØ˜tÐ#Ð#ßÜÐ[Ó\Ð\ÜðFó
ð 	
r   c               ó    € V ^8„  d   QhRRRR/# )r   Úfuturer   r   r-   r   )r   s   "r   r   rN  ø  s   € ÷ Rñ R¨ð R°ñ Rr   c                	óv   €  V P                  4        R#   \         d    \        P                  R 4        R# i ; i)z1[GoogleChat] Background inbound processing failedN)Úresultr·   r  Ú	exception)r§  s   &r   Ú_log_background_failureÚ)GoogleChatAdapter._log_background_failure÷  s1   € ð	RØ�M‰MŽOøÜô 	RÜ×ÑÐP×Qð	Rús   ‚ ” 8·8c               ó    € V ^8„  d   QhRRRR/# )r   Úloopz#Optional[asyncio.AbstractEventLoop]r   r   r   )r   s   "r   r   rN  ÿ  s   € ÷ Zñ ZÐ&Ið ZÈdñ Zr   c                	ó\   € V R J;'       d"    \        \        V RR 4      ! 4       4      '       * # )NÚ	is_closedc                 ó   € R # )Fr   r   r   r   Ú<lambda>Ú;GoogleChatAdapter._loop_accepts_callbacks.<locals>.<lambda>   s   € ÑPUr   )r   rF   )r®  s   &r   Ú_loop_accepts_callbacksÚ)GoogleChatAdapter._loop_accepts_callbacksþ  s)   € à˜4Ð×YÐY¬¬W°T¸;ÉÔ-VÓ-XÓ(YÔ$YÐYr   c               ó    € V ^8„  d   QhRRRR/# )r   Úcoror   r   r-   r   )r   s   "r   r   rN    s   € ÷ Cñ C Cð C¨Dñ Cr   c           	     óâ  € V P                  V P                  ;p4      '       g   \        P                  R4       R#  ^ RIHp V P                  e   V P                  P                  4       M\        P                  ! 4       pVP                  W1V\        R\        P                  R7      pTe   TP                  T P                  4       R# R#   \         d    \        P                  R4        R# i ; i)zHSchedule a coroutine on the adapter loop from a Pub/Sub callback thread.z9[GoogleChat] Loop not accepting callbacks; dropping eventN)Úsafe_schedule_threadsafez3[GoogleChat] Failed to schedule background callback)r  Úlog_messageÚ	log_levelz1[GoogleChat] Loop closed between check and submit)r´  rh  r  r  Úagent.async_utilsr¹  ri  ÚcopyÚcontextvarsÚcopy_contextÚrunÚloggingÚWARNINGr\   Úadd_done_callbackr«  )r7   r·  r®  r¹  Úctxr§  s   &&    r   Ú_submit_on_loopÚ!GoogleChatAdapter._submit_on_loop  sÄ   € à×+Ñ+°D·J±JÐ,>¨D×?Ò?ä�N‰NÐVÔWÙð	ÝBð -1¯O©OÒ,G�$—/‘/×&Ñ&Ô(Ì[×MeÒMeÓMgˆCØ—W‘WØ(°¼VØQÔ]d×]lÑ]lð ó ˆFð ÒØ×$Ñ$ T×%AÑ%AÖBñ øô ô 	Ü�N‰NÐNÔOÚð	ús   ¼A+C
 Ã
 C.Ã-C.c               ó   € V ^8„  d   QhRR/# )r   r   r  r   )r   s   "r   r   rN    s   € ÷ >ñ > Eñ >r   c                ó*   € ^ RI Hp V! 4       R,          # )zIResolved at call time so multiplexed profiles don't share one cache file.rP  zgoogle_chat_bot_id.json)ru  rQ  )r7   rƒ  s   & r   Ú_bot_id_cache_pathÚ$GoogleChatAdapter._bot_id_cache_path  s   € åHÙÓ!Ð$=Õ=Ð=r   c               ó   € V ^8„  d   QhRR/# ©r   r   rÛ   r   )r   s   "r   r   rN    s   € ÷ ñ  ]ñ r   c                	óâ   €  \         P                  ! V P                  4       P                  R R7      4      P	                  R4      ;'       g    R#   \
        \         P                  3 d     R# i ; i)rá   râ   Úbot_user_idN)rê   rë   rÉ  r
  r!   r  rì   ©r7   s   &r   Ú_load_cached_bot_idÚ%GoogleChatAdapter._load_cached_bot_id  s_   € ð	Ü—:’:˜d×5Ñ5Ó7×AÑAÈ;ÐAÓWÓX×\Ñ\Ð]jÓk×sÐsÐosÐsøÜœ×-Ñ-Ð.ô 	Úð	ús   ‚A	A ÁA ÁA.Á-A.c               ó    € V ^8„  d   QhRRRR/# )r   rÎ  r<   r   r-   r   )r   s   "r   r   rN  $  s   € ÷ \ñ \¨sð \°tñ \r   c                	ó  €  V P                  4       pVP                  P                  R R R7       VP                  \        P
                  ! RV/4      RR7       R#   \         d    \        P                  RR R7        R# i ; i)Tr.  rÎ  r2  râ   z0[GoogleChat] Could not persist bot_user_id cache©Úexc_infoN)	rÉ  r5  r6  r9  rê   r:  r  r  Údebug)r7   rÎ  rí   s   && r   Ú_save_cached_bot_idÚ%GoogleChatAdapter._save_cached_bot_id$  sn   € ð	\Ø×*Ñ*Ó,ˆDØ�K‰K×Ñ d°TÐÔ:Ø�O‰OœDŸJšJ¨°{Ð'CÓDÈwˆOÖWøÜô 	\Ü�L‰LÐKÐVZˆL×[ð	\ús   ‚AA Á"B Á?B c               ó   € V ^8„  d   QhRR/# rÌ  r   )r   s   "r   r   rN  ,  s   € ÷ ñ ¨Mñ r   c              ƒ  óZ  a "  € . pS P                   P                  '       dV   S P                   P                  P                  '       d0   VP                  S P                   P                  P                  4       S P                  '       d2   VP                  R S P                  P                  R4       4       4       V F¥  p \        P                  ! V3V 3R ll4      G Rj  x€L
 pTP                  R. 4       Ff  pTP                  R/ 4      P                  R4      R	8X  g   K+  TP                  R/ 4      P                  R
4      '       g   KT  TR,          R
,          u u # 	  K§  	  R#  L†  \         d5   p\        P                  RT\        \        T4      4      4        Rp?Kç  Rp?ii ; i5i)z¥Resolve ``users/{id}`` via members.list on the home channel, then bootstrap
spaces. None when no space is known (self-filter falls back to ``sender.type == 'BOT'``).c              3  óp   "  € T F,  qP                  4       '       g   K  VP                  4       x € K.  	  R # 5ir0   )r  )rŽ   Úss   & r   r‘   Ú9GoogleChatAdapter._resolve_bot_user_id.<locals>.<genexpr>3  s%   é € Ð#fÑ7X°!×\cÑ\c×\e¤I A§G¡G§I IÓ7Xùs   ‚6ž6r3  c                ó²   <€ SP                   P                  4       P                  4       P                  V ^2R7      P	                  SP                  4       R7      # )é2   )r5  ÚpageSize©Úhttp)ra  ÚspacesÚmembersÚlistÚexecuteÚ_new_authed_http)rÜ  r7   s   &€r   r²  Ú8GoogleChatAdapter._resolve_bot_user_id.<locals>.<lambda>7  sG   ø€  D§N¡N×$9Ñ$9Ó$;×$CÑ$CÓ$E×$JÑ$JÐRSÐ^`Ð$JÓ$aß‘W $×"7Ñ"7Ó"9�WÓ:ð%;r   Nz*[GoogleChat] members.list failed on %s: %sÚmembershipsÚmemberÚtypeÚBOTrq   )rM  Úhome_channelr  r©   r}  ÚextendÚsplitÚasyncioÚ	to_threadr$   r  rÖ  rÃ   r<   r!   )r7   Úcandidate_spacesÚspacerä  r_   rê  s   f     r   Ú_resolve_bot_user_idÚ&GoogleChatAdapter._resolve_bot_user_id,  sN  øé € ð ')ÐØ�;‰;×#×#Ð#¨¯©×(@Ñ(@×(H×(HÐ(HØ×#Ñ# D§K¡K×$<Ñ$<×$DÑ$DÔEØ×!×!Ð!Ø×#Ñ#Ñ#f°t×7MÑ7M×7SÑ7SÐTWÔ7XÓ#fÔfÛ%ˆEðÜ '× 1Ò 1Ø"ö ;ó!÷ �ð "Ÿ+™+ m°RÖ8�Ø—:‘:˜h¨Ó+×/Ñ/°Ó7¸5Ö@ÀVÇZÁZÐPXÐZ\ÓE]×EaÑEaÐbh×EiÔEiØ! (Õ+¨FÕ3Ô3ó 9ñ &ñ ñøô ô Ü—‘ÐIÈ5ÔRcÔdgÐhkÓdlÓRmÔnÝûðüs[   ƒAF+ÁA F+Â	6F+Ã  E)Ã E'Ã!E)Ã%8F+Ä"$F+ÅF+Å'E)Å)F(Å4)F#ÆF+Æ#F(Æ(F+c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   Úlog_fmtr<   r_   r†   ÚcodeÚ	retryabler   r   r   )r   s   "r   r   rN  C  s1   € ÷ ñ  sð °ð Àcð ÐY]ð Ðbfñ r   c               ó~   € \        \        V4      4      p\        P                  W4       V P	                  W5VR7       R# )zFLog a redacted connect-time failure, record it as fatal, return False.©rø  r—  rù  F)rÃ   r<   r  ÚerrorÚ_set_fatal_error)r7   r÷  r_   rø  rù  Úmsgs   &&&&$ r   Ú_connect_failedÚ!GoogleChatAdapter._connect_failedC  s2   € ä¤ C£Ó)ˆÜ�‰�WÔ"Ø×Ñ 4À	ÐÔJÙr   c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   rN  J  s   € ÷ @ñ @¨ñ @r   c           	   ƒ  óŠ  aa"  €  ^RI HpHo ^RI Hp \        P
                  ! V4      G Rj  x€L
 oSeE   SV n        \        P
                  ! VV3R l4      G Rj  x€L
 V n        \        P                  R4       \        P
                  ! V4      G Rj  x€L
 pV'       d2   \        P                  R\        V4      RP                  V4      4       R# Sf   \        P                  R4       R# R#  LÀ L” L^  \         dB   p\        P                  R	\        \        T4      4      4       R;T n        T n         Rp?R# Rp?ii ; i5i)
z†Legacy single-user OAuth (per-user tokens load lazily on first send).
Failure is NON-fatal: only attachments degrade to a text notice.©Úload_user_credentialsÚbuild_user_chat_service)Úlist_authorized_emailsNc                 ó   <€ S ! S4      # r0   r   )Ú_build_user_chatÚ
user_credss   €€r   r²  Ú4GoogleChatAdapter._load_user_oauth.<locals>.<lambda>S  s   ø€ ÑFVÐWaÔFbr   uN   [GoogleChat] Legacy user OAuth loaded â€” fallback attachment delivery enabledz1[GoogleChat] %d per-user OAuth tokens on disk: %sz, u²   [GoogleChat] No user OAuth tokens at setup â€” file attachments will degrade to text-only fallback. Each user runs /setup-files once in their own DM to enable native attachments.zX[GoogleChat] User OAuth load failed (attachments will degrade to text-only fallback): %s)Úoauthr  r  r  rð  rñ  rk  rj  r  rø   ÚlenÚjoinr·   r  rÃ   r<   )r7   Ú_load_user_credsÚ_list_emailsÚ
authorizedr_   r  r	  s   &    @@r   Ú_load_user_oauthÚ"GoogleChatAdapter._load_user_oauthJ  s  ùé € ð	@ßuÝEÜ&×0Ò0Ð1AÓB×BˆJØÒ%Ø)3�Ô&Ü,3×,=Ò,=Õ>bÓ,c×&c�Ô#Ü—‘ÐlÔmÜ&×0Ò0°Ó>×>ˆJßÜ—‘ÐOÔQTÐU_ÓQ`Ðbf×bkÑbkÐlvÓbwÖxØÒ#Ü—‘ðeöñ $ñ Cñ 'dá>øô ô 	@Ü�N‰NØjÜ!¤# c£(Ó+ôð <@Ð?ˆDÔ" T×%8Ò%8ûð	@üst   „E†'C4 ­C.®-C4 ÁC0Á7C4 ÂC2ÂC4 Â /C4 ÃEÃC4 Ã*EÃ.C4 Ã0C4 Ã2C4 Ã4E Ã?6D;Ä5EÄ;E Å Ec               ó$   € V ^8„  d   QhRRRRRR/# )r   Úsubscription_pathr<   rû   r   r   r   r   )r   s   "r   r   rN  d  s"   € ÷ ñ ¸3ð ÈSð ÐUYñ r   c              ƒ  óÜ  a a"  € \         P                  R
\         P                  R/p\        P	                  VR7      S n         \        P                  ! V V3R l4      G Rj  x€L
  R#  L  \         P                  \         P                  3 d3   pT\        T4      ,          w  rVS P                  YVRR7        Rp?R# Rp?i\         d    pS P                  RTRRR	7      u Rp?# Rp?ii ; i5i)zICreate the subscriber and verify the subscription exists / SA has access.©rû   c                 ó@   <€ S P                   P                  R S/R7      # )r¢  )r*   )r`  Úget_subscription)r7   r  s   €€r   r²  Ú7GoogleChatAdapter._check_subscription.<locals>.<lambda>m  s    ø€ ¨D×,<Ñ,<×,MÑ,MÐWeÐgxÐVyÐ,MÔ,zr   NFrû  z([GoogleChat] subscription.get failed: %sÚsubscription_checkT©rù  )Úsubscription_not_foundz1Pub/Sub subscription not found at configured path)Úsubscription_permissionzAService Account lacks roles/pubsub.subscriber on the subscription)Úgax_exceptionsÚNotFoundÚPermissionDeniedÚ	pubsub_v1ÚSubscriberClientr`  rð  rñ  rë  rý  r·   rÿ  )r7   r  rû   Úfatalsr_   rø  r—  s   ff&    r   Ú_check_subscriptionÚ%GoogleChatAdapter._check_subscriptiond  s×   ùé € ô ×#Ñ#Ð%tÜ×+Ñ+ð .pð
ˆô
 %×5Ñ5À+Ð5ÓNˆÔð	Ü×#Ò#Õ$zÓ{×{Ð{ñ ñ |øÜ×'Ñ'¬×)HÑ)HÐIô 	Ø"¤4¨£9Õ-‰MˆDØ×!Ñ! tÈÐ!ÔNÝûÜô 	Ø×'Ñ'Ð(RÐTWÐYmÐy}Ð'Ó~Õ~ûð	üs_   „>C,ÁA* Á!A(Á"A* Á&C,Á(A* Á*%C)Â'B<Â6C,Â<C)Ã	C)Ã
C$ÃC)ÃC,Ã$C)Ã)C,Úis_reconnectFc               ó    € V ^8„  d   QhRRRR/# )r   r&  r   r   r   )r   s   "r   r   rN  v  s   € ÷ .ñ .¨Tð .¸dñ .r   c          	   ƒ  óþ  a"  € \        4       '       g   V P                  RRRR7       R# \        P                  ! 4       V n        \
        P                  ! 4       V n         V P                  4       w  r#V P                  4       oY#SuT n        T n        T n         \        P                   ! T3R	 l4      G Rj  x€L
 T n        T P'                  4       G Rj  x€L
   \        P                   ! T P(                  P*                  4      G Rj  x€L
  Te#   T P1                  TS4      G Rj  x€L
 '       g   R# T P3                  4       T n        T P4                  '       ga   T P7                  4       G Rj  x€L
 T n        T P4                  '       d   T P9                  T P4                  4       M\,        P;                  R4       Te%   \        P<                  ! T P?                  4       4      MRT n         T PC                  4        \,        P;                  RT;'       g    RTe   RMRT'       d   RMRT P4                  ;'       g    RT PD                  T PF                  4       T PI                  R4       R#   \        \        3 d    pT P                  RTRRR7      u Rp?# Rp?ii ; i ELä  \$         d    pT P                  R
TRRR7      u Rp?# Rp?ii ; i EL÷ ELÇ  \$         d    \,        P/                  RRR7        ELêi ; i ELÕ EL‘5i)zBValidate config, authenticate, start Pub/Sub pull, resolve bot id.Úmissing_depsFz<google-cloud-pubsub / google-api-python-client not installed)rø  rù  r—  z)[GoogleChat] Config validation failed: %sÚconfig_invalidr  Nc                 ó"   <€ \        R RS RR7      # )ÚchatÚv1F)rû   Úcache_discovery)Úbuild_servicer  s   €r   r²  Ú+GoogleChatAdapter.connect.<locals>.<lambda>‡  s   ø€ œ f¨dÀÐ]bÕcr   z0[GoogleChat] Failed to build Chat API client: %sÚchat_api_initzK[GoogleChat] thread-count store load failed (treating all threads as fresh)TrÔ  z^[GoogleChat] bot_user_id not yet resolved; will resolve on first addedToSpace or member lookupzp[GoogleChat] Connected; project=%s, inbound=%s, subscription=%s, bot_user_id=%s, flow_control(msgs=%s, bytes=%s)z<unset>Úpubsubrâ  z
<redacted>z<none>z<unresolved>)%ru   rý  rð  Úget_running_looprh  r¾  r¿  ri  r¤  r˜  r  r”  rÿ  rd  re  rb  rñ  ra  r·   r  rv  rð   r  r  r$  rÐ  rf  rô  r×  rø   Úcreate_taskÚ_run_supervisorrg  Ú_mark_connectedrz  r{  Ú_wire_plugin_handlers)r7   r&  rœ  r  r_   rû   s   &$   @r   ÚconnectÚGoogleChatAdapter.connectv  s¨  øé € ô $×%Ò%Ø×!Ñ! ~ÀØ*hð "ô jáÜ×-Ò-Ó/ˆŒ
Ü%×2Ò2Ó4ˆŒð	}Ø,0×,AÑ,AÓ,CÑ)ˆJØ×3Ñ3Ó5ˆKð HRÐfqÐDˆÔ˜$Ô1°4Ô3Dð	CÜ#*×#4Ò#4Ücó$e÷ eˆDŒNð ×#Ñ#Ó%×%Ð%ð	yÜ×#Ò# D×$<Ñ$<×$AÑ$AÓB×BÐBð Ò(°t×7OÑ7OÐPaÐcnÓ7o×1oÖ1oÙà ×4Ñ4Ó6ˆÔØ× × Ð Ø&*×&?Ñ&?Ó&A× AˆDÔØ× × Ð Ø×(Ñ(¨×):Ñ):Õ;ä—‘Ð|Ô}ØO`ÒOl¤× 3Ò 3°D×4HÑ4HÓ4JÔ KÐrvˆÔØ×ÑÔÜ�‰ð>à×#Ð#˜)Ð1BÒ1N¡XÐTZß-‰L°8¸T×=NÑ=N×=`Ð=`ÐR`Ø×Ñ §¡ô	
ð 	×"Ñ" 4Ô(ÙøôE Ô-Ð.ô 	}Ø×'Ñ'Ð(SÐUXÐZjÐv{Ð'Ó|Õ|ûð	}úòeøäô 	CØ×'Ñ'Ð(ZÐ\_Ðapð  }BÐ'ó  Cõ  Cûð	Cúâ%âBøÜô 	yÜ�N‰NÐhÐswˆN×xð	yúâ1oò
 !Bùsý   ƒAK=Á"I% ÂK=ÂJ Â4JÂ5	J Â>K=ÃKÃK=Ã-K ÄKÄK Ä	K=Ä"K7Ä#	K=Ä-(K=ÅK=Å)K:Å*K=ÆBK=ÈK=ÈK=È50K=É%JÉ6JÊ
JÊK=ÊJÊK=ÊJ ÊKÊ&K Ê:KÊ;K=Ë KËK=ËK Ë"K4Ë0K=Ë3K4Ë4K=Ë:K=c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   rN  ¦  s   € ÷ 1ñ 1 $ñ 1r   c              ƒ  ó&  "  € RV n         V P                  '       d©   V P                  P                  4       '       g‰   V P                  P                  4        \        P
                  ! \        P                  \        P                  4      ;_uu_ 4        \        P                  ! V P                  RR7      G Rj  x€L
  RRR4       V P                  ;pel   \        P
                  ! \        4      ;_uu_ 4        VP                  4        \        P                  ! VP                  R4      G Rj  x€L
  RRR4       RV n
        V P                  ;pe[   \        P
                  ! \        4      ;_uu_ 4        \        P                  ! VP                  4      G Rj  x€L
  RRR4       RV n        V P!                  4        \"        P%                  R4       R#  EL  + '       g   i     EL ; i L»  + '       g   i     LÁ; i Lf  + '       g   i     Ll; i5i)zKClean shutdown: stop accepting new messages, wait in-flight, close clients.Tç      @©ÚtimeoutNç      $@z[GoogleChat] Disconnected)rp  rg  ÚdoneÚcancelÚ
contextlibÚsuppressrð  ÚCancelledErrorÚTimeoutErrorÚwait_forrc  r·   rñ  r©  r`  ÚcloseÚ_mark_disconnectedr  rø   )r7   r§  Ú
subscribers   &  r   Ú
disconnectÚGoogleChatAdapter.disconnect¦  sd  é € à"ˆÔØ× × Ð ¨×)>Ñ)>×)CÑ)C×)EÒ)EØ×!Ñ!×(Ñ(Ô*Ü×$Ò$¤W×%;Ñ%;¼W×=QÑ=Q×RÕRÜ×&Ò& t×'<Ñ'<ÀcÔJ×JÐJ÷ Sà×1Ñ1Ð1ˆFÒ>Ü×$Ò$¤Y×/Õ/Ø—‘”Ü×'Ò'¨¯©°tÓ<×<Ð<÷ 0ð +/ˆDÔ'Ø×*Ñ*Ð*ˆJÒ7Ü×$Ò$¤Y×/Õ/Ü×'Ò'¨
×(8Ñ(8Ó9×9Ð9÷ 0à#ˆDÔØ×ÑÔ!Ü�‰Ð/Ö0ò K÷ S×RÐRúñ
 =÷ 0×/úñ :÷ 0×/üsŠ   ‚9H¼AHÂ&GÂ7GÂ8GÂ<:HÃ65G)Ä+G'Ä,G)Ä0AHÅ1$G>ÆG<ÆG>Æ6HÇGÇG$	Ç	HÇ'G)Ç)G9	Ç4HÇ<G>Ç>H	È	Hc               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   rN  ¹  s   € ÷ +ñ + tñ +r   c              ƒ  ó  "  € \         P                  R\         P                  R/p^ pV P                  '       gÍ   \        P
                  P                  V P                  V P                  R7      p V P                  P                  V P                  V P                  VR7      ;V n        pV^ 8”  d   \        P                  RV4       ^ p\         P"                  ! VP$                  4      G Rj  x€L
  V P                  '       d   R# KÞ  R#  L  \         P&                   d     R# \         P                  \         P                  3 d3   pT\)        T4      ,          w  rgT P+                  YgRR7        Rp?R# Rp?i\,         Ed   pT^,          p\        P/                  RTT P0                  \3        \5        T4      4      4       Y P0                  8¼  d   T P+                  RR	T R
2RR7        Rp?R# \7        T P8                  T P:                  ^T^,
          ,          ,          4      p \         P<                  ! \>        P@                  ! ^ T4      4      G Rj  x€L 
   Rp?EK6    \         P&                   d	      Rp?R# i ; iRp?ii ; i5i)z—Run streaming_pull with exponential backoff + full jitter; fatal after N attempts.
``subscribe()`` returns a Future that resolves when the stream dies.)rR  rT  )ÚcallbackÚflow_controlz9[GoogleChat] Pub/Sub stream reconnected after %d attemptsNFrû  z4[GoogleChat] Pub/Sub stream died (attempt %d/%d): %sÚpubsub_reconnect_exhaustedzPub/Sub reconnect failed z times; giving up)Úpubsub_authzQPub/Sub authentication failed; check service-account credentials and gateway logs)Úpubsub_permissionz.SA lacks pubsub.subscriber on the subscription)!r  ÚUnauthenticatedr   rp  r!  ÚtypesÚFlowControlrz  r{  r`  Ú	subscribere  Ú_on_pubsub_messagerc  r  rø   rð  rñ  r©  rD  rë  rý  r·   r  Ú_MAX_RECONNECT_ATTEMPTSrÃ   r<   ÚminÚ_RECONNECT_MAX_DELAYÚ_RECONNECT_BASE_DELAYÚsleepÚrandomÚuniform)	r7   Úpubsub_fatalsÚattemptÚflowr§  r_   rø  r—  Údelays	   &        r   r5  Ú!GoogleChatAdapter._run_supervisor¹  s)  é € ô ×*Ñ*ð -ô ×+Ñ+Ð-tð
ˆð ˆØ×%×%Ð%Ü—?‘?×.Ñ.¸D×<NÑ<NÐZ^×ZiÑZiÐ.ÓjˆDðØ7;×7GÑ7G×7QÑ7QØ×+Ñ+°d×6MÑ6MÐ\`ð 8Ró 8bð b�Ô+¨fà˜Q”;Ü—K‘KÐ [Ð]dÔeØ�ä×'Ò'¨¯©Ó6×6Ð6Ø×&×&Ð&Ùñ 'ñ &ñ 7øô ×)Ñ)ô ÚÜ"×2Ñ2´N×4SÑ4SÐTô Ø -¬d°3«iÕ 8‘�Ø×%Ñ%¨4ÈEÐ%ÔRÝûÜõ Ø˜1•�Ü—‘ÐUÐW^Ø#×;Ñ;Ô=NÌsÐSVËxÓ=XôZà×:Ñ:Ô:Ø×)Ñ)Ø9ÐE^Ð_fÐ^gÐgxÐCyØ"'ð *ô õ Ü˜D×5Ñ5°t×7QÑ7QÐUVÐ[bÐefÕ[fÕUgÕ7hÓi�ðÜ!Ÿ-š-¬¯ª°q¸%Ó(@ÓA×A×AÐAøÜ×-Ñ-ô Þðþðüs®   ‚6J¹5JÁ/A;D	 Ã*DÃ+D	 ÄJÄD	 Ä	JÄJÄ!"JÅJÅ'E2Å,JÅ2JÆ JÆA%I=Ç&JÇ,5I=È".IÉIÉIÉJÉI:É2I=É3JÉ9I:É:I=É=JÊJc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úenveloperd   Úce_typer<   r   z4Optional[tuple[dict[str, Any], dict[str, Any], str]]r   )r   s   "r   r   rN  è  s#   € ÷ %ñ %¨>ð %Ø*-ð%Ø7kñ%r   c                ó$  € V P                  R4      ;'       g    / P                  R4      pV'       dR   VP                  R4      ;'       g    / pY2P                  R4      ;'       g    VP                  R4      ;'       g    / R3# \        V P                  R4      \        4      '       dY   V P                  RR4      R8w  d   R	# V R,          pY0P                  R4      ;'       g    VP                  R4      ;'       g    / R
3# RV 9   g	   RV 9   Ed�   V P                  RR4      R8w  d   R	# V P                  R4      ;'       g    RP                  4       pV P                  RR4      ;'       g    Rp\	        V P                  R4      ;'       g    R4      P                  4       P                  4       pRV P                  RR4      ;'       g    RRRRT;'       g    RP                  RR4      P                  RR4      ,           RTRV P                  R4      ;'       g    T;'       g    RRVR%9   d   TMR/RVRV/pV P                  R4      '       d   RV R,          /VR&   RV P                  R R4      ;'       g    RR!V P                  R"R#4      /pW7R$3# R	# )&a2  Return ``(message, space, format_name)`` or None for unknown / non-MESSAGE
envelopes. Formats: Workspace Add-ons ``{"chat": {"messagePayload": ...}}``; native
``{"type": "MESSAGE", "message", "space"}``; relay/flat ``{"event_type", "sender_email",
"text", ...}`` (a Chat-shaped ``message`` is synthesized).r,  ÚmessagePayloadr—  ró  Úworkspace_addonsrë  r¯   ÚMESSAGENÚnative_chat_apiÚ
event_typeÚsender_emailr�   Úsender_typeÚHUMANrq   Úmessage_nameÚsenderzusers/relay-ÚunknownÚ@Ú_at_r²   Ú_ÚemailÚdisplayNameÚsender_display_nameÚUnknownÚargumentTextr  rA  Ú
space_nameÚ	spaceTypeÚ
space_typeÚSPACEÚ
relay_flat>   rì  ro  )r!   rš   r  r  r<   rC   r;  )re  rf  Úmsg_payload_wrapperrþ  rm  r�   rn  ró  s   &&      r   Ú_extract_message_payloadÚ*GoogleChatAdapter._extract_message_payloadç  s\  € ð  (Ÿ|™|¨FÓ3×9Ð9°r×>Ñ>Ð?OÓPÐßØ%×)Ñ)¨)Ó4×:Ð:¸ˆCØ×/Ñ/°Ó8×RÐR¸C¿G¹GÀGÓ<L×RÐRÐPRÐTfÐfÐfÜ�h—l‘l 9Ó-¬t×4Ò4Ø�|‰|˜F BÓ'¨9Ô4ÙØ˜9Õ%ˆCØŸ™ WÓ-×GÐG°·±¸Ó1A×GÐGÀRÐIZÐZÐZØ˜8Ô# ~¸Õ'AØ�|‰|˜L¨)Ó4¸	ÔAÙØ$ŸL™L¨Ó8×>Ð>¸B×EÑEÓGˆLØ—<‘< ¨Ó+×1Ð1¨rˆDô ˜hŸl™l¨=Ó9×DÐD¸WÓE×KÑKÓM×SÑSÓUˆKà˜Ÿ™ ^°RÓ8×>Ð>¸BØà˜N¨l×.GÐ.G¸i×-PÑ-PÐQTÐV\Ó-]×-eÑ-eÐfiÐknÓ-oÕoØ˜\¨=¸(¿,¹,ÐG\Ó:]×:zÐ:zÐam×:zÐ:zÐqzØ¨;Ð:JÔ+J™KÐPWð	ð ˜˜n¨dð	#ˆCð �|‰|˜M×*Ò*Ø!'¨°-Õ)@Ð A��H‘Ø˜XŸ\™\¨,¸Ó;×AÐA¸rÀ;ÐPX×P\ÑP\Ð]iÐkrÓPsÐtˆEØ˜|Ð+Ð+Ùr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   re  rd   rf  rÛ   r   z/Optional[tuple[dict[str, Any], dict[str, Any]]]r   )r   s   "r   r   rN    s#   € ÷ ,ñ ,¨ð ,Ø"/ð,Ø;jñ,r   c                óF  € T P                  Y;'       g    R4      pVf5   Ve/   \        P                  RV\        VP	                  4       4      4       R# Vw  rEpVP                  R4      ;'       g    / P                  R4      R8X  d   R# VP                  R4      ;'       g    RpV'       d>   V P                  P                  V4      '       d   Ve   \        P                  RV4       R# \        V4      \        V4      r˜W‰3 F  p
R	V
9  g   K  V'       g   K  WZR	&   K  	  W‰3# )
zÞExtract + self-filter + dedup an inbound envelope. Returns ``(msg_with_space,
enriched_envelope)`` for ``_dispatch_message``, or None when the event must be
dropped. Debug logs only on the Pub/Sub path (``ce_type`` given).r¯   NzO[GoogleChat] Envelope did not match a known message format; ce-type=%s, keys=%srq  rë  rì  rq   z[GoogleChat] Dedup drop for %sró  )	r�  r  rÖ  rå  Úkeysr!   ro  Úis_duplicater  )r7   re  rf  Ú	extractedrþ  ró  Ú_fmtÚmsg_nameÚmsg_with_spaceÚenriched_envÚds   &&&        r   Ú_prepare_inboundÚ"GoogleChatAdapter._prepare_inbound  sù   € ð
 ×1Ñ1°(¿M¸MÀrÓJˆ	ØÒØÒ"Ü—‘ØeØœT (§-¡-£/Ó2ôñ Ø$Ñˆ�Dà�G‰G�HÓ×#Ð# ×(Ñ(¨Ó0°EÔ9Ùà—7‘7˜6“?×(Ð( bˆß˜Ÿ™×0Ñ0°×:Ò:ØÒ"Ü—‘Ð=¸xÔHÙä'+¨C£y´$°x³.˜Ø Ó/ˆAØ˜aÖ§E¡EØ"�'“
ñ 0ð Ð+Ð+r   c               ó    € V ^8„  d   QhRRRR/# ©r   r—  r   r   r-   r   )r   s   "r   r   rN  -  s   € ÷ 6ñ 6¨#ð 6°$ñ 6r   c                ó¸   € V P                   e   V P                   P                  4       M\        P                  ! 4       pVP	                  V P
                  V4       R# )u¨  Pub/Sub callback â€” parse envelope and dispatch to the asyncio loop.
Runs in a SubscriberClient worker thread: never block, never raise (that
triggers nack + infinite redelivery). Event type comes from ``ce-type``. The body runs under
the adapter's profile scope (a per-callback copy: a Context cannot be entered concurrently) so
``_save_cached_bot_id`` and the loop hand-off resolve the served profile, not the launch one.N)ri  r½  r¾  r¿  rÀ  Ú_handle_pubsub_message)r7   r—  rÄ  s   && r   rW  Ú$GoogleChatAdapter._on_pubsub_message-  s>   € ð )-¯©Ò(Cˆd�o‰o×"Ñ"Ô$Ì×IaÒIaÓIcˆØ�‰�×+Ñ+¨WÖ5r   c               ó    € V ^8„  d   QhRRRR/# r�  r   )r   s   "r   r   rN  6  s   € ÷ +ñ +¨cð +°dñ +r   c                	ó*  € V P                   '       d   VP                  4        R #  \        P                  ! VP                  P                  R4      4      p\        \        TR/ 4      ;'       g    / 4      P                  R4      ;'       g    Rp\        P                  R\        TP                  4       4      T4       T P                   '       dA    ^ RIHp T! \        P&                  ! T4      4      p\        P                  R	TR
,          4        RT9   g	   RT9   Ed>   TP                  R4      ;'       g    / P                  R4      ;'       g    / pTP                  R4      ;'       g    / pRT9   dÁ   TP                  R4      ;'       g    / P                  R4      ;'       g    / pTP                  R4      R8X  dP   T P(                  '       g>   TP                  R4      '       d'   TR,          T n        T P+                  TR,          4       \        P-                  RTP                  RR4      4       M�\        P-                  RTP                  RR4      4       MfRT9   g   RTP/                  4       9   d   \        P-                  R4       M4T P1                  Y#4      p	T	e    T P3                  T P4                  ! T	!  4       TP                  4        R #   \         d*    \        P                  R4       TP                  4         R # i ; i  \         d    Rp EL)i ; i  \         dj    \        P                  R4       \6        P8                  ! \        4      ;_uu_ 4        TP                  4        R R R 4        R #   + '       g   i      R # ; ii ; i)Nr2  z-[GoogleChat] Could not parse Pub/Sub envelopeÚ
attributeszce-typer¯   z)[GoogleChat] Envelope keys=%s, ce-type=%s)Úredact_sensitive_textz<redact filter unavailable>z([GoogleChat] RAW envelope (redacted): %s:NiÐ  NÚ
membershipÚ
MEMBERSHIPr,  ÚmembershipPayloadró  Úcreatedrê  rë  rì  rq   z[GoogleChat] ADDED_TO_SPACE %sÚ?z"[GoogleChat] REMOVED_FROM_SPACE %sÚwidgetÚcardz;[GoogleChat] Card/widget event ack'd (v2 feature, deferred)z([GoogleChat] Error in _on_pubsub_message)rp  Únackrê   rë   r  Údecoder·   r  rª  Úackr  rF   r!   rÖ  rå  r…  r~  Úagent.redactr—  r:  rf  r×  rø   rœ   r�  rÅ  Ú_dispatch_messagerB  rC  )
r7   r—  re  rf  r—  ÚdumpÚmplró  rê  Úprepareds
   &&        r   r’  Ú(GoogleChatAdapter._handle_pubsub_message6  s¯  € Ø××ÐØ�L‰LŒNÙð	Ü—z’z '§,¡,×"5Ñ"5°gÓ">Ó?ˆHô
 ”w˜w¨°bÓ9×?Ð?¸RÓ@×DÑDÀYÓO×UÐUÐSUˆÜ�‰Ð@Ä$ÀxÇ}Á}ÃÓBWÐY`ÔaØ�?�?ˆ?ð5Ý>Ù,¬T¯ZªZ¸Ó-AÓB�ô �L‰LÐCÀTÈ%Å[ÔQð	Ø˜wÔ&¨,¸'Õ*AØ—|‘| FÓ+×1Ð1¨r×6Ñ6Ð7JÓK×QÐQÈr�ØŸ™ Ó(×.Ð.¨B�Ø Ô'à!Ÿg™g lÓ3×9Ð9°r×>Ñ>¸xÓH×NÐNÈB�FØ—z‘z &Ó)¨UÔ2¸4×;L×;LÐ;LÐQW×Q[ÑQ[Ð\b×QcÒQcØ,2°6­N˜Ô)Ø×0Ñ0°¸µÔ@Ü—K‘KÐ @À%Ç)Á)ÈFÐTWÓBXÕYä—K‘KÐ DÀeÇiÁiÐPVÐX[ÓF\Õ]Ø˜WÔ$¨°'·-±-³/Ô(AÜ—‘ÐYÕZà×0Ñ0°ÓC�ØÒ'Ø×(Ñ(¨×)?Ò)?ÀÑ)JÔKØ�K‰KŽMøôC ô 	Ü×ÑÐLÔMØ�K‰KŒMÚð	ûô ô 5Ø4“ð5ûô. ô 	Ü×ÑÐGÔHÜ×$Ò$¤Y×/Õ/Ø—‘”÷ 0×/×/Ô/úð	úsy   ¦/K Ã"L
 Ä&L Ä6L ÅL Å*!L ÆL Æ%*L ÇL Ç'C*L Ë0LÌLÌ
LÌLÌANÍ M<Í1NÍ<NÎNÎNc               ó    € V ^8„  d   QhRRRR/# )r   re  rd   r   r   )r   s   "r   r   rN  c  s   € ÷ ñ °.ð À^ñ r   c              ƒ  	ó(  "  € ^ RI HpHp V P                  V4      pVf   / # V! 4       ;_uu_ 4       pV P                  ! V!  G Rj  x€L
  RRR4       XP
                  '       d   V P                  ! V!   V! 4       h/ #  L7  + '       g   i     L=; i5i)r@   )ÚParkedRouteRefusedÚretryable_ingressN)Úgateway.parked_route_refusalrª  r«  r�  r£  r˜   Ú_release_unadmitted)r7   re  rª  r«  r¦  Úscopes   &&    r   Údispatch_http_eventÚ%GoogleChatAdapter.dispatch_http_eventc  s{   é € ßVØ×(Ñ(¨Ó2ˆØÒØˆIñ × Ô  EØ×(Ò(¨(Ñ3×3Ð3÷ !à�=�=ˆ=Ø×$Ò$ hÒ/Ù$Ó&Ð&Øˆ	ñ	 4÷ !× üs4   ‚/B±A?ÁA=ÁA?Á
BÁ$BÁ=A?Á?B	Â
Bc               ó$   € V ^8„  d   QhRRRRRR/# ©r   rþ  rd   re  r   r-   r   )r   s   "r   r   rN  q  s'   € ÷ Cñ C ~ð CÀð CÐTXñ Cr   c                óÎ  € V P                   P                  VP                  R4      ;'       g    R4       VP                  R4      ;'       g    VP                  R4      ;'       g    / P                  R4      ;'       g    RpVP                  R4      ;'       g    / P                  R4      ;'       g    RpV'       d(   V'       d   V P                  P	                  W44       R# R# R# )z¯Undo what ingress recorded for a delivery that was not admitted (its dedup claim and DM
thread count), so the platform's redelivery is admitted and read as the first delivery.rq   r¯   ró  rA  N)ro  Údiscardr!   rv  r*  )r7   rþ  re  r{  r  s   &&&  r   r­  Ú%GoogleChatAdapter._release_unadmittedq  sª   € ð 	�‰×Ñ˜CŸG™G F›O×1Ð1¨rÔ2Ø—l‘l 7Ó+×EÐE¨s¯w©w°wÓ/?×EÐEÀ2×JÑJÈ6ÓR×XÐXÐVXˆ
Ø—w‘w˜xÓ(×.Ð.¨B×3Ñ3°FÓ;×AÐA¸rˆßŸ+Ø×$Ñ$×)Ñ)¨*ÖBñ &‰:r   c               ó    € V ^8„  d   QhRRRR/# )r   Úauth_headerr<   r   ztuple[bool, str]r   )r   s   "r   r   rN  z  s   € ÷ ñ °Sð Ð=Mñ r   c           	     	óÈ  € V P                   '       d   V P                  '       g   R# VP                  R4      '       d   VR,          P                  4       MRpV'       g   R	#  \	        W P                   4      pT P                  P                  R4       Uu0 uF8  qUP                  4       '       g   K  TP                  4       P                  4       kK:  	  pp\        TP                  R4      ;'       g    R4      P                  4       P                  4       T9  d   R# R#   \
         d5   p\        P                  R\        \        T4      4      4       R
u Rp?# Rp?ii ; iu upi )FúBearer :é   NNr¯   z6[GoogleChat] HTTP event bearer verification failed: %sNr3  rv  )FÚ&google_chat_http_events_not_configured)FÚmissing_google_bearer)FÚinvalid_google_bearer)FÚ!unexpected_google_bearer_identity)Tr¯   )r�  r‚  rÈ   r  ri   r·   r  r  rÃ   r<   rï  rœ   r!   )r7   r·  rb   Úclaimsr_   ÚitemÚexpecteds   &&     r   Úverify_http_event_requestÚ+GoogleChatAdapter.verify_http_event_requestz  s  € Ø×)×)Ð)°×1X×1XÐ1XØBÐBØ+6×+AÑ+AÀ)×+LÒ+L�˜B•×%Ñ%Ô'ÐRTˆßØ1Ð1ð	2Ü,¨U×4NÑ4NÓOˆFð 6:×5\Ñ5\×5bÑ5bÐcfÔ5gÓxÑ5g¨T×kuÑku×kwÔ(�D—J‘J“L×&Ñ&Ö(Ñ5gˆÐxÜˆv�z‰z˜'Ó"×(Ð( bÓ)×/Ñ/Ó1×7Ñ7Ó9ÀÔIØ=Ð=Øˆøô ô 	2Ü�N‰NÐSÔUfÔgjÐknÓgoÓUpÔqØ1Õ1ûð	2üò ys*   Á"D ÂEÂ0"EÄEÄ()EÅEÅEc               ó$   € V ^8„  d   QhRRRRRR/# r²  r   )r   s   "r   r   rN  Š  s'   € ÷ Fñ F¨>ð FÀ^ð FÐX\ñ Fr   c              ƒ  óB  "  €  V P                  W4      G Rj  x€L
 pVf   R# VP                  ;'       g    RP                  4       pVP                  R4      '       dz   VP                  el   T P                  VP                  P                  VP                  P                  TVP                  P                  ;'       g    RR7      G Rj  x€L
 '       d   R# V P                  V4      G Rj  x€L
  R#  LÙ L) L
  \         d    \        P                  R4        R# i ; i5i)z‰Translate a Chat message to a MessageEvent and hand off.
``/setup-files`` is intercepted BEFORE the agent sees it (bot-local OAuth flow).Nr¯   z/setup-files)r  r?  Úraw_textrm  z%[GoogleChat] _dispatch_message failed)Ú_build_message_eventr�   r  rÈ   ÚsourceÚ_handle_setup_files_commandr  r?  Úuser_id_altÚhandle_messager·   r  rª  )r7   rþ  re  Úeventr�   s   &&&  r   r£  Ú#GoogleChatAdapter._dispatch_messageŠ  sô   é € ð	FØ×3Ñ3°CÓB×BˆEØŠ}ÙØ—J‘J×$Ð$ "×+Ñ+Ó-ˆDà�‰˜~×.Ò.°5·<±<Ò3KÐVZ×VvÑVvØŸ™×,Ñ,¸¿¹×8NÑ8NÐY]Ø"Ÿ\™\×5Ñ5×=Ð=¸ð Wwó W÷ Qö Qñ Ø×%Ñ% eÓ,×,Ò,ñ Cñ
Qñ
 -øÜô 	FÜ×ÑÐD×Eð	Füs„   ‚D„C8 ˜C2™C8 ¡D£C8 ¶'C8 ÁA C8 Â?C8 Ã
C4Ã	C8 ÃDÃC8 Ã+C6Ã,C8 Ã0DÃ2C8 Ã4C8 Ã6C8 Ã8 DÄDÄDÄDc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r  r<   r?  rÛ   rÆ  rm  r   r   r   )r   s   "r   r   rN  œ  s9   € ÷ bñ b¸ð bÈð bÐbeð bØ8EðbØQUñbr   c              ƒ  ó>   "  € ^RI Hp V! WW#V4      G Rj  x€L
 #  L5i)zIIn-chat OAuth setup flow; see ``setup_files.handle_setup_files_command``.)Úhandle_setup_files_commandN)Úsetup_filesrÐ  )r7   r  r?  rÆ  rm  rÐ  s   &&&&& r   rÉ  Ú-GoogleChatAdapter._handle_setup_files_commandœ  s    é € õ 	<Ù/°¸yÐT`Óa×aÐaÑaùs   ‚–—c               ó$   € V ^8„  d   QhRRRRRR/# )r   rþ  rd   re  r   zOptional[MessageEvent]r   )r   s   "r   r   rN  ¢  s'   € ÷ D
ñ D
¨nð D
Èð D
Ð[qñ D
r   c              ƒ  ó*	  "  € VP                  R4      ;'       g    VP                  R4      ;'       g    / pVP                  R4      ;'       g    RpVP                  R4      ;'       g    VP                  R4      ;'       g    RP                  4       pVP                  R4      ;'       g    / P                  R4      ;'       g    RpVP                  R4      ;'       g    / pVP                  R4      ;'       g    RpVP                  R	4      ;'       g    Rp	V	'       d4   V'       d,   V	P                  4       P                  4       V P                  V&   VR9   d   R
MRp
VP                  R4      ;'       g    VP                  R4      ;'       g    RP                  4       pVP                  R4      ;'       g    / pV'       dZ   \        VP                  R4      ;'       g    R4      pV'       d.   VP                  R4      '       g   RV RV 2P                  4       p. p. p\        P                  pVP                  R4      ;'       g    .  FŒ  p V P                  V4      G Rj  x€L
 w  ppT'       g   K*  TP                  T4       TP                  T;'       g    R4       T\        P                  8X  g   Km  T'       d   Kw  \        T;'       g    R4      pKŽ  	  V'       d   \        P                  pV'       d$   V'       d   V P                   P#                  WF4      M^ pV
R
8X  d^   V^ 8„  pV'       d   TMRpV'       d    V'       d   V'       d   W`P$                  V&   MEV'       d   V P$                  P'                  VR4       M TpV'       d   V'       d   W`P$                  V&   T P)                  YCP                  R4      ;'       g    VP                  R4      ;'       g    RT
T	;'       g    TVP                  R4      ;'       g    T	;'       g    TTT;'       g    RVP                  R4      ;'       g    RR7      p\+        TTTYP                  R4      ;'       g    RWïR7      #  EL  \         d    \        P                  R4        EKC  i ; i5i)z4Parse a Chat API message into a hermes MessageEvent.ró  rq   r¯   rë  r|  rA  Nrq  rv  Údmr¡  rz  r�   ÚslashCommandÚ	commandIdÚ/z/cmd_Ú Ú
attachmentz'[GoogleChat] attachment download failedúapplication/octet-streamrw  )r  Ú	chat_nameÚ	chat_typeÚuser_idÚ	user_namer?  rÊ  Ú
message_id)r�   rË   rÈ  Úraw_messagerà  Ú
media_urlsÚmedia_types>   ÚDMÚDIRECT_MESSAGE)r!   rC   r  rœ   rn  r<   rÈ   r‚   ÚTEXTÚ_download_attachmentr·   r  rª  r©   rÌ   ÚCOMMANDrv  r&  rt  ÚpopÚbuild_sourcer�   )r7   rþ  re  ró  r{  r}  r  rq  Úsender_namerm  rÝ  r�   ÚslashÚ
command_idrâ  rã  rË   ÚattÚ
local_pathrÅ   Úprev_thread_countÚis_side_threadÚsession_thread_idrÈ  s   &&&                     r   rÇ  Ú&GoogleChatAdapter._build_message_event¢  sÁ  é € à—‘˜WÓ%×?Ð?¨¯©°Ó)9×?Ð?¸RˆØ—Y‘Y˜vÓ&×,Ð,¨"ˆ
Ø—i‘i Ó'×GÐG¨5¯9©9°[Ó+A×GÐGÀR×NÑNÓPˆ
Ø—w‘w˜xÓ(×.Ð.¨B×3Ñ3°FÓ;×CÐC¸tˆØ—‘˜Ó"×(Ð( bˆØ—j‘j Ó(×.Ð.¨BˆØ—z‘z 'Ó*×0Ð0¨bˆ÷ ŸJØ4@×4FÑ4FÓ4H×4NÑ4NÓ4PˆD×%Ñ% jÑ1Ø&Ð*BÔB‘DÈˆ	Ø—‘˜Ó'×@Ð@¨3¯7©7°6«?×@Ð@¸b×GÑGÓIˆà—‘˜Ó'×-Ð-¨2ˆßÜ˜UŸY™Y {Ó3×9Ð9°rÓ:ˆJß $§/¡/°#×"6Ò"6Ø˜z˜l¨!¨D¨6Ð2×8Ñ8Ó:�à "ˆ
Ø!#ˆÜ"×'Ñ'ˆØ—7‘7˜<Ó(×.Ð.¨BÒ.ˆCðØ)-×)BÑ)BÀ3Ó)G×#GÑ �
˜D÷ ÙØ×Ñ˜jÔ)Ø×Ñ˜t×AÐAÐ'AÔBàœ{×/Ñ/Ö/¿¹Ü5°d·j°j¸bÓA’ñ /÷ Ü&×.Ñ.ˆL÷ Wb×fp˜D×4Ñ4×9Ñ9¸*ÔRÐvwÐð ˜ÔØ.°Ñ2ˆNß/=¡À4ÐçŸz¯nØ8C×)Ñ)¨*Ò5ßØ×)Ñ)×-Ñ-¨j¸$Ô?øà +ÐßŸzØ8C×)Ñ)¨*Ñ5Ø×"Ñ"Ø¯)©)°MÓ*B×*]Ð*]ÀeÇiÁiÐPVÓFW×*]Ð*]Ð[]Ðirð "×0Ð0 [¸V¿Z¹ZÈÓ=V×=uÐ=uÐZf×=uÐ=uÐjuØ'°k×6IÐ6IÀTÐWZ×W^ÑW^Ð_eÓWf×WnÐWnÐjnð #ó 
ˆô Ø L¸ÈS×]dÑ]dÐekÓ]l×]tÐ]tÐptØ!ô
ð 	
òM $HøÜô Ü× Ñ Ð!JÔKÛðüs8  ‚1R´RÁRÁ*RÂ(RÂ,RÃRÃ RÃ;RÄ
RÄ!RÄ)ARÅ7RÆ(RÆ9
RÇRÇ!RÇ0RÈARÉ	RÉQ+É$Q(É%Q+É,RÉ4&RÊRÊ9RËRËRË$RË<RÌ0RÌ5RÍRÍ	RÍRÍ(&RÎRÎ0RÏRÏ!RÏ-RÐ	RÐRÐRÐ7'RÑ	RÑ(Q+Ñ+ RÒRÒRÒRc               ó    € V ^8„  d   QhRRRR/# )r   rÚ  rd   r   z#tuple[Optional[str], Optional[str]]r   )r   s   "r   r   rN  è  s   € ÷ 9Kñ 9K°^ð 9KÐHkñ 9Kr   c           	   ƒ  óV  a aa"  € VP                  R4      ;'       g    RpVP                  R4      ;'       g    RpVP                  R4      ;'       g    / P                  R4      ;'       g    RoVP                  R4      ;'       g    RoVP                  R4      ;'       g    RR8X  d"   S'       g   \        P                  R	4       R
V3# R
pS'       d*   R VV 3R llp \        P                  ! V4      G R
j  x€L
 pVf\   S'       dT   \        S4      '       g   \        P                  R4       R
V3# R VV 3R llp \        P                  ! V4      G R
j  x€L
 pVf   R
V3# V'       d   VP                  R4      R,          MRpRV9   d/   RVP                  R^4      R,          P                  4       ,           MRp	\         F<  w  r«pVP                  V
4      '       g   K  T! YI;'       g    TR7      G R
j  x€L
 V3u # 	  \!        WH4      G R
j  x€L
 V3#  EL   \
         d4   p\        P                  R\        \        T4      4      4        R
p?ELWR
p?ii ; i EL  \         d7   p\        P                  R\        \        T4      4      4       R
T3u R
p?# R
p?ii ; i Lª L“5i)zýDownload an inbound attachment to the local cache; return (path, mime). Bot SA
path is ``media.download`` via ``attachmentDataRef.resourceName``; Drive-picker shares
without one need user OAuth (skipped); ``downloadUri`` is a last resort (usually 401s).ÚcontentTyper¯   rq   ÚattachmentDataRefÚresourceNameÚdownloadUrirÈ  Ú
DRIVE_FILEzb[GoogleChat] Skipping Drive-picker attachment (no resourceName, would need user-OAuth Drive scope)Nc               ó   € V ^8„  d   QhRR/# ©r   r   Úbytesr   )r   s   "r   r   Ú<GoogleChatAdapter._download_attachment.<locals>.__annotate__ø  s   € ÷ 	&ñ 	& %ñ 	&r   c                 óö   <€ SP                   P                  4       P                  SR 7      p ^ RIHp ^ RIpVP                  4       pV! W04      RrTV'       g   VP                  4       w  reK  VP                  4       # ))rø  )ÚMediaIoBaseDownloadNF)	ra  ÚmediaÚdownload_mediaÚgoogleapiclient.httpr   ÚioÚBytesIOÚ
next_chunkÚgetvalue)	Úreqr   r  ÚbufÚ
downloaderr@  Ú_statusÚresource_namer7   s	          €€r   Ú_fetch_mediaÚ<GoogleChatAdapter._download_attachment.<locals>._fetch_mediaø  sa   ø€ Ø—n‘n×*Ñ*Ó,×;Ñ;ÈÐ;ÓW�ÝDÛà—j‘j“l�Ù#6°sÓ#@À%˜DßØ$.×$9Ñ$9Ó$;‘M�G™TØ—|‘|“~Ð%r   z,[GoogleChat] media.download_media failed: %sz8[GoogleChat] Rejecting attachment fetch: non-Google hostc               ó   € V ^8„  d   QhRR/# rü  r   )r   s   "r   r   rþ    s   € ÷ $ñ $ ñ $r   c                 ó¬   <€ ^ RI Hu Hu Hp  V P	                  SP
                  4      P                  S^R7      pVP                  4        VP                  # )r@   Nr=  )	Úgoogle.auth.transport.requestsrö   Ú	transportrW   ÚAuthorizedSessionrb  r!   Úraise_for_statusÚcontent)Úgarrˆ   Údownload_urir7   s     €€r   Ú
_fetch_uriÚ:GoogleChatAdapter._download_attachment.<locals>._fetch_uri  sF   ø€ ß<Ó<à×,Ñ,¨T×->Ñ->Ó?×CÑCÀLÐZ\ÐCÓ]�Ø×%Ñ%Ô'Ø—|‘|Ð#r   zx[GoogleChat] downloadUri fetch failed (SA tokens often lack access here; this is expected for user-uploaded content): %srØ  rÚ  r²   )Úextéÿÿÿÿ)r!   r  rø   rð  rñ  r$   r  rÃ   r<   r¼   r·   rï  Úrsplitrœ   Ú_MEDIA_CACHERSrÈ   r~   )r7   rÚ  rÅ   rq   r  r  r_   r  Úfilenamer  rÊ   Úcache_fnÚdefault_extr  r  s   f&           @@r   rç  Ú&GoogleChatAdapter._download_attachmentè  s?  úé € ð �~‰~˜mÓ,×2Ð2°ˆØ�~‰~˜fÓ%×+Ð+¨ˆØ#Ÿ™Ð(;Ó<×BÐBÀ×GÑGÈÓW×]Ð]Ð[]ˆØ!—~‘~ mÓ4×:Ð:¸ˆð �N‰N˜8Ó$×*Ð*¨¨|Ô;ÇMÜ�K‰KÐ|Ô}Ø˜�:Ðà $ˆß÷	&ñ 	&ðlÜ$×.Ò.¨|Ó<×<�ð Š<ŸLÜ(¨×6Ò6Ü—‘ÐYÔZØ˜T�zÐ!÷$ñ $ð"Ü$×.Ò.¨zÓ:×:�ð Š<Ø˜�:Ðç*.�4—:‘:˜c“? 2Ö&°LˆØ;>À(¼?ˆc�H—O‘O C¨Ó+¨BÕ/×5Ñ5Ó7Ö7ÐPRˆß-;Ñ)ˆF˜kØ�‰˜v×&Ô&Ù% d×0BÐ0B°{ÔC×CÀTÐIÒIñ .<ô 5°TÓD×DÀdÐJÐJò= =øÜô lÜ—‘ÐMÔO`ÔadÐehÓaiÓOj×kÒkûðlúò ;øÜô "Ü—‘ð1Ü2CÄCÈÃHÓ2Môð ˜T�zÕ!ûð"úñ DÙDùsã   …3J)¹J)ÁJ)Á-J)ÂJ)Â#J)Â3"J)Ã
J)Ã!H Ã:HÃ;H Ã?J)Ä4J)Å I! ÅIÅI! ÅJ)Å.A1J)Ç$
J)Ç/J)Ç:J%Ç;J)ÈJ'ÈJ)ÈH ÈIÈ((IÉJ)ÉIÉJ)ÉI! É!J"É,+JÊJ"ÊJ)ÊJ"Ê"J)Ê'J)c               ó    € V ^8„  d   QhRRRR/# )r   r  r<   r   r,   r   )r   s   "r   r   rN  $  s   € ÷ .ñ .¨ð .°ñ .r   c                	óˆ   € V P                   P                  V^ 4      ^,           V P                   V&   V P                   V,          # r  )rs  r!   ©r7   r  s   &&r   Ú_note_rate_limitÚ"GoogleChatAdapter._note_rate_limit$  s<   € Ø)-×)>Ñ)>×)BÑ)BÀ7ÈAÓ)NÐQRÕ)Rˆ×Ñ˜gÑ&Ø×$Ñ$ WÕ-Ð-r   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   r  r<   r  Úreply_torÛ   ÚmetadataúOptional[dict[str, Any]]r   r|   r   )r   s   "r   r   rN  (  s1   € ÷ 81ñ 81 #ð 81°ð 81¸}ð 81Ø5ð81ØAKñ81r   c              ƒ  óN  "  € V P                  W4VR7      pV P                  V4        V P                  V P                  V4      4      pV'       g   \	        RRR7      V P                  V4       # RpV P                  P                  VR4      pV\        8X  d   RpRp	\        V4       Fg  w  r«\        Yº^ 8”  g	   V'       g   TMR4      p V
^ 8X  d&   V'       d   V P                  WŒ4      G Rj  x€L
 pRp	KN  V P                  W4      G Rj  x€L
 pKi  	  Vf   \	        RRR7      V P                  V4       # V	'       d   \        V P                  V&   VV P                  V4       #  Lu LZ  \         Ed   p\        T4      pTR8X  dC   T P                  RR	RR
7       \	        R\!        T4      R7      u Rp?u T P                  T4       # TR8X  d‚   T
^ 8X  dA   T'       d9   \"        P%                  R4       RpT P                  Y4      G Rj  x€L 
 p Rp?EKm  \"        P%                  R4       \	        RRR7      u Rp?u T P                  T4       # TR8X  d3   T P'                  T4      pT\(        8¼  d   \"        P+                  RT4       h Rp?ii ; i  T P                  T4       i ; i5i)zôSend a text message; ``metadata`` may carry ``thread_id``. A tracked typing card is
patched in place (delete would leave a "Message deleted" tombstone) with the first
chunk, further chunks are new messages; ``_keep_typing`` is paused meanwhile.©r  Fzempty message©Úsuccessrü  NTé“  Úchat_forbiddenz6Bot lacks access (removed from space or perms revoked)rû  é”  z:[GoogleChat] Typing card disappeared; creating new messagez&[GoogleChat] send target 404; skippingztarget not foundé­  z8[GoogleChat] Rate limit hit %d times on chat; throttling)Ú_resolve_thread_idÚpause_typing_for_chatÚ_chunk_textr   r|   Úresume_typing_for_chatrq  ré  Ú_TYPING_CONSUMED_SENTINELÚ	enumeraterC  Ú_patch_messageÚ_create_messager$   rŠ   rý  r<   r  rø   r%  Ú_RATE_LIMIT_WARN_THRESHOLDr  )r7   r  r  r(  r)  r?  ÚchunksÚlast_resultÚtyping_msg_nameÚpatched_typingÚidxÚchunkrB  r_   rB   Úhitss   &&&&&           r   ÚsendÚGoogleChatAdapter.send(  s\  é € ð
 ×+Ñ+¨HÈÐ+ÓPˆ	Ø×"Ñ" 7Ô+ð1	1à×%Ñ% d×&9Ñ&9¸'Ó&BÓCˆFßÜ!¨%°ÔGðZ ×'Ñ'¨Õ0ðY 15ˆKØ"×3Ñ3×7Ñ7¸ÀÓFˆOØÔ";Ô;Ø"&�Ø"ˆNÜ'¨Ö/‘
�ä# E¸q¼Ï©9Ð^bÓc�ðØ˜a”x§OØ,0×,?Ñ,?ÀÓ,V×&V˜Ø)-šà,0×,@Ñ,@ÀÓ,O×&Ošñ 0ð> Ò"Ü!¨%°ÔGð ×'Ñ'¨Õ0÷	 Ü1J�×%Ñ% gÑ.Øà×'Ñ'¨Õ0ñE 'Wñ 'PøÜ õ Ü)¨#Ó.�FØ ”}Ø×-Ñ-Ø!1Ð;sØ&+ð .ô ô  *°%¼sÀ3»xÔHÖHð. ×'Ñ'¨Õ0ð-  ”}à !œ8¯Ü"ŸK™KÐ(dÔeØ.2˜OØ04×0DÑ0DÀWÓ0S×*SÐ*S˜KÞ$ÜŸ™Ð$LÔMÜ)°%Ð?QÔRÖRð ×'Ñ'¨Õ0ð  ”}Ø#×4Ñ4°WÓ=˜ØÔ#=Ô=Ü"ŸN™NÐ+eÐgkÔlØûð+ûð< ×'Ñ'¨Õ0üsé   ‚%J%¨4J ÁJ%Á.AJ Â?J ÃE%ÃE%Ã+E!Ã,E%Ã2J Ã4E%ÄE#Ä	E%ÄJ Ä!J%Ä3J Ä;J ÅJ%Å!E%Å#E%Å%JÅ1;JÆ,JÆ-J Æ3J%ÇJÇ+JÈH	ÈJÈJ È!JÈ4JÈ5J È;J%É:JÊJÊJ ÊJ"Ê"J%c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r  r<   rž  rd   r)  r*  r   r|   r   )r   s   "r   r   rN  b  s0   € ÷ tñ t sð t°.ð tÐLdð tÐpzñ tr   c           	   ƒ  	ó  "  € R V./pV P                  RW1R7      pV'       d   RV/VR&    V P                  W4      G Rj  x€L
 pVP                  ;'       g    R VR ,          /Vn        V#  L*  \         d;   p\	        R\        \        T4      4      \        T4      \        9   R7      u Rp?# Rp?i\         dK   p\        P                  RRR	7       \	        R\        \        T4      4      \        T4      R7      u Rp?# Rp?ii ; i5i)
ÚcardsV2Nr,  rq   rA  F)r.  rü  rù  z[GoogleChat] send_card failedTrÔ  )r3  r:  Úraw_responser$   r|   rÃ   r<   rŠ   r›   r·   r  rÖ  rŸ   )r7   r  rž  r)  rB  r?  r©  r_   s   &&&&    r   Ú	send_cardÚGoogleChatAdapter.send_cardb  só   é € Ø )¨D¨6Ð2ˆØ×+Ñ+¨D°(Ð+ÓLˆ	ßØ$ iÐ0ˆD�‰Nð		tØ×/Ñ/°Ó>×>ˆFØ"(×"5Ñ"5×"UÐ"U¸)ÀTÈ)Å_Ð9UˆFÔØˆMñ ?øô ô 	{ÜØÔ%6´s¸3³xÓ%@ÌLÐY\ÓL]ÔayÑLyô{õ {ûäô 	tÜ�L‰LÐ8À4ˆLÔHÜ eÔ3DÄSÈÃXÓ3NÔZmÐnqÓZrÔsÕsûð	tüsi   ‚(D«A, ¿A*Á A, ÁA, Á)DÁ*A, Á,DÁ7/B,Â&DÂ'DÂ,DÂ9DÂ:?C?Ã9DÃ:DÃ?DÄDc               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r   r  r<   ÚquestionÚchoiceszOptional[list]Ú
clarify_idÚsession_keyr)  r*  r   r|   r   )r   s   "r   r   rN  r  sO   € ÷ iñ iØðiØ&)ðiØ4BðiØPSðiØbeðià*ðið 
ñir   c              ƒ  	óœ  <a"  € V'       g   \         SV `  WVSWV4      G R j  x€L
 # R V3R llp. pV F^  p	\        V	4      P                  4       p
V
'       g   K&  TP	                  T! \        V
4      ^P8:  d   T
MV
R,          R,           V
4      4       K`  	  VP	                  V! \        R4      R4      4       \        RRS 2R	R
\        R4      /RRRRR\        RVR7      /RRRV/././4      pV P                  WVR7      G R j  x€L
 pVP                  '       d   WPP                  S&   V# \         SV `  WVSWV4      G R j  x€L
 #  EL# LC L	5i)Nc               ó$   € V ^8„  d   QhRRRRRR/# )r   r�   r<   Úchoicer   rd   r   )r   s   "r   r   Ú4GoogleChatAdapter.send_clarify.<locals>.__annotate__y  s&   € ÷ 	zñ 	z˜#ð 	z sð 	z¨~ñ 	zr   c           	     ó   <€ R V RRRRSRV//# )r�   ÚactionÚhermes_clarifyÚ
parametersrN  rR  r   )r�   rR  rN  s   &&€r   Ú_buttonÚ/GoogleChatAdapter.send_clarify.<locals>._buttony  s#   ø€ Ø˜D (Ð,<¸lÈ\Ð[eÐgoÐqwÐLxÐyÐyr   :NéM   Nz...z)platform.google_chat.clarify.other_buttonÚ	__other__Úcard_idzclarify-ÚheaderÚtitlez#platform.google_chat.clarify.headerÚsectionsÚwidgetsrë  r�   z%platform.google_chat.clarify.question)rL  Úbuttons)r)  )rÔ   Úsend_clarifyr<   r  r©   r  r   r   rI  r.  rr  )r7   r  rL  rM  rN  rO  r)  rX  ra  rR  Úchoice_textrž  r©  rÕ   s   &&&&f&&      €r   rb  ÚGoogleChatAdapter.send_clarifyr  sa  ùé € ÷ Ü™Ñ-¨gÀÈ*ÐVaÓl×lÐl÷	zð 	zà(*ˆÛˆFÜ˜f›+×+Ñ+Ó-ˆKß‰{Ø—‘™w´c¸+Ó6FÈ"Ô6L¡{ÐR]Ð^aÕRbÐejÕRjÐlwÓxÖyñ ð 	�‰‘wœqÐ!LÓMÈ{Ó[Ô\Ü$Ø˜ * Ð.°¸7ÄAÐFkÓDlÐ:mØ˜) v¨v°v¼qÐAhÐs{Ô?|Ð&}Ø'-¨y¸)ÀWÐ&Mð&Oð Pð Qð&
ó ˆð
 —~‘~ g¸h�~ÓG×GˆØ�>�>ˆ>Ø.9×Ñ 
Ñ+ØˆMÜ‘WÑ)¨'¸WÀjÐR]Óh×hÐhò' mñ Hñ iùs@   „E¢E£2EÁB*EÄEÄEÄ%EÅ E
ÅEÅEÅ
EÚfinalizec          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r  r<   rà  r  re  r   r   r|   r   )r   s   "r   r   rN  Œ  s1   € ÷ =ñ =¨#ð =¸3ð =Èð =Ð[_ð =Ðlvñ =r   c          	   ƒ  óø  "  € V'       g   \        RRR7      # \        V4      \        8”  d   VR\        ^,
           R,           p V P                  VRV/4      G Rj  x€L
 #  L  \         dK   p\        T4      R8X  d   T P                  T4       \        R\        \        T4      4      R7      u Rp?# Rp?i\         d8   p\        P                  RR	R
7       \        R\        T4      R7      u Rp?# Rp?ii ; i5i)zÙEdit via ``messages.patch`` (required by the tool-progress / token-streaming
pipeline). ``finalize`` is unused: Chat's patch has no streaming lifecycle.
404/403 are non-success so the gateway falls back to ``send()``.Fzmissing message_idr-  Nu   â€¦r�   r2  z [GoogleChat] edit_message failedTrÔ  )r|   r  Ú_MAX_TEXT_LENGTHr9  r$   rŠ   r%  rÃ   r<   r·   r  rÖ  )r7   r  rà  r  re  r_   s   &&&&$ r   Úedit_messageÚGoogleChatAdapter.edit_messageŒ  sÍ   é € ÷ Ü eÐ3GÔHÐHÜˆw‹<Ô*Ô*ØÐ4Ô 0°1Õ 4Ð5¸Õ=ˆGð	=Ø×,Ñ,¨Z¸&À'Ð9JÓK×KÐKÑKøÜô 	PÜ˜CÓ  CÔ'Ø×%Ñ% gÔ.Ü eÔ3DÄSÈÃXÓ3NÔOÕOûÜô 	=Ü�L‰LÐ;ÀdˆLÔKÜ e´3°s³8Ô<Õ<ûð	=üsf   ‚AC:ÁA" ÁA ÁA" ÁC:Á A" Á"C7Á-?B2Â,C7Â-C:Â2C7Â?C7Ã ,C2Ã,C7Ã-C:Ã2C7Ã7C:c               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   rà  r   r   r   )r   s   "r   r   rN  ž  s!   € ÷ ñ ¨Cð ¸Sð ÀTñ r   c           	   ƒ  ó\  a a"  € S'       g   R#  \         P                  ! VV 3R l4      G Rj  x€L
  R#  L  \         dD   p\        T4      R9  d)   \        P                  R\        \        T4      4      4        Rp?R# Rp?i\         d    \        P                  RRR7        R# i ; i5i)	u“   Delete a message. Prefer ``edit_message`` â€” deletion leaves a "Message
deleted by its author" tombstone; kept for stream-consumer fallback paths.Fc                 ó°   <€ SP                   P                  4       P                  4       P                  S R 7      P	                  SP                  4       R7      # ©)rq   rá  )ra  rã  ÚmessagesÚdeleteræ  rç  )rà  r7   s   €€r   r²  Ú2GoogleChatAdapter.delete_message.<locals>.<lambda>¦  sA   ø€ ˜Ÿ™×-Ñ-Ó/×8Ñ8Ó:×AÑAÀzÐAÓR×ZÑZÐ`d×`uÑ`uÓ`wÐZÔxr   NTz&[GoogleChat] delete_message failed: %sz"[GoogleChat] delete_message failedrÔ  >   r/  r1  )	rð  rñ  r$   rŠ   r  rÖ  rÃ   r<   r·   )r7   r  rà  r_   s   f&f r   Údelete_messageÚ GoogleChatAdapter.delete_messagež  sœ   ùé € ÷ Ùð	NÜ×#Ò#Ýxóz÷ zð záñzøô ô 	dÜ˜CÓ ¨
Ô2Ü—‘ÐEÔGXÔY\Ð]`ÓYaÓGbÔcûñ ûô ô 	NÜ�L‰LÐ=ÈˆLÕMÙð	NüsI   „B,�7 ®5¯7 ³B,µ7 ·B)Á8B Á:B,Â B)ÂB)Â%B,Â(B)Â)B,c               ó$   € V ^8„  d   QhRRRRRR/# )r   rp  r<   rB  rd   r   r|   r   )r   s   "r   r   rN  ¯  s&   € ÷ Sñ S°ð S¸Nð SÈzñ Sr   c              ƒ  óL  a aaaa"  € RP                  V3R lR
 4       4      ;'       g    RoSP                  4        UUu/ uF  w  r4VR8w  g   K  W4bK  	  uppo\        P                  ! VVV V3R l4      G Rj  x€L
 p\	        RVP                  RS4      R	7      # u uppi  L'5i)z8Update a message's text (and optionally cards) in-place.r3  c              3  ó8   <"  € T F  qS9   g   K  Vx € K  	  R # 5ir0   r   )rŽ   ÚkrB  s   & €r   r‘   Ú3GoogleChatAdapter._patch_message.<locals>.<genexpr>±  s   øé € ÐKÑ*= QÀdÁŸqšqÓ*=ùs   ƒ�
r�   rA  c                 ó´   <€ SP                   P                  4       P                  4       P                  S SSR 7      P	                  SP                  4       R7      # ))rq   Ú
updateMaskrB  rá  )ra  rã  ro  Úpatchræ  rç  )rp  Ú
patch_bodyr7   Úupdate_masks   €€€€r   r²  Ú2GoogleChatAdapter._patch_message.<locals>.<lambda>´  sI   ø€ �D—N‘N×)Ñ)Ó+×4Ñ4Ó6×<Ñ<À,Ð[fÐmwÐ<Óxß‰W˜$×/Ñ/Ó1ˆWÓ2ð3r   NTrq   ©r.  rà  )r�   rG  )r  r  rð  rñ  r|   r!   )r7   rp  rB  rw  Úvrˆ   r|  r}  s   fff   @@r   r9  Ú GoogleChatAdapter._patch_message¯  sˆ   üé € à—h‘hÔKÑ*=ÓKÓK×UÐUÈvˆØ'+§z¡z¤|ÔE¡|™t˜q°q¸H±}”d�a’d¡|ÒEˆ
Ü×&Ò&÷3ó
÷ 
ˆô  $°4·8±8¸FÀLÓ3QÔRÐRùó Fñ
ùs#   ‡9B$Á BÁBÁ$B$Á:B"Á;(B$c               ó    € V ^8„  d   QhRRRR/# )r   r�   r<   r   z	list[str]r   )r   s   "r   r   rN  ¹  s   € ÷ ñ  ð ¨	ñ r   c                	ó  € . pTpV'       d€   \        V4      \        8:  d   VP                  V4        V# VP                  R ^ \        4      pV\        ^,          8  d   \        pVP                  VRV 4       W4R P	                  4       pK‡  V# )Ú
N)r  rh  r©   Úrfindré   )r7   r�   r<  Ú	remainingÚcuts   &&   r   r5  ÚGoogleChatAdapter._chunk_text¹  sƒ   € ØˆØˆ	ßÜ�9‹~Ô!1Ô1Ø—‘˜iÔ(Øð ˆð —/‘/ $¨Ô+;Ó<ˆCØÔ%¨Õ*Ô*Ü&�Ø�M‰M˜) D S˜/Ô*Ø! $˜×.Ñ.Ó0ŠIØˆr   c               ó    € V ^8„  d   QhRRRR/# )r   r  r<   r   r   )r   s   "r   r   rN  É  s   € ÷ (ñ ( Sð (¨Sñ (r   c                ó   € \        V4      # )zsConvert standard Markdown to Google Chat's dialect (see ``cards.format_message``).

Pattern lifted from PR #14965.
)Ú_format_message)Úclsr  s   &&r   r   Ú GoogleChatAdapter.format_messageÈ  s   € ô ˜wÓ'Ð'r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r(  rÛ   r)  r*  r  r   r   )r   s   "r   r   rN  Ð  s1   € ÷ Uñ U¨=ð UÐD\ð UØ$1ðUØ=JñUr   c                óH  € V'       d4   R F-  pVP                  V4      '       g   K  \        W$,          4      u # 	  V'       d   RV9   d
   RV9  d   V# V'       d   VP                  R4      '       d   R# V'       d&   V P                  P                  V4      ;'       g    R# R# )uT  Thread to reply under, or None: ``metadata['thread_id']`` â†’ ``thread_name`` /
``thread_ts`` aliases â†’ ``reply_to`` when already a ``spaces/X/threads/Y`` name â†’
``_last_inbound_thread[chat_id]`` (else DM replies land top-level). Cron deliveries
(``job_id`` in metadata) skip the last fallback so output is not buried in a stale thread.z	/threads/z
/messages/Újob_idN)r?  r  Ú	thread_ts)r!   r<   rt  )r7   r(  r)  r  r†  s   &&&& r   r3  Ú$GoogleChatAdapter._resolve_thread_idÐ  s�   € ÷ Û@�Ø—<‘< ×$Ô$Ü˜x�}Ó-Ò-ñ A÷ ˜ xÔ/°LÈÔ4PØˆOß˜Ÿ™ X×.Ò.ÙßCJ�×)Ñ)×-Ñ-¨gÓ6×>Ð>¸$ÐTÐPTÐTr   c               ó   € V ^8„  d   QhRR/# rU   r   )r   s   "r   r   rN  à  s   € ÷ Qñ Q #ñ Qr   c                óX   € \        V P                  \        P                  ^R7      R7      # )zŠFresh AuthorizedHttp per call: httplib2 shares SSL state, so the discovery
client is not thread-safe across ``asyncio.to_thread`` workers.r=  rá  )ÚAuthorizedHttprb  Úhttplib2ÚHttprÏ  s   &r   rç  Ú"GoogleChatAdapter._new_authed_httpà  s"   € ô ˜d×/Ñ/´h·m±mÈB°mÓ6OÔPÐPr   Úop_namezchat-api-callc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úsync_fnzCallable[[], Any]r™  r<   r   r   r   )r   s   "r   r   rN  å  s#   € ÷ 9ñ 9Ð.?ð 9ÈSð 9Ðgjñ 9r   c             ƒ  ó\  "  € \         p\        ^\        ^,           4       F"  p \        P                  ! V4      G Rj  x€L
 u # 	  R#  L
  \
         dÕ   p\        T4      '       d   T\        8¼  d   h \        Y3\        ,          \        P                  ! 4       ,          ,           \        \        ,           4      p\        P                  RY$\        \        \        T4      4      T4       \        P                  ! T4      G Rj  x€L 
  \        T^,          \        4      p Rp?EK  Rp?ii ; i5i)z·Run ``sync_fn`` in a thread with bounded retry + jittered backoff; only
transient failures are retried, permanent ones bubble up on the first attempt.

Pattern lifted from PR #14965.
Nz<[GoogleChat] %s attempt %d/%d failed (%s); retrying in %.2fs)Ú_RETRY_BASE_DELAYÚrangeÚ_RETRY_MAX_ATTEMPTSrð  rñ  r·   rŸ   rY  Ú_RETRY_JITTERr]  Ú_RETRY_MAX_DELAYr  r  rÃ   r<   r\  )r7   r›  r™  rb  r`  r_   Úwaits   &&$    r   Ú_call_with_retryÚ"GoogleChatAdapter._call_with_retryå  sÔ   é € ô "ˆÜ˜QÔ 3°aÕ 7Ö8ˆGð9Ü$×.Ò.¨wÓ7×7Ò7ó 9á7øÜô 	9Ü*¨3×/Ò/°7Ô>QÔ3QØÜ˜5¬=Õ#8¼6¿=º=»?Õ#JÕJÔL\Ô_lÕLlÓm�Ü—‘ØRØÔ&9Ô;LÌSÐQTËXÓ;VÐX\ôô —m’m DÓ)×)Ñ)Ü˜E A�IÔ'7Ó8—ûð	9üsK   ‚!D,¤A
½A¾A
ÁD,ÁA
Á
D)ÁB+D$Ä DÄD$ÄD,Ä$D)Ä)D,c               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   rˆ   rd   r   r-   r   )r   s   "r   r   rN  ú  s&   € ÷ ^ñ ^¨cð ^¸ð ^ÈDñ ^r   c                ó   € VP                  R4      ;'       g    / P                  R4      ;'       g    RpV'       d)   V'       d    V P                  P                  W4       R# R# R#   \         d    \        P                  RRR7        R# i ; i)z’Count the outbound destination thread so a later user "Reply in thread" on
the bot's message resolves as a known side-thread instead of main flow.rA  rq   r¯   z.[GoogleChat] outbound thread-count incr failedTrÔ  N)r!   rv  r&  r·   r  rÖ  )r7   r  rˆ   Úresp_threads   &&& r   Ú_track_outbound_threadÚ(GoogleChatAdapter._track_outbound_threadú  sx   € ð —x‘x Ó)×/Ð/¨R×4Ñ4°VÓ<×BÐBÀˆß—{ð^Ø×(Ñ(×-Ñ-¨gÖCñ #‰7øô ô ^Ü—‘ÐMÐX\�×]ð^ús   ÁA' Á'"BÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   rB  rd   r   r|   r   )r   s   "r   r   rN    s&   € ÷ Eñ E¨Sð E¸ð EÈ:ñ Er   c              ƒ  óÂ   a a"  € \        W4      oS P                  VV 3R lRR7      G Rj  x€L
 pS P                  W4       \        RVP	                  R4      R7      #  L15i)zIPOST spaces/{space}/messages via REST (with retry), returning SendResult.c                 ó°   <€ SP                   P                  4       P                  4       P                  ! R/ S B P	                  SP                  4       R 7      # )rá  r   )ra  rã  ro  Úcreateræ  rç  )r>   r7   s   €€r   r²  Ú3GoogleChatAdapter._create_message.<locals>.<lambda>  sA   ø€ �D—N‘N×)Ñ)Ó+×4Ñ4Ó6×=Ò=ÑGÀÑG×OÑOÐUY×UjÑUjÓUlÐOÔmr   zmessages.create)r™  NTrq   r  )rH  r£  r¨  r|   r!   )r7   r  rB  rˆ   r>   s   f&& @r   r:  Ú!GoogleChatAdapter._create_message  s[   ùé € ä Ó.ˆØ×*Ñ*ÝmØ%ð +ó 
÷ 
ˆð 	×#Ñ# GÔ2Ü $°4·8±8¸FÓ3CÔDÐDñ
ùs   „'A«A¬2Ac               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   r)  r   r   r-   r   )r   s   "r   r   rN    s&   € ÷ $Hñ $H¨ð $H¸ð $HÀtñ $Hr   c              ƒ  óâ  a aaa"  € SS P                   9   d   R# SS P                  9   d|   \        P                  ! \        P
                  \        4      ;_uu_ 4        \        P                  ! S P                  S,          P                  4       RR7      G Rj  x€L
  RRR4       R# S P                  RVSR7      p\        \        S P                  RR4      ;'       g    \        R4      V4      o\        P                  ! 4       ;S P                  S&   oR VVVV 3R llp\        P                  ! \        P                   ! V! 4       4      4      G Rj  x€L
  R#  L¿  + '       g   i     R# ; i L5i)	uæ  Post a visible 'Hermes is thinkingâ€¦' marker (Chat has no typing API); ``send()``
PATCHes it with the reply, ``on_processing_complete`` reaps it otherwise. Created in
the user's thread (patch cannot move it). ``_keep_typing`` wraps this in
``wait_for(timeout=1.5)``: a cancelled create would still land an unrecorded card and
the next tick would create a second, so the slot is reserved with an in-flight Event
and the create runs in a shielded task that records the msg_id regardless.Nr<  r=  )r(  r)  r  Útyping_status_textz$platform.google_chat.typing.thinkingc               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   Ú3GoogleChatAdapter.send_typing.<locals>.__annotate__!  s   € ÷ 	 ñ 	 ¨$ñ 	 r   c               “  ó\  <"  €  SP                  SS4      G R j  x€L
 p V P                  '       ds   V P                  '       da   SSP                  9  d   V P                  SP                  S&   M5SP                  P                  S. 4      P                  V P                  4       SP                  P                  SR 4       SP                  4        R #  L¶  \         d    \        P                  RRR7        LTi ; i  SP                  P                  SR 4       SP                  4        i ; i5i)Nz1[GoogleChat] send_typing background create failedTrÔ  )r:  r.  rà  rq  rx  r"  r©   r·   r  rÖ  rw  ré  Úset)r©  rB  r  Ú	completedr7   s    €€€€r   Ú_create_and_recordÚ9GoogleChatAdapter.send_typing.<locals>._create_and_record!  sï   øé € ð Ø#×3Ñ3°G¸TÓB×B�Ø—>—>�> f×&7×&7Ð&7Ø d×&;Ñ&;Ô;Ø9?×9JÑ9J˜×-Ñ-¨gÒ6ð ×4Ñ4×?Ñ?ÀÈÓL×SÑSÐTZ×TeÑTeÔfð ×*Ñ*×.Ñ.¨w¸Ô=Ø—‘–ñ Cøô ô aÜ—‘ÐPÐ[_�Ö`ðaûð ×*Ñ*×.Ñ.¨w¸Ô=Ø—‘•üs[   ƒD,…C šC›C ±C Á*C Á-C; Á.5C Â#.D,ÃC Ã"C8Ã5C; Ã7C8Ã8C; Ã;.D)Ä)D,)rq  rw  rB  rC  rð  rE  ÚKeyErrorrF  r¢  r3  rC  rF   rM  r   ÚEventÚshieldr4  )r7   r  r)  r?  r¸  rB  r·  s   ff&  @@r   Úsend_typingÚGoogleChatAdapter.send_typing  s  ûé € ð �d×+Ñ+Ô+ÙØ�d×0Ñ0Ô0ä×$Ò$¤W×%9Ñ%9¼8×DÕDÜ×&Ò& t×'AÑ'AÀ'Õ'J×'OÑ'OÓ'QÐ[^Ô_×_Ð_÷ EáØ×+Ñ+°TÀHÐV]Ð+Ó^ˆ	ÜœG D§K¡KÐ1EÀtÓL×yÐyÔPQÐRxÓPyð  |Eó  FˆÜ:A¿-º-»/ÐIˆ×"Ñ" 7Ñ+¨i÷	 ó 	 ô" �nŠnœW×0Ò0Ñ1CÓ1EÓFÓG×GÒGñ/ `÷ EÖDáúñ, 	HùsD   †AE/Á;EÂEÂEÂA E/ÃA3E/ÅE-ÅE/ÅEÅE*	Å$
E/c               ó    € V ^8„  d   QhRRRR/# )r   r  r<   r   r-   r   )r   s   "r   r   rN  4  s   € ÷ 5ñ 5¨ð 5°ñ 5r   c              ƒ  ó’   "  € V P                   P                  V4      \        8X  d   V P                   P                  VR4       R# R# 5i)zâNO-OP for a live card: upstream calls ``stop_typing`` BEFORE ``send()`` patches it
(deleting would tombstone). Only the SENTINEL is popped so the next turn starts clean;
stranded cards are reaped by ``on_processing_complete``.N)rq  r!   r7  ré  r$  s   &&r   Ústop_typingÚGoogleChatAdapter.stop_typing4  s=   é € ð × Ñ ×$Ñ$ WÓ-Ô1JÔJØ×!Ñ!×%Ñ% g¨tÖ4ñ Kùs   ‚AAc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   rp  r<   r�   Úlog_msgÚlog_argsr   r   r-   r   )r   s   "r   r   rN  ;  s1   € ÷ <ñ <°ð <¸Cð <È#ð <ÐZ]ð <Ðbfñ <r   c              ‡  	ó¤   "  €  V P                  VR V/4      G Rj  x€L
  R#  L  \         d    \        P                  ! T.TO5RR/   R# i ; i5i)r�   NrÕ  T)r9  r·   r  rÖ  )r7   rp  r�   rÄ  rÅ  s   &&&&*r   Ú_patch_quietlyÚ GoogleChatAdapter._patch_quietly;  sH   é € ð	<Ø×%Ñ% l°V¸T°NÓC×CÔCøÜô 	<Ü�LŠL˜Ð; 8Ò;°dÕ;ð	<üs1   ‚A„$ ›"œ$  A¢$ ¤%AÁ	AÁAÁAc               ó$   € V ^8„  d   QhRRRRRR/# )r   rÌ  r�   Úoutcomerƒ   r   r-   r   )r   s   "r   r   rN  A  s(   € ÷ añ a°,ð aÐIZð aÐ_cñ ar   c              ƒ  ó
  "  € VP                   f   R# VP                   P                  p V P                  P                  VR4      pV'       dH   V\        8w  d=   \        V\        P                  8X  d   RMR4      pV P                  WER4      G Rj  x€L
  V P                  P                  V. 4       F  pV P                  VRRV4      G Rj  x€L
  K!  	  R#  LE L  \         d    \        P                  RRR	7        R# i ; i5i)
uÜ   Reap typing card(s) after the turn: pop the SENTINEL on success; on
failure/cancel patch a still-tracked card to a final label (no tombstone);
patch orphan cards (background creates that lost a race with send()) to "Â·".Nz'platform.google_chat.typing.interruptedz$platform.google_chat.typing.no_replyz9[GoogleChat] on_processing_complete patch fallback failedô   Â·z0[GoogleChat] orphan typing-card patch failed: %sz5[GoogleChat] cleanup in on_processing_complete failedTrÔ  )rÈ  r  rq  ré  r7  r   rƒ   Ú	CANCELLEDrÇ  rx  r·   r  rÖ  )r7   rÌ  rÊ  r  ÚcurrentÚlabelÚ	orphan_ids   &&&    r   Úon_processing_completeÚ(GoogleChatAdapter.on_processing_completeA  sç   é € ð �<‰<ÒÙØ—,‘,×&Ñ&ˆð		aØ×+Ñ+×/Ñ/°¸Ó>ˆGß˜7Ô&?Ô?ÜÀwÔRc×RmÑRmÔGmÑCØEóG�à×)Ñ)¨'Ð:uÓv×vÐvØ!×9Ñ9×=Ñ=¸gÀrÖJ�	Ø×)Ñ)¨)°TÐ;mÐoxÓy×yÒyó Kñ wáyøÜô 	aÜ�L‰LÐPÐ[_ˆL×`ð	aüsS   ‚'Dª#C ÁAC ÂCÂ:C ÃCÃC ÃDÃC ÃC Ã"D Ã<DÃ?D Ä Dc               ó$   € V ^8„  d   QhRRRRRR/# )r   r  r<   r�   r   zOptional[SendResult]r   )r   s   "r   r   rN  T  s"   € ÷ ñ ¸Cð Àsð ÐOcñ r   c              ƒ  ó^  "  € V P                   P                  V4      pV'       d   V\        8X  d   R# V P                   P                  VR4        V P	                  VRV/4      G Rj  x€L
 p\        V P                   V&   V#  L  \
         d   p\        T4      R8X  d    Rp?R# h Rp?ii ; i5i)uý   Patch the tracked typing card with ``text`` (no tombstone); None when there is no
real card (caller creates a message) â€” the SENTINEL stays so ``_keep_typing`` doesn't
post a fresh card during a subsequent attachment send. Raises transient HttpErrors.Nr�   r1  )rq  r!   r7  ré  r9  r$   rŠ   )r7   r  r�   rÎ  r©  r_   s   &&&   r   Ú_consume_typing_card_with_textÚ0GoogleChatAdapter._consume_typing_card_with_textT  sž   é € ð ×'Ñ'×+Ñ+¨GÓ4ˆß˜'Ô%>Ô>ÙØ×Ñ×!Ñ! '¨4Ô0ð	Ø×.Ñ.¨w¸À¸ÓG×GˆFÜ-FˆD×!Ñ! 'Ñ*ØˆMñ Høô ô 	Ü˜CÓ  CÔ'ÝØûð	üsH   ‚AB-ÁB Á'BÁ(B Â B-ÂB ÂB*ÂB%ÂB-Â$B%Â%B*Â*B-c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r  r<   Ú	image_urlÚcaptionrÛ   r(  r)  r*  r   r|   r   )r   s   "r   r   rN  e  sF   € ÷ Pñ PØðPØ'*ðPØ5BðPØUbðPà*ðPð 
ñPr   c           	   ƒ  ót  "  € V P                  WEVR7      pRP                  V'       d   V.M. V.,           4      p V P                  W4      G Rj  x€L
 pVe   V# V P                  V\	        Wv4      4      G Rj  x€L
 #  L- L  \
         d*   p	\        R\        \        T	4      4      R7      u Rp	?	# Rp	?	ii ; i5i)zOSend an inline image via URL (no upload); patches the typing card when tracked.r,  r„  NFr-  )	r3  r  rÕ  r:  rC  r$   r|   rÃ   r<   )
r7   r  rØ  rÙ  r(  r)  r?  r�   Úpatchedr_   s
   &&&&&&    r   Ú
send_imageÚGoogleChatAdapter.send_imagee  sª   é € ð
 ×+Ñ+¨HÈÐ+ÓPˆ	Ø�y‰y§w˜7™)°B¸9¸+ÕEÓFˆð	PØ ×?Ñ?ÀÓN×NˆGØÒ"Ø�Ø×-Ñ-¨g´|ÀDÓ7TÓU×UÐUñ Oñ VøÜô 	PÜ eÔ3DÄSÈÃXÓ3NÔOÕOûð	Püsd   ‚8B8»B ÁA=Á	B ÁB8ÁB Á8A?Á9B Á<B8Á=B Á?B ÂB5ÂB0Â*B5Â+B8Â0B5Â5B8c               ó8   € V ^8„  d   QhRRRRRRRRRRR	RR
RRR/# )r   r  r<   rí   rÙ  rÛ   r(  r>   rd   Ú	mime_hintÚoverride_filenamer   r|   r   )r   s   "r   r   rN  t  sX   € ÷ sñ sØðsØ"%ðsØ0=ðsØIVðsØ`nðsà ðsà5Bðsð 
ñsr   c           	   ƒ  	óŠ   "  € V P                  WEP                  R 4      VR7      pV P                  WW6W‡R7      G Rj  x€L
 #  L5i)r)  r,  )rß  r?  rà  N)r3  r!   Ú
_send_file)	r7   r  rí   rÙ  r(  r>   rß  rà  r?  s	   &&&&&&&& r   Ú_send_file_replyÚ"GoogleChatAdapter._send_file_replyt  sQ   é € ð ×+Ñ+¨H·j±jÀÓ6LÐV]Ð+Ó^ˆ	Ø—_‘_Ø˜7À9ð %ó s÷ sð 	sñ sùs   ‚:A¼A½Ac               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r  r<   Ú
image_pathrÙ  rÛ   r(  r>   r   r   r|   r   )r   s   "r   r   rN  |  sA   € ÷ fñ f¨Sð f¸cð fÈMð fØ(5ðfØHKðfØPZñfr   c              ‹  	óF   "  € V P                  WW4VR 4      G Rj  x€L
 #  L5i)zimage/*N©rã  )r7   r  ræ  rÙ  r(  r>   s   &&&&&,r   Úsend_image_fileÚ!GoogleChatAdapter.send_image_file|  s$   é € à×*Ñ*¨7ÀÐSYÐ[dÓe×eÐeÑeùó   ‚!š›!c               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r   r  r<   Ú	file_pathrÙ  rÛ   Ú	file_namer(  r>   r   r   r|   r   )r   s   "r   r   rN  €  sO   € ÷ kñ kØðkØ'*ðkØ5BðkØVcðkàðkà25ðkð 
ñkr   c           	   ‹  	óH   "  € V P                  WW5VR V4      G R j  x€L
 #  L5ir0   rè  )r7   r  rí  rÙ  rî  r(  r>   s   &&&&&&,r   Úsend_documentÚGoogleChatAdapter.send_document€  s)   é € ð ×*Ñ*¨7¸wÐRXÐZ^Ð`iÓj×jÐjÑjùs   ‚"› œ"c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r  r<   Ú
audio_pathrÙ  rÛ   r(  r>   r   r   r|   r   )r   s   "r   r   rN  †  óA   € ÷ hñ h¨ð h¸ð hÀ}ð hØ#0ðhØCFðhØKUñhr   c              ‹  	óF   "  € V P                  WW4VR 4      G Rj  x€L
 #  L5i)z	audio/oggNrè  )r7   r  ró  rÙ  r(  r>   s   &&&&&,r   Ú
send_voiceÚGoogleChatAdapter.send_voice†  ó$   é € à×*Ñ*¨7ÀÐSYÐ[fÓg×gÐgÑgùrë  c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r  r<   Ú
video_pathrÙ  rÛ   r(  r>   r   r   r|   r   )r   s   "r   r   rN  Š  rô  r   c              ‹  	óF   "  € V P                  WW4VR 4      G Rj  x€L
 #  L5i)z	video/mp4Nrè  )r7   r  rú  rÙ  r(  r>   s   &&&&&,r   Ú
send_videoÚGoogleChatAdapter.send_videoŠ  rø  rë  c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   r  r<   Úanimation_urlrÙ  rÛ   r(  r)  r*  r   r|   r   )r   s   "r   r   rN  Ž  sF   € ÷ tñ tØðtØ+.ðtØ9FðtØYfðtà*ðtð 
ñtr   c              ƒ  óF   "  € V P                  WW4VR7      G Rj  x€L
 #  L5i)zBGoogle Chat has no native animation type; fall back to send_image.)rÙ  r(  r)  N)rÜ  )r7   r  rÿ  rÙ  r(  r)  s   &&&&&&r   Úsend_animationÚ GoogleChatAdapter.send_animationŽ  s#   é € ð
 —_‘_ WÀWÐjr�_Ós×sÐsÑsùrë  c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úcredsr   rv  rÛ   rÄ  r<   r   úOptional[Any]r   )r   s   "r   r   rN  ™  s)   € ÷ ñ  cð °-ð È#ð ÐR_ñ r   c              ƒ  ó¬   "  € ^RI Hp  \        P                  ! W0V4      G Rj  x€L
 #  L  \         d    \
        P                  TRR7        R# i ; i5i)zV``oauth.refresh_or_none`` in a thread; a raise is logged at DEBUG and treated as None.)Úrefresh_or_noneNTrÔ  )r  r  rð  rñ  r·   r  rÖ  )r  rv  rÄ  Ú_refreshs   &&& r   Ú_refresh_or_noneÚ"GoogleChatAdapter._refresh_or_none˜  sI   é € õ 	7ð	Ü ×*Ò*¨8¸EÓB×BÐBÑBøÜô 	Ü�L‰L˜¨4ˆLÔ0Úð	üs1   ‚AŠ+ ¤)¥+ ¨A©+ «"AÁAÁAÁAc               ó    € V ^8„  d   QhRRRR/# )r   rv  r<   r   r  r   )r   s   "r   r   rN  ¢  s   € ÷ ñ °3ð ¸=ñ r   c              ƒ  óJ  aa"  € ^RI HpHo V P                  P	                  V4      pV P
                  P	                  V4      pVeF   VeB   V P                  WAR4      G Rj  x€L
 pVf   V P                  V4       R# WPP
                  V&   V#  \        P                  ! W!4      G Rj  x€L
 oSf   R# \        P                  ! VV3R l4      G Rj  x€L
 pST P
                  T&   Y`P                  T&   T#  L’ LN L'  \         d    \        P                  RTRR7        R# i ; i5i)uØ   Get (or build + cache) a user-authed Chat client for ``email``.
Cache hit â†’ refresh creds (evict on failure so the next request goes back
through disk / the text-notice fallback). Miss â†’ load token, build, cache.r  Nz+[GoogleChat] cached per-user refresh raisedc                 ó   <€ S ! S4      # r0   r   )Ú_buildr  s   €€r   r²  Ú;GoogleChatAdapter._load_per_user_chat_api.<locals>.<lambda>´  s	   ø€ ±&¸´-r   z4[GoogleChat] per-user creds load/build failed for %sTrÔ  )r  r  r  rm  r!   rl  r	  Ú_invalidate_user_credsrð  rñ  r·   r  rÖ  )	r7   rv  Ú_loadÚ
cached_apiÚcached_credsÚ	refreshedÚapir  r  s	   &&     @@r   Ú_load_per_user_chat_apiÚ)GoogleChatAdapter._load_per_user_chat_api¢  s  ùé € ÷ 	]Ø×1Ñ1×5Ñ5°eÓ<ˆ
Ø×0Ñ0×4Ñ4°UÓ;ˆØÒ! lÒ&>Ø"×3Ñ3°LÐIvÓw×wˆIØÒ Ø×+Ñ+¨EÔ2ÙØ/8×%Ñ% eÑ,ØÐð	Ü!×+Ò+¨EÓ9×9ˆEØŠ}ÙÜ×)Ò)Õ*?Ó@×@ˆCð ,1ˆ×!Ñ! %Ñ(Ø.1×$Ñ$ UÑ+Øˆ
ñ! xñ :ñ AøÜô 	Ü�L‰LÐOÐQVÐaeˆLÔfÚð	üsf   „AD#Á C3Á!+D#ÂC9 Â&C5Â'C9 Â/D#Â1C9 ÃC7ÃC9 Ã D#Ã5C9 Ã7C9 Ã9#D ÄD#ÄD Ä D#c               ó    € V ^8„  d   QhRRRR/# )r   rm  rÛ   r   z#tuple[Optional[Any], Optional[str]]r   )r   s   "r   r   rN  ¼  s   € ÷ ñ ¸ð ÐKnñ r   c              ƒ  ót  "  € V'       d!   V P                  V4      G Rj  x€L
 pVe   W!3# V P                  ez   V P                  V P                  RR4      G Rj  x€L
 pVf3   \        P                  R4       V P                  V P                  4       R# W0n        V P                  V P                  3# R#  L” L\5i)uö   User-authed Chat client for an outbound attachment: per-user token for
``sender_email`` â†’ legacy single-user fallback â†’ ``(None, None)`` (caller posts the
setup notice). The identity label (email / ``"__legacy__"``) selects the slot to evict.Nz([GoogleChat] legacy creds refresh raiseduP   [GoogleChat] legacy user-OAuth refresh returned None â€” evicting fallback creds©NN)r  rj  r	  rk  r  r  r  Ú_LEGACY_USER_IDENTITY)r7   rm  r  r  s   &&  r   Ú_acquire_user_chat_apiÚ(GoogleChatAdapter._acquire_user_chat_api¼  s±   é € ÷ Ø×4Ñ4°\ÓB×BˆCØŠØÐ(Ð(Ø×ÑÒ*Ø"×3Ñ3°D×4JÑ4JÈDÐR|Ó}×}ˆIØÒ Ü—‘ÐqÔrØ×+Ñ+¨D×,FÑ,FÔGØ!Ð!Ø%.Ô"Ø×&Ñ&¨×(BÑ(BÐBÐBØÐñ Cñ ~ùs"   ‚B8ŸB4 9B8ÁB6ÁAB8Â6B8c               ó    € V ^8„  d   QhRRRR/# )r   ÚidentityrÛ   r   r-   r   )r   s   "r   r   rN  Î  s   € ÷ 9ñ 9¨}ð 9Àñ 9r   c                óÊ   € V'       g   R# WP                   8X  d   R;V n        V n        R# V P                  P	                  VR4       V P
                  P	                  VR4       R# )zLDrop creds for ``identity`` (email or ``__legacy__``) after an auth failure.N)r  rk  rj  rl  ré  rm  )r7   r  s   &&r   r  Ú(GoogleChatAdapter._invalidate_user_credsÎ  sS   € çÙØ×1Ñ1Ô1Ø;?Ð?ˆDÔ" TÔ%8ÙØ×!Ñ!×%Ñ% h°Ô5Ø×$Ñ$×(Ñ(¨°4Ö8r   c               ó4   € V ^8„  d   QhRRRRRRRRRRRRR	R
/# )r   r  r<   rí   rÙ  rÛ   rß  r?  rà  r   r|   r   )r   s   "r   r   rN  Ø  sO   € ÷ 0Pñ 0PØð0PØ"%ð0PØ0=ð0PØJWð0Pà ð0Pà<Ið0Pð 
ñ0Pr   c           	   ƒ  óâ  aaaaaa"  € \         P                  P                  S4      '       g   \        RRS 2R7      # T;'       g*    \         P                  P	                  S4      ;'       g    RoT;'       g    RoV P                  V P                  P                  S4      4      G Rj  x€L
 w  opSf   V P                  SSSW54      G Rj  x€L
 #  T P                  ST;'       g    R4      G Rj  x€L
   \        P                  ! VVVVV3R l4      G Rj  x€L
 pTP                  R4      pT'       g   \        RRR7      # RRT/./pTP+                  RT3RT'       d   RT/MR33 UUu/ uF  w  rÞT'       g   K  YÞbK  	  upp4       \-        ST4      o \        P                  ! TT3R l4      G Rj  x€L
 pT P/                  ST4       \        R	TP                  R4      R7      #  EL@ EL  Lý  \         d    \        P                  RR	R
7        EL i ; i EL  \         d…   p	\!        T	4      p
T
R9   dJ   \        P#                  RYz4       T P%                  T4       T P                  SSSY54      G Rj  x€L 
 u Rp	?	# \        R\'        \)        T	4      4      R7      u Rp	?	# Rp	?	ii ; iu uppi  Lþ  \         d*   p	\        R\'        \)        T	4      4      R7      u Rp	?	# Rp	?	ii ; i5i)a5  Native attachment: user-authed ``media.upload`` then ``messages.create`` with the
latest inbound sender's token (legacy token as fallback; text notice when neither).
``messages.patch`` cannot add attachments, so the typing card is patched with the
caption (or a single space) to retire it without a tombstone.Fzfile not found: r-  z
upload.binrÛ  NrÙ  z4[GoogleChat] _send_file pre-patch typing-card failedTrÔ  c            
     ó€   <€ S P                  4       P                  SR S/\        SSRR7      R7      P                  4       # )r  F)ÚmimetypeÚ	resumable)r5  rB  Ú
media_body)r  ÚuploadÚMediaFileUploadræ  )Úchat_apir  r  rÅ   rí   s   €€€€€r   r²  Ú.GoogleChatAdapter._send_file.<locals>.<lambda>í  sA   ø€ ¸(¿.¹.Ó:J×:QÑ:QØ j°(Ð%;Ü*¨4¸$È%ÔPð ;Ró ;÷ ‰g‹ið;r   u‚   [GoogleChat] media.upload auth failure for identity=%s (token revoked or scope missing) â€” falling back to text notice. Status=%sr÷  z$upload returned no attachmentDataRefrÚ  r�   rA  rq   c                 ó|   <€ S P                  4       P                  4       P                  ! R/ SB P                  4       # )Nr   )rã  ro  r­  ræ  )r*  Úcreate_kwargss   €€r   r²  r+    s-   ø€ °8·?±?Ó3D×3MÑ3MÓ3O×3VÒ3VÑ3gÐYfÑ3g×3oÑ3oÔ3qr   r  >   é‘  r/  )r   rí   rî   r|   Úbasenamer  rn  r!   Ú_post_attachment_fallbackrÕ  r·   r  rÖ  rð  rñ  r$   rŠ   r  r  rÃ   r<   rp   rH  r¨  )r7   r  rí   rÙ  rß  r?  rà  r  Úupload_respr_   rB   Úattachment_refrB  rw  r€  rˆ   r*  r-  r  rÅ   s   &ff&&&&         @@@@r   râ  ÚGoogleChatAdapter._send_fileØ  s   ýé € ô �w‰w�~‰~˜d×#Ò#Ü eÐ5EÀdÀVÐ3LÔMÐMØ$×NÐN¬¯©×(8Ñ(8¸Ó(>×NÐNÀ,ˆØ×6Ð6Ð6ˆØ#'×#>Ñ#>¸t×?XÑ?X×?\Ñ?\Ð]dÓ?eÓ#f×fÑˆ�(ØÒØ×7Ñ7¸ÀÀxÐQXÓd×dÐdð	`Ø×5Ñ5°g¸w¿~¸~È#ÓN×NÐNð	PÜ '× 1Ò 1÷ 3ð 3ó !÷ ˆKð %Ÿ™Ð)<Ó=ˆßÜ eÐ3YÔZÐZØ ,Ð0CÀ^Ð/TÐ.UÐVˆØ�‰¨°Ð'8¸8×\eÀfÈiÑEXÐkoÐ:pÑ&qÔwÑ&q™d˜aÔuv”T�Q’TÑ&qÒwÔxô ' w°Ó5ˆð	PÜ ×*Ò*Õ+qÓr×rˆDØ×'Ñ'¨°Ô6Ü d°t·x±xÀÓ7GÔHÐHòE gâdáNøÜô 	`Ü�L‰LÐOÐZ^ˆL×_ð	`úòøô ô 		PÜ! #Ó&ˆFØ˜Ô#Ü—‘ð5Ø6>ôð ×+Ñ+¨HÔ5Ø!×;Ñ;¸GÀTÈ8ÐU\Óh×hÐhÕhÜ eÔ3DÄSÈÃXÓ3NÔOÕOûð		Püó xñ
 søô ô 	PÜ eÔ3DÄSÈÃXÓ3NÔOÕOûð	Püs,  ˆ>K/Á&K/Á.K/Á:0K/Â*G*Â+"K/ÃG-ÃK/ÃG2 Ã(
G2 Ã2G0Ã3G2 Ã8!H ÄHÄH ÄK/Ä7*K/Å"K/Å-J0
Å>J0
ÆK/ÆJ8 Æ7J6Æ81J8 Ç)K/Ç-K/Ç0G2 Ç2"HÈK/ÈHÈK/ÈH ÈJ-È)AJ(É9I<É:J(É>J-É?K/ÊJ(Ê"J-Ê#K/Ê(J-Ê-	K/Ê6J8 Ê8K,ËK'Ë!K,Ë"K/Ë'K,Ë,K/c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r   r  r<   rí   r  rÙ  rÛ   r?  r   r|   r   )r   s   "r   r   rN  
  sB   € ÷ tñ t°sð tÀ#ð tÐQTð tÐ_lð tØ3@ðtØEOñtr   c           
   ƒ  ó   "  € RP                  \        RVR7      \        R4      \        R4      \        RVR7      .4      pT P                  V'       d   V RV 2MTT;'       g    R4      p V'       d$   V P                  V\	        Wu4      4      G R	j  x€L
  \        RRR7      #  L  \
         d    \        P                  R
RR7        L3i ; i5i)zxPost the ``/setup-files`` notice (plus host path) when native delivery is
unavailable. Always returns ``success=False``.r„  z/platform.google_chat.attachment_fallback.header)r  z0platform.google_chat.attachment_fallback.explainz1platform.google_chat.attachment_fallback.activatez2platform.google_chat.attachment_fallback.host_path)rí   r¯   Nz3[GoogleChat] attachment fallback notice send failedTrÔ  FuO   google_chat: native attachment requires user OAuth â€” run /setup-files in chatr-  )	r  r   Úwarning_textr:  rC  r·   r  rÖ  r|   )r7   r  rí   r  rÙ  r?  ÚnoticerB  s   &&&&&&  r   r0  Ú+GoogleChatAdapter._post_attachment_fallback
  sÒ   é € ð —‘ÜÐ?È(ÔSÜÐ@ÓAÜÐAÓBÜÐBÈÔNð	
ó ˆð × Ñ ¿7 G 9¨B¨v¨hÑ!7ÈÐPW×P]ÐP]Ð[]Ó^ˆð	_ßØ×*Ñ*¨7´LÀÓ4QÓR×RÐRô ØÐ!rôtð 	tñ SøÜô 	_Ü�L‰LÐNÐY]ˆLÖ^ð	_üsH   ‚A!CÁ$CÁ,B& Á4B& ÂB$ÂB& ÂCÂ$B& Â&"CÃCÃ
CÃCc               ó    € V ^8„  d   QhRRRR/# )r   r  r<   r   rd   r   )r   s   "r   r   rN    s   € ÷ 
ñ 
¨3ð 
°>ñ 
r   c           	   ƒ  óÈ  a a"  €  \         P                  ! VV 3R l4      G Rj  x€L
 pTP                  R4      ;'       g    TP                  R4      ;'       g    R	P                  4       pRTP                  R
4      ;'       g    SRTR9   d   RRS/# RRS/#  Ls  \         d;   p\        P	                  R\        \        T4      4      4       RSRRRS/u Rp?# Rp?ii ; i5i)z)Return {name, type, chat_id} for a space.c                 ó”   <€ SP                   P                  4       P                  S R 7      P                  SP	                  4       R7      # rn  )ra  rã  r!   ræ  rç  )r  r7   s   €€r   r²  Ú1GoogleChatAdapter.get_chat_info.<locals>.<lambda>!  s7   ø€ ˜Ÿ™×-Ñ-Ó/×3Ñ3¸Ð3ÓA×IÑIÈt×OdÑOdÓOfÐIÔgr   Nz%[GoogleChat] get_chat_info failed: %srq   rë  r¡  r  r|  r¯   rw  rÕ  >   rä  rå  )	rð  rñ  r$   r  rÖ  rÃ   r<   r!   rC   )r7   r  rø   r_   r}  s   ff   r   Úget_chat_infoÚGoogleChatAdapter.get_chat_info  sâ   ùé € ð	JÜ ×*Ò*Ýgói÷ iˆDð
 —h‘h˜{Ó+×EÐE¨t¯x©x¸Ó/?×EÐEÀ2×LÑLÓNˆ
à�D—H‘H˜]Ó+×6Ð6¨wØ˜JÐ*BÔB�DØ�wð
ð 	
àHOØ�wð
ð 	
ñiøäô 	JÜ�L‰LÐ@ÔBSÔTWÐX[ÓT\ÓB]Ô^Ø˜G V¨W°iÀÐIÕIûð	JüsU   „C"†B ¤B¥B ©C"ÁC"Á)C"ÂC"ÂB ÂCÂ%/CÃCÃC"ÃCÃC")r}  rf  ra  rr  rb  r~  ro  r�  r‚  r€  rt  rn  rh  r{  rz  rx  rd  rs  ri  rp  rc  r`  re  rg  rv  rw  rq  rj  rm  rk  rl  rŽ  r0   r  )NNN)MrM   rN   rO   rP   rQ   rh  ÚMAX_MESSAGE_LENGTHrX  r[  rZ  r  r8   Ústaticmethodry  r  r˜  r¤  r«  r´  rÅ  rÉ  rÐ  r×  rô  rÿ  r  r$  r8  rJ  r5  r�  r�  rW  r’  r¯  r­  rÂ  r£  rÉ  rÇ  rç  r%  rC  rI  rb  ri  rr  r9  r5  Úclassmethodr   r3  rç  r£  r¨  r:  r½  rÁ  rÇ  rÑ  rÕ  rÜ  rã  ré  rð  rö  rü  r  r	  r  r  r  râ  r0  r=  rS   r×   rØ   s   @r   rJ  rJ  ~  s  ø† ñ^ð *Ðà ÐØÐØ ÐØ(Ð÷1qð 1qðf ôó ðð öXó ðXõõ(
ð4 ôRó ðRð ôZó ðZõCõ.>õ
õ\õõ.õ@õ4ð$.°E÷ .õ`1õ&+ð\ ö%ó ð%÷N,õ<6õ+õZõCõõ F÷$bõD
õL9Kõx.÷81÷tt÷ iò ið4=Ðbg÷ =õ$õ"Sõð ô(ó ð(÷Uõ Qð
9ÐSb÷ 9õ*^õE÷$HõL5õ<õaõ&÷"P÷s÷f÷k÷h÷h÷tð ôó ðõõ4õ$9÷0Põdt÷&
ó 
r   rJ  c               ó    € V ^8„  d   QhRRRR/# ©r   rM  rw   r   r   r   )r   s   "r   r   r   .  s   € ÷ nñ n˜^ð n°ñ nr   c                óÈ   € \        V R/ 4      ;'       g    / p\        VP                  R4      ;'       g+    VP                  R4      ;'       d    VP                  R4      4      # )zCPlugin-side config gate for HTTP callback or Pub/Sub inbound modes.r«   rZ  rœ  r�  )rF   r   r!   )rM  r«   s   & r   r¤  r¤  .  sP   € ä�F˜G RÓ(×.Ð.¨B€EÜ�—	‘	Ð+Ó,×lÐl°·±¸<Ó1H×1kÐ1kÈUÏYÉYÐWjÓMkÓmÐmr   c               ó   € V ^8„  d   QhRR/# )r   r   z2tuple[Optional[str], Optional[str], Optional[str]]r   )r   s   "r   r   r   4  s   € ÷ Tñ TÐQñ Tr   c                 ó”   € \        R4      ;'       g    \        R4      p \        R4      ;'       g    \        R4      pW\        R4      3# )zT(project, subscription, http_events_url) from the scoped env, with legacy fallbacks.ÚGOOGLE_CHAT_PROJECT_IDÚGOOGLE_CLOUD_PROJECTÚGOOGLE_CHAT_SUBSCRIPTION_NAMEÚGOOGLE_CHAT_SUBSCRIPTIONr[  )r|  )rž  r¢  s     r   Ú_env_inbound_settingsrK  4  sH   € ä Ð!9Ó:×hÐhÔ>PÐQgÓ>h€GÜ%Ð&EÓF×xÐxÔJ\Ð]wÓJx€LØÔ"4Ð5RÓ"SÐSÐSr   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   ;  s   € ÷ ?ñ ? ñ ?r   c                 óZ   € \        4       w  rp\        T;'       g    T ;'       d    T4      # r0   )rK  r   )rž  r¢  rZ  s      r   Ú_env_inbound_configuredrN  ;  s*   € Ü-BÓ-DÑ*€G˜?Ü�×=Ð= G×$<Ð$<°Ó>Ð>r   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   @  s   € ÷ Jñ J˜Tñ Jr   c                 ó:   € \        4       ;'       d    \        4       # )z�``check_fn`` for the registry pass: deps installed AND minimum inbound env set,
so an unconfigured user never sees ``google_chat`` auto-enabled.)r¢   rN  r   r   r   Ú_check_for_registryrQ  @  s   € ô *Ó+×IÐIÔ0GÓ0IÐIr   c               ó    € V ^8„  d   QhRRRR/# rC  r   )r   s   "r   r   r   F  s   € ÷ Pñ P˜.ð P¨Tñ Pr   c                óT   € \        \        V RR4      4      ;'       d    \        V 4      # )z7``GatewayConfig.get_connected_platforms()`` polls this.ÚenabledF)r   rF   r¤  )rM  s   &r   Ú_is_connectedrU  F  s$   € ä”˜ 	¨5Ó1Ó2×OÐOÔ7GÈÓ7OÐOr   c               ó   € V ^8„  d   QhRR/# )r   r   r*  r   )r   s   "r   r   r   S  s   € ÷ ñ Ð1ñ r   c                 ó"  € \        4       '       g   R# \        4       w  rpRV 3RV3RV3R\        R4      ;'       g    \        R4      3.pV UUu/ uF  w  rEV'       g   K  WEbK  	  pppVP                  \	        \
        RR	7      4       V# u uppi )
zÎ``env_enablement_fn``: seed ``PlatformConfig.extra`` from the profile's env before the adapter exists
(so ``gateway status`` reflects env-only config); ``None`` when the minimum inbound settings are absent.Nrœ  r�  rZ  r’  r   r   ÚGOOGLE_CHAT_HOME_CHANNEL)Úhome_env)rN  rK  r|  rp   Ú_seed_extra_from_envÚ_ENV_SEED_KEYS)rž  r¢  rZ  ÚvaluesÚ
extra_nameÚvalueÚseeds          r   Ú_env_enablementr`  S  s¦   € ô #×$Ò$ÙÜ-BÓ-DÑ*€G˜?Ø˜WÐ%Ð(;¸\Ð'JÐM^Ð`oÐLpØ%Ô'9Ð:\Ó']÷ (Gð (GÜ$Ð%EÓFðHðI€Fñ 8>ÔG±vÑ"3 *ÄÔˆJÒ±v€DÑGØ‡K�KÔ$¤^Ð>XÔYÔZØ€Kùó Hs   ÁBÁ Bu[  Google Chat needs a GCP project, a Pub/Sub topic + subscription,
and a Service Account with Pub/Sub Subscriber on the subscription.
Walkthrough:
  1. Create or select a GCP project; enable Google Chat API + Cloud Pub/Sub API.
  2. Create a Service Account (no project-level IAM role needed).
  3. Create a Pub/Sub topic (e.g. hermes-chat-events) and a Pull subscription.
  4. On the TOPIC: add chat-api-push@system.gserviceaccount.com as Pub/Sub Publisher.
  5. On the SUBSCRIPTION: grant your Service Account Pub/Sub Subscriber.
  6. Download the Service Account JSON key.
  7. Google Chat API console â†’ Configuration: connection = Cloud Pub/Sub,
     point at the topic, enable 1:1 + group, restrict visibility.
  8. Install the bot in a space (fires ADDED_TO_SPACE and resolves its user_id).

Full guide: website/docs/user-guide/messaging/google_chat.md
c               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   r   s  s   € ÷ '>ñ '>˜4ñ '>r   c                 óÚ  € ^ RI Hp HpHpHpHp ^ RIHpHp ^ RI	H
p V! RRR4      '       d   R# \        P                  4        F  pV ! V4       K  	  R FR  w  ršr¼T! Y•! V
4      ;'       g    R	VR
7      pV'       g   Vf   K.  V! V R24        R# V! W­P                  4       4       KT  	  V! RR4      '       dO   T! RV! R4      ;'       g    R	R7      pV'       d#   V! RVP                  RR	4      4       V! R4       MV! RR	4       MV! RR4       V! R4       T! RV! R4      ;'       g    R	R7      pV'       d   V! RVP                  4       4       \        4        V! R4       V ! R4       R# )zd``hermes setup`` wizard: print GCP instructions, prompt for env vars, persist to ``~/.hermes/.env``.)Ú
print_infoÚprint_successÚprint_warningÚpromptÚprompt_yes_no)Úget_env_valueÚsave_env_value)Údeclines_reconfigureúGoogle ChatzReconfigure Google Chat?rI  NTr¯   )r÷   Úpasswordu+    is required â€” skipping Google Chat setupz0Restrict access to specific users? (recommended)z%Allowed user emails (comma-separated)ÚGOOGLE_CHAT_ALLOWED_USERS)r÷   rÙ  zAllowlist configuredÚGOOGLE_CHAT_ALLOW_ALL_USERSÚtrueuA   âš ï¸�  Open access â€” anyone who can DM the bot can command it.zFHome space for cron/notification delivery (e.g. spaces/AAAA, or empty)rX  z1Google Chat configuration saved to ~/.hermes/.envz+Restart the gateway: hermes gateway restart))z GCP project ID (e.g. my-project)rG  z
Project IDF)z:Pub/Sub subscription (projects/<proj>/subscriptions/<sub>)rI  ÚSubscriptionF)z-Path to Service Account JSON (or inline JSON)r   NT)Úhermes_cli.cli_outputrc  rd  re  rf  rg  Úhermes_cli.configrh  ri  Úhermes_cli.setup_platformsrj  Ú_SETUP_WALKTHROUGHÚ
splitlinesr  r;  Úprint)rc  rd  re  rf  rg  rh  ri  rj  ÚlinerL  r‡  Úrequired_labelrl  r^  ÚallowedÚhomes                   r   Úinteractive_setupr{  s  sR  € çeÕeß?Ý?Ù˜MÐ+EÐGf×gÒgÙÜ"×-Ñ-Ö/ˆÙ�4Öñ 0ó9Ñ4ˆ˜Nñ
 �x¨°xÓ)@×)FÐ)FÀBÐQYÔZˆßØÒ%ÙÙ˜^Ð,Ð,WÐXÔYÚÙ�x§¡£Ö/ñ9ñ ÐGÈ×NÒNÙÐ@É-ÐXsÓJt×JzÐJzÐxzÔ{ˆßÙÐ6¸¿¹ÈÈRÓ8PÔQÙÐ0Õ1áÐ6¸Õ;áÐ4°fÔ=ÙÐYÔZÙØPÙÐ8Ó9×?Ð?¸Rô€D÷ ÙÐ1°4·:±:³<Ô@Ü	„GÙÐEÔFÙÐ<Ö=r   z!^(?:spaces|users)/[A-Za-z0-9_-]+$z.^spaces/[A-Za-z0-9_-]+/threads/[A-Za-z0-9_-]+$z inline SA JSON is invalid: {exc}z SA JSON file not found at {path}zSA JSON file is invalid: {exc}zƒADC skipped for this profile: service-account credentials are set in the process environment but not in this profile's secret scopezNno SA credentials configured and google-auth is not installed for ADC fallbackzWno SA credentials configured and Application Default Credentials are unavailable: {exc}c               ó    € V ^8„  d   QhRRRR/# )r   rÑ   r<   r   rd   r   )r   s   "r   r   r   ®  s   € ÷ @ñ @˜cð @ nñ @r   c                ó   € \        R V  24      # )zGoogle Chat standalone send: )r   )rÑ   s   &r   Ú_standalone_errorr~  ®  s   € ÜÐ5°f°XÐ>Ó?Ð?r   r?  Úmedia_filesÚforce_documentc               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r   r  r<   r—  r?  rÛ   r  zOptional[list[str]]r€  r   r   rd   r   )r   s   "r   r   r   ²  sF   € ÷ 9Fñ 9FØð9FØ$'ð9FØ7Dð9Fà$ð9Fà=Að9Fð ñ9Fr   c             ƒ  ó
  "  € V'       g   \        R4      # \        P                  V4      '       g   \        RV: R24      # Ve,   \        P                  V4      '       g   \        RV: R24      # \	        V R/ 4      ;'       g    / pVP                  R4      ;'       g    \        R	4      ;'       g    \        R
4      p\        f   \        R4      #  ^ RIH	p  \        T4      p
 \"        P$                  ! \"        P&                  ! T
P(                  T! 4       4      RR7      G Rj  x€L
  \	        T
RR4      pT'       g   \        R4      #  ^ RIp TP1                  TP3                  RR7      \5        4       R7      ;_uu_4       GRj  x€L
 pTP7                  RT R2\9        Y#4      RRT 2RR/R 7      ;_uu_4       GRj  x€L
 pTP:                  R!8¼  d]   \        R"TP:                   R#TP=                  4       G Rj  x€L
 R$,           24      uuRRR4      GRj  x€L
  uuRRR4      GRj  x€L
  # TP?                  4       G Rj  x€L
 pRRR4      GRj  x€L
  RRR4      GRj  x€L
  R%R&R'XP                  R(4      /#   \         d   p	\        RT	 24      u Rp	?	# Rp	?	ii ; i  \         dF   p\        \        TP                  ,          P                  TP                   TR7      4      u Rp?# Rp?i\         d   p	\        RT	 24      u Rp	?	# Rp	?	ii ; i ELô  \*         d    \        R4      u # \         d   p	\        RT	 24      u Rp	?	# Rp	?	ii ; i  \.         d    \        R4      u # i ; i ELî EL¸ EL ELd ELU EL? EL2  + GRj  x€L 
 '       g   i     ELJ; i ELB  + GRj  x€L 
 '       g   i     ELZ; i  \         d0   p	\@        PC                  R)R&R*7       \E        R+T	 24      u Rp	?	# Rp	?	ii ; i5i),zøPOST one Chat message via REST without the SDK (``send_message_tool`` when the
gateway runner is not in-process, e.g. ``hermes cron``). Needs SA credentials and a
validated space name; ``media_files`` / ``force_document`` are signature parity only.z$chat_id (space resource) is requiredzchat_id zK must match 'spaces/<id>' or 'users/<id>' with only [A-Za-z0-9_-] in the idNz
thread_id z& must match 'spaces/<id>/threads/<id>'r«   r’  r   r   zgoogle-auth not installed)r]   zgoogle-auth import failed: )r_   rí   zcredential load failed: r?  r=  ztoken refresh timed outztoken refresh failed: rb   z#refreshed credentials have no tokenzaiohttp not installedg      >@)Útotal)r>  Ú	trust_envzhttps://chat.googleapis.com/v1/z	/messagesÚAuthorizationr¹  zContent-Typezapplication/json)rê   Úheadersi�  zAPI returned z: :Ni,  Nr.  Trà  rq   z"Google Chat standalone send raisedrÔ  z$Google Chat standalone send failed: )#r~  Ú_GCHAT_CHAT_ID_REr   Ú_GCHAT_THREAD_ID_RErF   r!   r|  rñ   r  r]   r·   rý   rÎ   Ú_STANDALONE_SA_ERRORSrÐ   r   rÑ   rð  rF  rñ  ÚrefreshrE  Úaiohttpr[   ÚClientSessionÚClientTimeoutrz   ÚpostrC  rB   r�   rê   r  rÖ  r   )Úpconfigr  r—  r?  r  r€  r«   rÚ   Ú_GoogleAuthRequestÚer  r–  rb   Ú_aiohttpÚsessionrˆ   Úpayloads   &&&$$$           r   Ú_standalone_sendr•  ²  sª  é € ÷ Ü Ð!GÓHÐHÜ×"Ñ" 7×+Ò+Ü Ø�w‘kÐ!lÐmóoð 	oàÒÔ%8×%>Ñ%>¸y×%IÒ%IÜ  :¨i©]Ð:`Ð!aÓbÐbÜ�G˜W bÓ)×/Ð/¨R€Eà�	‰	Ð(Ó)÷ 	@ð 	@Ô-?Ð@bÓ-c÷ 	@ð 	@ÜÐ>Ó?ð ô ÒÜ Ð!<Ó=Ð=ðDÝPðAÜ)¨(Ó3ˆð?Ü×Òœw×0Ò0°·±Ñ@RÓ@TÓUÐ_cÔd×dÐdô
 �E˜7 DÓ)€EßÜ Ð!FÓGÐGð:Û"ðFØ×)Ñ)°(×2HÑ2HÈtÐ2HÓ2TÔ`qÓ`sÐ)×t×tÔtÐxØ—|‘|Ø1°'°¸)ÐDÌ<ÐX_ÓKkØ(¨G°E°7Ð*;¸^ÐM_Ð`ð $÷ ÷ ô ð Ø—;‘; #Ô%Ü,¨}¸T¿[¹[¸MÈÐSW×S\ÑS\ÓS^×M^Ð`dÕLeÐKfÐ-gÓh÷÷ ñ ÷ u×tÒtð !%§	¡	£×+�÷÷ ÷ u×tð ˜4 ¨w¯{©{¸6Ó/BÐCÐCøô? ô DÜ Ð#>¸q¸cÐ!BÓCÕCûðDûô ô hÜ Ô!6°s·x±xÕ!@×!GÑ!GÈCÏJÉJÐ]eÐ!GÓ!fÓgÕgûÜô AÜ Ð#;¸A¸3Ð!?Ó@Õ@ûðAúò 	eøÜô <Ü Ð!:Ó;Ò;Üô ?Ü Ð#9¸!¸Ð!=Ó>Õ>ûð?ûô ô :Ü Ð!8Ó9Ò9ð:úò uòò
 N_òò uò ,÷÷ ÷ ô ú÷ u×t×tÔtûô ô FÜ�‰Ð9ÀDˆÔIÜÐ@ÀÀÐDÓEÕEûðFüs2  ‚.P±.PÁ #PÂPÂPÂ2PÃI> ÃJ$ Ã%?L Ä$LÄ%L Ä) PÅ
M Å7O ÆM4ÆO Æ
5N)Æ?M7Ç N)Ç8N		Ç;M:Ç<N		ÈN)ÈM=
ÈN)ÈO È+N È,O È0PÈ1N		ÉNÉN		É	N)ÉNÉN)ÉO É$N&É%O É=PÉ>J!Ê	JÊJ!ÊPÊJ!Ê!PÊ$LÊ/:K/Ë)LË*PË/LË<LË=LÌ
LÌPÌLÌPÌL ÌMÌ1PÌ3MÌ<MÌ=MÍ
MÍPÍMÍPÍM1Í.PÍ0M1Í1PÍ4O Í7N)Í:N		Í=N)Î O ÎN		ÎN)Î	N#ÎNÎ
N#ÎN#Î	N)Î&O Î)O	Î/N2Î0
O	Î;O	Î=	O ÏP Ï$O;Ï5P Ï6PÏ;P Ð Pc               ó   € V ^8„  d   QhRR/# r  r   )r   s   "r   r   r   î  s   € ÷ &ñ &�Tñ &r   c                óŽ   € V P                  RRRRR \        \        \        \        R.R\
        \        R\        R	R
RRRRR7       R# )zUPlugin entry point: registers the ``google_chat`` adapter with the platform registry.rx   z0Connect Hermes to Google Chat via Cloud Pub/Sub.zKhttps://hermes-agent.nousresearch.com/docs/user-guide/messaging/google_chatrk  c                ó   € \        V 4      # r0   )rJ  )Úcfgs   &r   r²  Úregister.<locals>.<lambda>õ  s
   € Ô$5°cÔ$:r   r   z2Run `hermes setup` to install Google Chat support.rX  rm  rn  r„   u   ðŸ’¬Tu{  You are on Google Chat. Limited markdown subset is rendered: *bold*, _italic_, ~strike~, `code`. No headings or lists. Message size limit: 4000 characters; longer responses are split across multiple messages. You are in a space (DM or group). Images render inline; audio, video, and document attachments render as download cards (no native voice/video UI). To send files, include MEDIA:/absolute/path/to/file in your response. Native file attachments require the user to run /setup-files once in their own DM â€” until they do, file requests fall back to a text notice with the host path. Do NOT generate interactive Card v2 buttons â€” Google Chat interactivity is not yet supported by this gateway; ask for typed confirmations instead. While you are generating a response, a 'Hermes is thinkingâ€¦' marker message appears in the space and is deleted once your response is ready. You do NOT have access to Google Chat-specific APIs â€” you cannot search space history, list space members, or manage spaces. Do not promise to perform these actions; explain that you can only read messages sent directly to you and respond in the same space/thread.)rq   Údashboard_descriptionÚdocs_urlrÏ  Úadapter_factoryÚcheck_fnÚensure_deps_fnÚvalidate_configÚis_connectedÚrequired_envÚinstall_hintÚsetup_fnÚenv_enablement_fnÚcron_deliver_env_varÚstandalone_sender_fnÚallowed_users_envÚallow_all_envÚmax_message_lengthÚemojiÚallow_update_commandÚplatform_hintN)Úregister_platformrQ  r¬   r¤  rU  r{  r`  r•  )rÄ  s   &r   Úregisterr¯  î  sY   € à×ÑØØPØ^ØÙ:Ü$Ü.Ü(Ü"Ø8Ð9ØIÜ"Ü)Ø7Ü-Ø5Ø3àØØ!ð0ð/ ö $r   ))r–  r–  N)r!  zgoogle.cloud.pubsub_v1N)r  zgoogle.api_core.exceptionsN)rñ   zgoogle.oauth2.service_accountN)r•  Úgoogle_auth_httplib2r•  )r/  zgoogleapiclient.discoveryÚbuild)r$   zgoogleapiclient.errorsr$   )r)  zgoogleapiclient.httpr)  )é   g      ð?g       @g333333Ó?>   r2  éô  éö  é÷  éø  )r>  z	timed outzbroken pipezremote disconnected)zgoogleapis.comzchat.google.comzdrive.google.comzdocs.google.comzlh3.googleusercontent.comzlh4.googleusercontent.comzlh5.googleusercontent.comzlh6.googleusercontent.com))r]  r\  N)r_  r^  N)rS  rR  N)rU  rT  N)rW  rV  N)rY  rX  N)ƒÚ__conditional_annotations__rQ   Ú
__future__r   rð  rB  r¾  rm   rê   rÁ  r   r]  Úrer1   rD   Úpathlibr   r  Útypingr   r   r   r   r   r	   Úurllib.parser
   Ú
agent.i18nr   Úagent.secret_scoper   Úgateway.platforms._sharedr   r|  r   rZ  r   Úcardsr   r   r‹  r"   r#   Ú__annotations__r–  r!  r  rñ   r•  r/  r)  r·   r$   r%   rl   rR   r&   r2   rY   r(   r`   ri   ru   Úgateway.configrv   rw   Úgateway.platforms.helpersry   Úgateway.platforms.baserz   r{   r|   r}   r~   r   r€   Úgateway.platforms.eventr�   r‚   rƒ   Ú	getLoggerr  ÚcompilerŸ  rô   rh  r;  rŸ  r�  r¡  r   Ú	frozensetr›   rž   r7  rº   r¿   ÚPHOTOÚAUDIOÚVIDEOrÇ   r  rŠ   rŸ   r¢   r¬   r¼   rÃ   rÌ   rÎ   rý   rÿ   r“  rC  rH  rJ  r¤  rK  rN  rQ  rU  r[  r`  rt  r{  r‡  rˆ  r‰  r~  r•  r¯  )r·  s   @r   Ú<module>rÌ     s_  øðôõ #ã Û Û Û Û Û Û 	Û Û 	Û Û Ý !ß =× =Ý !å Ý 2÷ñ ÷ Lõð $Ð �tÓ #ØmqÐ q€Ð qˆ9Ð q�~Ð q¨Ð q¸.Ð qÈ=Ð[jØ€	ˆ3Ó à$Ð ˜Ó $ð€ð &)Ð "Ø $Ð ˜#Ó $Ø )§¢Ó 0Ð ÷ñ õ.	(õYõ÷$ 4ñ 	ˆÔ Ý 9÷÷ ñ ÷
 QÑ Pð 
×	Ò	Ð:Ó	;€àŸ
š
Ð#`ÓaÐ ð ;Ð<dÐe€ØÐ ØÐ àJZÑ GÐ Ð&Ð(8¸-Ù$Ò%>Ó?Ð ØYÐ ð )Ð ðÐ ð
 ‡Z‚ZÐ9Ó:Ð<jÐkØ‡Z‚ZÐ2Ó3Ð5\Ð]Ø‡Z‚ZÐLÓMÐOwÐxð€ð
 ! +×"3Ñ"3Ð4°xÀ×ARÑARÐ6SÐV^Ð`k×`qÑ`qÐUrÐsÐ àÐ+¨VÐ4°xÐA]Ð_eÐ6fØÐ+¨VÐ4ð€õ?õ
	õ"õ
"õ4	Wõõ ô.˜ô .õ÷B9kñ 9kðz Ð?ØÐJØÐHØð &ð ð uàð yðÐ õõôl
Ð+ô l
õ`%nõTõ?õ
JõPð
€õðÐ õ"'>ðX —J’JÐCÓDÐ Ø—j’jÐ!RÓSÐ ð Ð8ØÐ3ØÐ4Øð 9àÐcØÐkðÐ õ@ð9FØGKð9Fà'+ð9FàDI÷9F÷x&r   