@@ -52,6 +52,37 @@ import { recordMSTeamsSentMessage, wasMSTeamsMessageSent } from "../sent-message
5252import { resolveMSTeamsSenderAccess } from "./access.js" ;
5353import { resolveMSTeamsInboundMedia } from "./inbound-media.js" ;
5454
55+ function buildStoredConversationReference ( params : {
56+ activity : MSTeamsTurnContext [ "activity" ] ;
57+ conversationId : string ;
58+ conversationType : string ;
59+ teamId ?: string ;
60+ } ) : StoredConversationReference {
61+ const { activity, conversationId, conversationType, teamId } = params ;
62+ const from = activity . from ;
63+ const conversation = activity . conversation ;
64+ const agent = activity . recipient ;
65+ const clientInfo = activity . entities ?. find ( ( e ) => e . type === "clientInfo" ) as
66+ | { timezone ?: string }
67+ | undefined ;
68+ return {
69+ activityId : activity . id ,
70+ user : from ? { id : from . id , name : from . name , aadObjectId : from . aadObjectId } : undefined ,
71+ agent,
72+ bot : agent ? { id : agent . id , name : agent . name } : undefined ,
73+ conversation : {
74+ id : conversationId ,
75+ conversationType,
76+ tenantId : conversation ?. tenantId ,
77+ } ,
78+ teamId,
79+ channelId : activity . channelId ,
80+ serviceUrl : activity . serviceUrl ,
81+ locale : activity . locale ,
82+ ...( clientInfo ?. timezone ? { timezone : clientInfo . timezone } : { } ) ,
83+ } ;
84+ }
85+
5586export function createMSTeamsMessageHandler ( deps : MSTeamsMessageHandlerDeps ) {
5687 const {
5788 cfg,
@@ -140,6 +171,12 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
140171 const conversationMessageId = extractMSTeamsConversationMessageId ( rawConversationId ) ;
141172 const conversationType = conversation ?. conversationType ?? "personal" ;
142173 const teamId = activity . channelData ?. team ?. id ;
174+ const conversationRef = buildStoredConversationReference ( {
175+ activity,
176+ conversationId,
177+ conversationType,
178+ teamId,
179+ } ) ;
143180
144181 const {
145182 dmPolicy,
@@ -177,6 +214,11 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
177214 allowNameMatching,
178215 } ) ;
179216 if ( access . decision === "pairing" ) {
217+ conversationStore . upsert ( conversationId , conversationRef ) . catch ( ( err ) => {
218+ log . debug ?.( "failed to save conversation reference" , {
219+ error : formatUnknownError ( err ) ,
220+ } ) ;
221+ } ) ;
180222 const request = await pairing . upsertPairingRequest ( {
181223 id : senderId ,
182224 meta : { name : senderName } ,
@@ -306,30 +348,6 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
306348 return ;
307349 }
308350
309- // Extract clientInfo entity (Teams sends this on every activity with timezone, locale, etc.)
310- const clientInfo = activity . entities ?. find ( ( e ) => e . type === "clientInfo" ) as
311- | { timezone ?: string ; locale ?: string ; country ?: string ; platform ?: string }
312- | undefined ;
313-
314- // Build conversation reference for proactive replies.
315- const agent = activity . recipient ;
316- const conversationRef : StoredConversationReference = {
317- activityId : activity . id ,
318- user : { id : from . id , name : from . name , aadObjectId : from . aadObjectId } ,
319- agent,
320- bot : agent ? { id : agent . id , name : agent . name } : undefined ,
321- conversation : {
322- id : conversationId ,
323- conversationType,
324- tenantId : conversation ?. tenantId ,
325- } ,
326- teamId,
327- channelId : activity . channelId ,
328- serviceUrl : activity . serviceUrl ,
329- locale : activity . locale ,
330- // Only set timezone if present (preserve previously stored value on next upsert)
331- ...( clientInfo ?. timezone ? { timezone : clientInfo . timezone } : { } ) ,
332- } ;
333351 conversationStore . upsert ( conversationId , conversationRef ) . catch ( ( err ) => {
334352 log . debug ?.( "failed to save conversation reference" , {
335353 error : formatUnknownError ( err ) ,
@@ -642,8 +660,10 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
642660 // Use Teams clientInfo timezone if no explicit userTimezone is configured.
643661 // This ensures the agent knows the sender's timezone for time-aware responses
644662 // and proactive sends within the same session.
645- // Apply Teams clientInfo timezone if no explicit userTimezone is configured.
646- const senderTimezone = clientInfo ?. timezone || conversationRef . timezone ;
663+ const activityClientInfo = activity . entities ?. find ( ( e ) => e . type === "clientInfo" ) as
664+ | { timezone ?: string }
665+ | undefined ;
666+ const senderTimezone = activityClientInfo ?. timezone || conversationRef . timezone ;
647667 const configOverride =
648668 senderTimezone && ! cfg . agents ?. defaults ?. userTimezone
649669 ? {
0 commit comments