
    iii                    8   d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	m
Z
 	 ddlmZ dZn# e$ r dZdZY nw xY w	 ddlmZmZ dd	lmZ dd
lmZmZ ddlmZ ddlmZ ddlmZmZ ddlmZm Z  ddl!m"Z"m#Z#m$Z$m%Z% ddl&m'Z'm(Z(m)Z) dZ*n1# e$ r) dZ*dZdZdZdZdZdZdZdZdZdZ dZe+Z"dZ#dZ$dZ%dZ'dZ(dZ)Y nw xY wddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2m3Z3m4Z4m5Z5m6Z6  ej7        e8          Z9dZ:dZ; G d d          Z<d"dZ=d"dZ>d"dZ?e=Z@ G d de2          ZAd#d ZBd#d!ZCdS )$a  
Microsoft Teams platform adapter for Hermes Agent.

Uses the microsoft-teams-apps SDK for authentication and activity processing.
Runs an aiohttp webhook server to receive messages from Teams.
Proactive messaging (send, typing) uses the SDK's App.send() method.

Requires:
    pip install microsoft-teams-apps aiohttp
    TEAMS_CLIENT_ID, TEAMS_CLIENT_SECRET, and TEAMS_TENANT_ID env vars

Configuration in config.yaml:
    platforms:
      teams:
        enabled: true
        extra:
          client_id: "your-client-id"      # or TEAMS_CLIENT_ID env var
          client_secret: "your-secret"      # or TEAMS_CLIENT_SECRET env var
          tenant_id: "your-tenant-id"       # or TEAMS_TENANT_ID env var
          port: 3978                        # or TEAMS_PORT env var
    )annotationsN)AnyDictOptional)webTF)AppActivityContext)ClientOptions)MessageActivityConversationReference)TypingActivityInput)AdaptiveCardInvokeActivity)AdaptiveCardActionCardResponse!AdaptiveCardActionMessageResponse)InvokeResponseAdaptiveCardInvokeResponse)
HttpMethodHttpRequestHttpResponseHttpRouteHandler)AdaptiveCardExecuteAction	TextBlock)PlatformPlatformConfig)MessageDeduplicator)BasePlatformAdapterMessageEventMessageType
SendResultcache_image_from_urli  z/api/messagesc                  :    e Zd ZdZddZddZddZddZddZdS )_AiohttpBridgeAdaptera3  HttpServerAdapter that bridges the Teams SDK into an aiohttp server.

    Without a custom adapter, ``App()`` unconditionally imports fastapi/uvicorn
    and allocates a ``FastAPI()`` instance.  This bridge captures the SDK's
    route registrations and wires them into our own aiohttp ``Application``.
    aiohttp_app'web.Application'c                    || _         d S N)_aiohttp_app)selfr$   s     D/home/ubuntu/.hermes/hermes-agent/plugins/platforms/teams/adapter.py__init__z_AiohttpBridgeAdapter.__init__h   s    '    method'HttpMethod'pathstrhandler'HttpRouteHandler'returnNonec                V    dfd}| j         j                            |||           dS )z2Register an SDK route handler as an aiohttp route.request'web.Request'r3   'web.Response'c                z  K   |                                   d {V }t          | j                  } t          ||                     d {V }|                    dd          }|                    d          }|)t          j        |t          j        |          d          S t          j        |          S )N)bodyheadersstatus   r:   zapplication/json)r<   r:   content_type)r<   )jsondictr;   r   getr   Responsedumps)r6   r:   r;   resultr<   	resp_bodyr1   s         r*   _aiohttp_handlerz>_AiohttpBridgeAdapter.register_route.<locals>._aiohttp_handlern   s       ''''''D7?++G+27;DRY3Z3Z3Z+[+[%[%[%[%[%[%[FZZ#..F

6**I$|!I..!3   
 <v....r,   N)r6   r7   r3   r8   )r(   router	add_route)r)   r-   r/   r1   rF   s      ` r*   register_routez$_AiohttpBridgeAdapter.register_routek   sH    	/ 	/ 	/ 	/ 	/ 	/ 	 **649IJJJJJr,   	directoryc                    d S r'    )r)   r/   rJ   s      r*   serve_staticz"_AiohttpBridgeAdapter.serve_static~   s    r,   portintc                $   K   t          d          )Nz(aiohttp server is managed by the adapter)NotImplementedError)r)   rN   s     r*   startz_AiohttpBridgeAdapter.start   s      !"LMMMr,   c                
   K   d S r'   rL   r)   s    r*   stopz_AiohttpBridgeAdapter.stop   s      r,   N)r$   r%   )r-   r.   r/   r0   r1   r2   r3   r4   )r/   r0   rJ   r0   r3   r4   )rN   rO   r3   r4   r3   r4   )	__name__
__module____qualname____doc__r+   rI   rM   rR   rU   rL   r,   r*   r#   r#   `   s         ( ( ( (K K K K&   N N N N     r,   r#   r3   boolc                     t           ot          S )zDReturn True when all Teams dependencies and credentials are present.)TEAMS_SDK_AVAILABLEAIOHTTP_AVAILABLErL   r,   r*   check_requirementsr_      s    4#44r,   c                J   t          | di           pi }t          j        d          p|                    dd          }t          j        d          p|                    dd          }t          j        d          p|                    dd          }t	          |o|o|          S )	zAReturn True when the config has the minimum required credentials.extraTEAMS_CLIENT_ID	client_id TEAMS_CLIENT_SECRETclient_secretTEAMS_TENANT_ID	tenant_id)getattrosgetenvrA   r[   )configra   rc   rf   rh   s        r*   validate_configrm      s    FGR((.BE	+,,J		+r0J0JII344V		/SU8V8VM	+,,J		+r0J0JI	9m9	:::r,   c                     t          |           S )z7Check whether Teams is configured (env or config.yaml).)rm   )rl   s    r*   is_connectedro      s    6"""r,   c                       e Zd ZdZdZd, fdZd-dZd.d
Zd/dZd0dZ	d1dZ
	 	 d2d3dZ	 	 d4d5d#Zd6d7d$Z	 	 	 d8d9d'Z	 	 d4d:d)Zd;d+Z xZS )<TeamsAdapterz;Microsoft Teams adapter using the microsoft-teams-apps SDK.`m  rl   r   c                   t                                          |t          d                     |j        pi }|                    d          pt          j        dd          | _        |                    d          pt          j        dd          | _        |                    d          pt          j        dd          | _	        t          |                    d	          p&t          j        d
t          t                                        | _        d | _        d | _        t!          d          | _        i | _        d S )Nteamsrc   rb   rd   rf   re   rh   rg   rN   
TEAMS_PORTi  )max_size)superr+   r   ra   rA   rj   rk   
_client_id_client_secret
_tenant_idrO   r0   _DEFAULT_PORT_port_app_runnerr   _dedup
_conv_refs)r)   rl   ra   	__class__s      r*   r+   zTeamsAdapter.__init__   s   '!2!2333"))K00TBI>OQS4T4T#ii88`BIF[]_<`<`))K00TBI>OQS4T4T6**Ybic-FXFX.Y.YZZ
%)	26)4888 +-r,   r3   r[   c           
     x   K   t           s                     ddd           dS t          s                     ddd           dS  j        r j        r j        s                     ddd           dS 	 t          j                    }|j        	                    dd	            t           j         j         j        t          |          t          d
di                     _         j        j        d fd            } j        j        d fd            } j                                         d {V  t          j        |           _         j                                         d {V  t          j         j        d j                  }|                                 d {V  d _                                          t2                              d j        t6                     dS # t8          $ rA}                     dd| d           t2                              d|           Y d }~dS d }~ww xY w)NMISSING_SDKzImicrosoft-teams-apps not installed. Run: pip install microsoft-teams-appsF)	retryablez/aiohttp not installed. Run: pip install aiohttpMISSING_CREDENTIALSzJTEAMS_CLIENT_ID, TEAMS_CLIENT_SECRET, and TEAMS_TENANT_ID are all requiredz/healthc                ,    t          j        d          S )Nok)text)r   rB   )_s    r*   <lambda>z&TeamsAdapter.connect.<locals>.<lambda>   s    CLd<S<S<S r,   z
User-AgentHermes)r;   )rc   rf   rh   http_server_adapterclientctx ActivityContext[MessageActivity]c                B   K                        |            d {V  d S r'   )_on_messager   r)   s    r*   _handle_messagez-TeamsAdapter.connect.<locals>._handle_message   s3      &&s+++++++++++r,   +ActivityContext[AdaptiveCardInvokeActivity]r3   1InvokeResponse[AdaptiveCardActionMessageResponse]c                >   K                        |            d {V S r'   )_on_card_actionr   s    r*   _handle_card_actionz1TeamsAdapter.connect.<locals>._handle_card_action   s/       "11#666666666r,   z0.0.0.0Tz0[teams] Webhook server listening on 0.0.0.0:%d%sCONNECT_FAILEDzTeams connection failed: z[teams] Failed to connect: %s)r   r   )r   r   r3   r   )r]   _set_fatal_errorr^   rx   ry   rz   r   ApplicationrG   add_getr   r#   r
   r}   
on_messageon_card_action
initialize	AppRunnerr~   setupTCPSiter|   rR   _running_mark_connectedloggerinfo_WEBHOOK_PATH	Exceptionerror)r)   r$   r   r   sitees   `     r*   connectzTeamsAdapter.connect   s     " 	!![ "   
 5  	!!A "   
 5 	d&9 	 	!!%\ "   
 51	/++K&&y2S2STTT/"1/$9+$F$F$lH-EFFF  DI Y!, , , , , "!, Y%7 7 7 7 7 &%7 )&&(((((((((=55DL,$$&&&&&&&&&;t|Y
CCD**,, DM  """KKB
  
 4 	 	 	!! /A// "   
 LL8!<<<55555	s   6E6G. .
H986H44H9r4   c                   K   d| _         | j        r&| j                                         d {V  d | _        d | _        |                                  t
                              d           d S )NFz[teams] Disconnected)r   r~   cleanupr}   _mark_disconnectedr   r   rT   s    r*   
disconnectzTeamsAdapter.disconnect   sv      < 	 ,&&(((((((((DL	!!!*+++++r,   r   r   c                  K   |j         }| j        r| j        j        nd}|rt          |j        dd          |k    rdS t          |dd          }|r| j                            |          rdS t          |j        dd          }|r|j        | j	        |<   d}t          |d          r|j        r|j        }d|v r-ddl}|                    dd|                                          }|j        }t          |dd          pd}	|	d	k    rd
}
n|	dk    rd}
n|	dk    rd}
nd
}
|j        }t          |dd          pt          |dd          }t          |dd          pd}|                     |j        t          |dd          pd|
t!          |          |t          |dd          p| j                  }g }g }t          |dd          pg D ]}t          |dd          }t          |dd          pd}|r|                    d          ru	 t'          |           d{V }|r*|                    |           |                    |           # t*          $ r%}t,                              d|           Y d}~d}~ww xY w|rt0          j        nt0          j        }t7          ||||||          }|                     |           d{V  dS )z>Process an incoming Teams message and dispatch to the gateway.Nidrd   r   z<at>r   z<at>[^<]*</at>\s*conversation_typepersonaldm	groupChatgroupchannelaad_object_idnamerh   )chat_id	chat_name	chat_typeuser_id	user_nameguild_idattachmentscontent_urlr>   zimage/z,[teams] Failed to cache image attachment: %s)r   sourcemessage_type
media_urlsmedia_types
message_id)activityr}   r   ri   from_r   is_duplicateconversationconversation_refr   hasattrr   resubstripbuild_sourcer0   rz   
startswithr!   appendr   r   warningr   PHOTOTEXTr   handle_message)r)   r   r   bot_idmsg_idconv_idr   r   conv	conv_typer   from_accountr   r   r   r   r   attr   r>   cachedr   msg_typeevents                           r*   r   zTeamsAdapter._on_message  s~     < "&4 	ghndD99VCCF 4.. 	dk..v66 	F (/t<< 	<'*';DOG$ 8V$$ 	! 	!=DT>>III66.D99??AAD $D"5t<<B	
""II+%%II)##!III  ~,>>a',X\^`BaBaL&$77=2	""GdFD117RLLT;55H # 
 
 
8]D99?R 
	V 
	VC!#}d;;K"3==CL V|66x@@ VV#7#D#DDDDDDDF 9"))&111#**<888  V V VNN#QSTUUUUUUUUV )3H;$$8H!!#
 
 
 !!%(((((((((((s    AI
I1I,,I1r   r0   card'AdaptiveCard''Any'c                2  K   ddl m} | j                            |          }|rJ| j        rC |                                |          }| j        j                            ||           d{V S | j        r!| j                            ||           d{V S dS )zJSend an AdaptiveCard, using a stored ConversationReference when available.r   )MessageActivityInputN)microsoft_teams.apir   r   rA   r}   add_cardactivity_sendersend)r)   r   r   r   conv_refr   s         r*   
_send_cardzTeamsAdapter._send_cardX  s      <<<<<<?&&w// 	7	 	7++--66t<<H277(KKKKKKKKKY 	7666666666tr,   -'ActivityContext[AdaptiveCardInvokeActivity]'3'InvokeResponse[AdaptiveCardActionMessageResponse]'c                  K   ddl m}m} |j        j        j        }|j        pi }|                    dd          }|                    dd          }|r|st          dt          d          	          S t          j        d
d                                          }|r|j        j        }	t          |	dd          pt          |	dd          }
d |                    d          D             }d|vr>|
|vr:t                               d|
           t          dt          d          	          S ddddd}|                    |          }|st          dt          d          	          S  ||          sat          dt%          t'                                          d                              t-          dd          g                    	          S  |||           ddddd }|                    d!d          }|                    d"d          }g }|rM|                    t-          d#dd$%                     |                    t-          d&| d'd                     |r(|                    t-          d(| dd)                     |                    t-          ||         dd$%                     t          dt%          t'                                          d                              |                    	          S )*z4Handle an Adaptive Card Action.Execute button click.r   )resolve_gateway_approvalhas_blocking_approvalhermes_actionrd   session_keyr=   zUnknown action.)value)r<   r:   TEAMS_ALLOWED_USERSr   Nr   c                ^    h | ]*}|                                 |                                 +S rL   )r   ).0uids     r*   	<setcomp>z/TeamsAdapter._on_card_action.<locals>.<setcomp>z  s-    XXX3CIIKKX399;;XXXr,   ,*u3   [teams] Unauthorized card action by %s — ignoringu   ⛔ Not authorized.oncesessionalwaysdeny)approve_onceapprove_sessionapprove_alwaysr   1.4u,   ⚠️ Approval already resolved or expired.Tr   wrapu   ✅ Allowed (once)u   ✅ Allowed (session)u   ✅ Always allowedu
   ❌ Denied)r   r   r   r   cmddesc    ⚠️ Command Approval RequiredBolderr   r  weight```

```Reason: r   r  isSubtle)tools.approvalr   r   r   r   actiondatarA   r   r   rj   rk   r   r   ri   splitr   r   r   r   with_version	with_bodyr   r   )r)   r   r   r   r  r  r   r   allowed_csvr   
clicker_idallowed_ids
choice_mapchoice	label_mapr  r  r:   s                     r*   r   zTeamsAdapter._on_card_actiond  s      	SRRRRRRR#*{ b"55hh}b11 	K 	!6=NOOO    i 5r::@@BB 		<-L EEhQ]_cegIhIhJXX+2C2CC2H2HXXXK+%%*K*G*GTV`aaa%:AVWWW    #(&	
 

 .. 	!6=NOOO   
 %$[11 	!3&..!\%((Y	/]dh i i ijkk      	! f555 ).* 	
 
	 hhub!!xx## 	GKK	'IPT]efffgggKK	'9s'9'9'9EEEFFF 	UKK	'8$'8'8tdSSSTTTI9V#44QQQRRR/"nn11%88BB4HH  
 
 
 	
r,   dangerous commandNcommandr   descriptionmetadataOptional[Dict[str, Any]]r    c                  K   | j         st          dd          S t          |          dk    r|dd         dz   n|}|t          |          dk    r|dd         dz   n||d}t                                          d	                              t          d
dd          t          d| dd          t          d| dd          g                              t          ddi |ddid          t          ddi |ddi          t          ddi |ddi          t          ddi |ddid           g          }	 | 	                    ||           d{V }	|	rt          |	d!d          nd}
t          d|
"          S # t          $ rF}t                              d#|d$           t          dt          |          d%          cY d}~S d}~ww xY w)&z>Send an Adaptive Card approval prompt with Allow/Deny buttons.FTeams app not initializedsuccessr   i  Nz...r=   )r   r  r  r  r  Tr	  r
  r  r  r  r  r  z
Allow Oncehermes_approver   r   positive)titleverbr  stylezAllow Sessionr  )r(  r)  r  zAlways Allowr  Denyr   destructiver   r%  r   z%[teams] send_exec_approval failed: %sexc_infor%  r   r   )r}   r    lenr   r  r  r   with_actionsr   r   ri   r   r   r   r0   )r)   r   r  r   r  r   cmd_previewbtn_data_baser   rD   r   r   s               r*   send_exec_approvalzTeamsAdapter.send_exec_approval  s      y 	Pe3NOOOO03Gt0C0Cgetenu,, ',/LL3,>,>74C4=5((G
 
 NN\%  YAU]^^^9{999EEE7+77dTRRR  
 \&)KMK?NKK$	   ))NMN?<MNN  
 ()MMM?<LMM  
  )CMC?FCC'	  #   	D	K??7D99999999F8>Ht444DJdzBBBB 	K 	K 	KLL@!dLSSSe3q66TJJJJJJJJJ	Ks   AF 
G;G	GGcontentreply_toOptional[str]c                  K   | j         st          dd          S |                     |          }|                     |          }d }|D ]m}	 | j                             ||           d {V }	t          |	dd           }6# t          $ r+}
t          dt          |
          d          cY d }
~
c S d }
~
ww xY wt          d|          S )NFr#  r$  r   Tr0  r-  )r}   r    format_messagetruncate_messager   ri   r   r0   )r)   r   r6  r7  r   	formattedchunkslast_message_idchunkrD   r   s              r*   r   zTeamsAdapter.send  s      y 	Pe3NOOOO''00	&&y11 	O 	OEO#y~~gu========")&$"="= O O O!%s1vvNNNNNNNNNNNO $?CCCCs   2A??
B4	B/'B4/B4c                   K   | j         sd S 	 | j                             |t                                 d {V  d S # t          $ r Y d S w xY wr'   )r}   r   r   r   )r)   r   r   s      r*   send_typingzTeamsAdapter.send_typing  sq      y 	F	)..*=*?*?@@@@@@@@@@@ 	 	 	DD	s   -< 
A
	A
	image_urlcaptionc                  K   | j         st          dd          S 	 dd l}dd l}ddlm}m}	 |                    d          s|                    d          r|}
d}n|                    d	          }|	                    |          d         pd}t          |d
          5 }d| d|                    |                                                                           }
d d d            n# 1 swxY w Y    |||
          } |	                                |          }|r|                    |          }| j                            |          }|r'| j         j                            ||           d {V }n!| j                             ||           d {V }t          dt)          |dd                     S # t*          $ rF}t,                              d|d           t          dt1          |          d          cY d }~S d }~ww xY w)NFr#  r$  r   )
Attachmentr   zhttp://zhttps://z	image/pngzfile://rbzdata:z;base64,)r>   r   Tr   r-  z[teams] send_image failed: %sr.  r0  )r}   r    base64	mimetypesr   rE  r   r   removeprefix
guess_typeopen	b64encodereaddecodeadd_attachmentsadd_textr   rA   r   r   ri   r   r   r   r0   )r)   r   rB  rC  r7  r   rG  rH  rE  r   r   	mime_typer/   f
attachmentr   r   rD   r   s                      r*   
send_imagezTeamsAdapter.send_image  s      y 	Pe3NOOOO	KMMMLLLLLLLL##I.. c)2F2Fz2R2R c''		 !--i88%0066q9H[	$%% c"b)"b"bV=M=Maffhh=W=W=^=^=`=`"b"bKc c c c c c c c c c c c c c c $TTTJ++--==jIIH 6#,,W55**733H A#y8==hQQQQQQQQ#y~~gx@@@@@@@@dwvtT7R7RSSSS 	K 	K 	KLL8!dLKKKe3q66TJJJJJJJJJ	KsD   BF9 A C)F9 )C--F9 0C-1CF9 9
H	;H>H	H	
image_pathc                D   K   |                      ||||           d {V S )N)r   rB  rC  r7  )rT  )r)   r   rU  rC  r7  kwargss         r*   send_image_filezTeamsAdapter.send_image_file9  sM       __ 	 % 
 
 
 
 
 
 
 
 	
r,   r@   c                   K   |d|dS )Nunknown)r   typer   rL   )r)   r   s     r*   get_chat_infozTeamsAdapter.get_chat_infoH  s      wGGGr,   )rl   r   r3   r[   rV   )r   r   r3   r4   )r   r0   r   r   r3   r   )r   r   r3   r   )r  N)r   r0   r  r0   r   r0   r  r0   r   r!  r3   r    )NN)
r   r0   r6  r0   r7  r8  r   r!  r3   r    r'   )r   r0   r   r!  r3   r4   )NNN)r   r0   rB  r0   rC  r8  r7  r8  r   r!  r3   r    )
r   r0   rU  r0   rC  r8  r7  r8  r3   r    )r   r0   r3   r@   )rW   rX   rY   rZ   MAX_MESSAGE_LENGTHr+   r   r   r   r   r   r5  r   rA  rT  rX  r\  __classcell__)r   s   @r*   rq   rq      s       EE- - - - - -J J J JX, , , ,O) O) O) O)b
 
 
 
L
 L
 L
 L
f /-1<K <K <K <K <KD #'-1D D D D D.     "&"&-1(K (K (K (K (K\ "&"&
 
 
 
 
H H H H H H H Hr,   rq   r4   c                 v   ddl m} m}m}m}m}m}m}  | d          }|r |d| d            |dd          sdS  |d	            |d
            |d           t                        |d            |d            |d           t                        |d           t                        |d|pd          }|s |d           dS  |d|	                                            |d | d          pdd          }	|	s |d           dS  |d|		                                            |d | d          pd          }
|
s |d           dS  |d|
	                                           t                        |d            |dd          rS |d | d          pd          }|r, |d|
                    d d                      |d!           n$ |dd           n |d"d#            |d$           t                        |d%            |d&            |d'           dS )(z7Guide the user through Teams setup using the Teams CLI.r   )get_env_valuesave_env_valuepromptprompt_yes_no
print_infoprint_successprint_warningrb   z#Teams: already configured (app ID: )zReconfigure Teams?FNz2You'll need the Teams CLI. If you haven't already:z-  npm install -g @microsoft/teams.cli@previewz  teams loginzAThen expose port 3978 publicly (devtunnel / ngrok / cloudflared),zand create your bot:zM  teams app create --name "Hermes" --endpoint "https://<tunnel>/api/messages"zMThe CLI will print CLIENT_ID, CLIENT_SECRET, and TENANT_ID. Paste them below.z	Client IDrd   )defaultu.   Client ID is required — skipping Teams setupzClient secretre   T)ri  passwordu2   Client secret is required — skipping Teams setupz	Tenant IDrg   u.   Tenant ID is required — skipping Teams setupzDTo find your AAD object ID for the allowlist: teams status --verbosez0Restrict access to specific users? (recommended)z(Allowed AAD object IDs (comma-separated)r    zAllowlist configuredTEAMS_ALLOW_ALL_USERStrueuF   ⚠️  Open access — anyone who can message the bot can command it.z+Teams configuration saved to ~/.hermes/.envz>Install the app in Teams:  teams app install --id <teamsAppId>z1Restart the gateway:       hermes gateway restart)hermes_cli.configra  rb  rc  rd  re  rf  rg  printr   replace)ra  rb  rc  rd  re  rf  rg  existing_idrc   rf   rh   alloweds               r*   interactive_setuprs  N  sm                      - 122K 
GGGGHHH}1599 	FJCDDDJ>???J	GGGJRSSSJ%&&&Jbccc	GGGJ^___	GGG{K,=2>>>I FGGGN$ioo&7&7888F?MMBW4X4X4^\^imnnnM JKKKN(-*=*=*?*?@@@{MM:K,L,L,RPRSSSI FGGGN$ioo&7&7888	GGGJUVVV}GNN `&6!M"788>B
 
 
  	6N0'//#r2J2JKKKM01111N0"5555.777^___	GGGM?@@@JOPPPJBCCCCCr,   c                |    |                      ddd t          t          t          g ddt          dddd	d
d           dS )u:   Plugin entry point — called by the Hermes plugin system.rt   zMicrosoft Teamsc                     t          |           S r'   )rq   )cfgs    r*   r   zregister.<locals>.<lambda>  s    L$5$5 r,   )rb   re   rg   z(pip install microsoft-teams-apps aiohttpr   rl  rr   u   💼Tu   You are chatting via Microsoft Teams. Teams renders a subset of markdown — bold (**text**), italic (*text*), and inline code (`code`) work, but complex tables or raw HTML do not. Keep responses clear and professional.)r   labeladapter_factorycheck_fnrm   ro   required_envinstall_hintsetup_fnallowed_users_envallow_all_envmax_message_lengthemojiallow_update_commandplatform_hintN)register_platformr_   rm   ro   rs  )r   s    r*   registerr    sa    55#'!RRR?"/- !0)      r,   r]  rV   )DrZ   
__future__r   asyncior?   loggingrj   typingr   r   r   aiohttpr   r^   ImportErrormicrosoft_teams.appsr   r	   "microsoft_teams.common.http.clientr
   r   r   r   %microsoft_teams.api.activities.typingr   3microsoft_teams.api.activities.invoke.adaptive_cardr   (microsoft_teams.api.models.adaptive_cardr   r   *microsoft_teams.api.models.invoke_responser   r   !microsoft_teams.apps.http.adapterr   r   r   r   microsoft_teams.cardsr   r   r   r]   r0   gateway.configr   r   gateway.platforms.helpersr   gateway.platforms.baser   r   r   r    r!   	getLoggerrW   r   r{   r   r#   r_   rm   ro   check_teams_requirementsrq   rs  r  rL   r,   r*   <module>r     s   , # " " " " "    				 & & & & & & & & & &   
CCC'99999999@@@@@@JJJJJJJJIIIIII^^^^^^        feeeeeee            MLLLLLLLLL   M
COO !%%)"(,%!%NJKLLMIII'* 4 3 3 3 3 3 3 3 9 9 9 9 9 9              
	8	$	$% % % % % % % %P5 5 5 5
; ; ; ;# # # # . jH jH jH jH jH& jH jH jH^BD BD BD BDN     s   - 	99A
B +B65B6