diff --git a/apps/sim/app/api/tools/microsoft_teams/write_channel/route.ts b/apps/sim/app/api/tools/microsoft_teams/write_channel/route.ts
index fad1296281..c014541a44 100644
--- a/apps/sim/app/api/tools/microsoft_teams/write_channel/route.ts
+++ b/apps/sim/app/api/tools/microsoft_teams/write_channel/route.ts
@@ -4,7 +4,7 @@ import { checkHybridAuth } from '@/lib/auth/hybrid'
import { createLogger } from '@/lib/logs/console/logger'
import { downloadFileFromStorage, processFilesToUserFiles } from '@/lib/uploads/file-processing'
import { generateRequestId } from '@/lib/utils'
-import { resolveMentionsForChannel } from '@/tools/microsoft_teams/utils'
+import { resolveMentionsForChannel, type TeamsMention } from '@/tools/microsoft_teams/utils'
export const dynamic = 'force-dynamic'
@@ -142,11 +142,7 @@ export async function POST(request: NextRequest) {
let messageContent = validatedData.content
let contentType: 'text' | 'html' = 'text'
- const mentionEntities: Array<{
- type: 'mention'
- mentioned: { id: string; name: string }
- text: string
- }> = []
+ const mentionEntities: TeamsMention[] = []
try {
const mentionResult = await resolveMentionsForChannel(
@@ -158,8 +154,9 @@ export async function POST(request: NextRequest) {
if (mentionResult.hasMentions) {
contentType = 'html'
- mentionEntities.push(...mentionResult.entities)
- logger.info(`[${requestId}] Resolved ${mentionResult.entities.length} mention(s)`)
+ messageContent = mentionResult.updatedContent
+ mentionEntities.push(...mentionResult.mentions)
+ logger.info(`[${requestId}] Resolved ${mentionResult.mentions.length} mention(s)`)
}
} catch (error) {
logger.warn(`[${requestId}] Failed to resolve mentions, continuing without them:`, error)
@@ -170,7 +167,7 @@ export async function POST(request: NextRequest) {
const attachmentTags = attachments
.map((att) => ``)
.join(' ')
- messageContent = `${validatedData.content}
${attachmentTags}`
+ messageContent = `${messageContent}
${attachmentTags}`
}
const messageBody: {
@@ -179,11 +176,7 @@ export async function POST(request: NextRequest) {
content: string
}
attachments?: any[]
- mentions?: Array<{
- type: 'mention'
- mentioned: { id: string; name: string }
- text: string
- }>
+ mentions?: TeamsMention[]
} = {
body: {
contentType,
diff --git a/apps/sim/app/api/tools/microsoft_teams/write_chat/route.ts b/apps/sim/app/api/tools/microsoft_teams/write_chat/route.ts
index 445edf480c..f0156e5502 100644
--- a/apps/sim/app/api/tools/microsoft_teams/write_chat/route.ts
+++ b/apps/sim/app/api/tools/microsoft_teams/write_chat/route.ts
@@ -4,7 +4,7 @@ import { checkHybridAuth } from '@/lib/auth/hybrid'
import { createLogger } from '@/lib/logs/console/logger'
import { downloadFileFromStorage, processFilesToUserFiles } from '@/lib/uploads/file-processing'
import { generateRequestId } from '@/lib/utils'
-import { resolveMentionsForChat } from '@/tools/microsoft_teams/utils'
+import { resolveMentionsForChat, type TeamsMention } from '@/tools/microsoft_teams/utils'
export const dynamic = 'force-dynamic'
@@ -140,11 +140,7 @@ export async function POST(request: NextRequest) {
let messageContent = validatedData.content
let contentType: 'text' | 'html' = 'text'
- const mentionEntities: Array<{
- type: 'mention'
- mentioned: { id: string; name: string }
- text: string
- }> = []
+ const mentionEntities: TeamsMention[] = []
try {
const mentionResult = await resolveMentionsForChat(
@@ -155,8 +151,9 @@ export async function POST(request: NextRequest) {
if (mentionResult.hasMentions) {
contentType = 'html'
- mentionEntities.push(...mentionResult.entities)
- logger.info(`[${requestId}] Resolved ${mentionResult.entities.length} mention(s)`)
+ messageContent = mentionResult.updatedContent
+ mentionEntities.push(...mentionResult.mentions)
+ logger.info(`[${requestId}] Resolved ${mentionResult.mentions.length} mention(s)`)
}
} catch (error) {
logger.warn(`[${requestId}] Failed to resolve mentions, continuing without them:`, error)
@@ -167,7 +164,7 @@ export async function POST(request: NextRequest) {
const attachmentTags = attachments
.map((att) => ``)
.join(' ')
- messageContent = `${validatedData.content}
${attachmentTags}`
+ messageContent = `${messageContent}
${attachmentTags}`
}
const messageBody: {
@@ -176,11 +173,7 @@ export async function POST(request: NextRequest) {
content: string
}
attachments?: any[]
- mentions?: Array<{
- type: 'mention'
- mentioned: { id: string; name: string }
- text: string
- }>
+ mentions?: TeamsMention[]
} = {
body: {
contentType,
diff --git a/apps/sim/tools/microsoft_teams/utils.ts b/apps/sim/tools/microsoft_teams/utils.ts
index 20b6939318..e8b03d8a53 100644
--- a/apps/sim/tools/microsoft_teams/utils.ts
+++ b/apps/sim/tools/microsoft_teams/utils.ts
@@ -7,8 +7,7 @@ const logger = createLogger('MicrosoftTeamsUtils')
interface ParsedMention {
name: string
fullTag: string
- startIndex: number
- endIndex: number
+ mentionId: number
}
interface TeamMember {
@@ -17,13 +16,22 @@ interface TeamMember {
userIdentityType?: string
}
-export interface MentionEntity {
- type: 'mention'
- mentioned: {
- id: string
- name: string
- }
- text: string
+export interface TeamsMention {
+ id: number
+ mentionText: string
+ mentioned:
+ | {
+ id: string
+ name: string
+ userIdentityType?: string
+ }
+ | {
+ application: {
+ displayName: string
+ id: string
+ applicationIdentityType: 'bot'
+ }
+ }
}
/**
@@ -126,6 +134,7 @@ function parseMentions(content: string): ParsedMention[] {
const mentions: ParsedMention[] = []
const mentionRegex = /([^<]+)<\/at>/gi
let match: RegExpExecArray | null
+ let mentionId = 0
while ((match = mentionRegex.exec(content)) !== null) {
const name = match[1].trim()
@@ -133,8 +142,7 @@ function parseMentions(content: string): ParsedMention[] {
mentions.push({
name,
fullTag: match[0],
- startIndex: match.index,
- endIndex: match.index + match[0].length,
+ mentionId: mentionId++,
})
}
}
@@ -201,40 +209,63 @@ export async function resolveMentionsForChat(
content: string,
chatId: string,
accessToken: string
-): Promise<{ entities: MentionEntity[]; hasMentions: boolean }> {
+): Promise<{ mentions: TeamsMention[]; hasMentions: boolean; updatedContent: string }> {
const parsedMentions = parseMentions(content)
if (parsedMentions.length === 0) {
- return { entities: [], hasMentions: false }
+ return { mentions: [], hasMentions: false, updatedContent: content }
}
const members = await fetchChatMembers(chatId, accessToken)
- const entities: MentionEntity[] = []
- const resolvedNames = new Set()
+ const mentions: TeamsMention[] = []
+ const resolvedTags = new Set()
+ let updatedContent = content
for (const mention of parsedMentions) {
- if (resolvedNames.has(mention.fullTag)) {
+ if (resolvedTags.has(mention.fullTag)) {
continue
}
const member = findMemberByName(members, mention.name)
if (member) {
- entities.push({
- type: 'mention',
- mentioned: {
- id: member.id,
- name: member.displayName,
- },
- text: mention.fullTag,
- })
- resolvedNames.add(mention.fullTag)
+ const isBot = member.userIdentityType === 'bot'
+
+ if (isBot) {
+ mentions.push({
+ id: mention.mentionId,
+ mentionText: mention.name,
+ mentioned: {
+ application: {
+ displayName: member.displayName,
+ id: member.id,
+ applicationIdentityType: 'bot',
+ },
+ },
+ })
+ } else {
+ mentions.push({
+ id: mention.mentionId,
+ mentionText: mention.name,
+ mentioned: {
+ id: member.id,
+ name: member.displayName,
+ userIdentityType: member.userIdentityType,
+ },
+ })
+ }
+ resolvedTags.add(mention.fullTag)
+ updatedContent = updatedContent.replace(
+ mention.fullTag,
+ `${mention.name}`
+ )
}
}
return {
- entities,
- hasMentions: entities.length > 0,
+ mentions,
+ hasMentions: mentions.length > 0,
+ updatedContent,
}
}
@@ -243,39 +274,62 @@ export async function resolveMentionsForChannel(
teamId: string,
channelId: string,
accessToken: string
-): Promise<{ entities: MentionEntity[]; hasMentions: boolean }> {
+): Promise<{ mentions: TeamsMention[]; hasMentions: boolean; updatedContent: string }> {
const parsedMentions = parseMentions(content)
if (parsedMentions.length === 0) {
- return { entities: [], hasMentions: false }
+ return { mentions: [], hasMentions: false, updatedContent: content }
}
const members = await fetchChannelMembers(teamId, channelId, accessToken)
- const entities: MentionEntity[] = []
- const resolvedNames = new Set()
+ const mentions: TeamsMention[] = []
+ const resolvedTags = new Set()
+ let updatedContent = content
for (const mention of parsedMentions) {
- if (resolvedNames.has(mention.fullTag)) {
+ if (resolvedTags.has(mention.fullTag)) {
continue
}
const member = findMemberByName(members, mention.name)
if (member) {
- entities.push({
- type: 'mention',
- mentioned: {
- id: member.id,
- name: member.displayName,
- },
- text: mention.fullTag,
- })
- resolvedNames.add(mention.fullTag)
+ const isBot = member.userIdentityType === 'bot'
+
+ if (isBot) {
+ mentions.push({
+ id: mention.mentionId,
+ mentionText: mention.name,
+ mentioned: {
+ application: {
+ displayName: member.displayName,
+ id: member.id,
+ applicationIdentityType: 'bot',
+ },
+ },
+ })
+ } else {
+ mentions.push({
+ id: mention.mentionId,
+ mentionText: mention.name,
+ mentioned: {
+ id: member.id,
+ name: member.displayName,
+ userIdentityType: member.userIdentityType,
+ },
+ })
+ }
+ resolvedTags.add(mention.fullTag)
+ updatedContent = updatedContent.replace(
+ mention.fullTag,
+ `${mention.name}`
+ )
}
}
return {
- entities,
- hasMentions: entities.length > 0,
+ mentions,
+ hasMentions: mentions.length > 0,
+ updatedContent,
}
}