Skip to content

Commit 8ec194a

Browse files
aadamgoughAdam Gough
andauthored
feat(tools): added support for ms teams attachments (#412)
* added support for attachments in teams * ran linter * fixed small error * run lint * removed comments --------- Co-authored-by: Adam Gough <adamgough@Adams-MacBook-Pro.local>
1 parent 950e055 commit 8ec194a

File tree

6 files changed

+182
-41
lines changed

6 files changed

+182
-41
lines changed

apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/file-selector/components/teams-message-selector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,8 @@ export function TeamsMessageSelector({
381381
setSelectedChannelId(channel.channelId || '')
382382
setSelectedChatId('')
383383
setSelectedMessage(channel)
384-
setSelectedMessageId(channel.id)
385-
onChange(channel.id, channel)
384+
setSelectedMessageId(channel.channelId || '')
385+
onChange(channel.channelId || '', channel)
386386
onMessageInfoChange?.(channel)
387387
setOpen(false)
388388
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { MicrosoftTeamsAttachment } from './types'
2+
3+
/**
4+
* Transform raw attachment data from Microsoft Graph API
5+
*/
6+
function transformAttachment(rawAttachment: any): MicrosoftTeamsAttachment {
7+
return {
8+
id: rawAttachment.id,
9+
contentType: rawAttachment.contentType,
10+
contentUrl: rawAttachment.contentUrl,
11+
content: rawAttachment.content,
12+
name: rawAttachment.name,
13+
thumbnailUrl: rawAttachment.thumbnailUrl,
14+
size: rawAttachment.size,
15+
sourceUrl: rawAttachment.sourceUrl,
16+
providerType: rawAttachment.providerType,
17+
item: rawAttachment.item,
18+
}
19+
}
20+
21+
/**
22+
* Extract attachments from message data
23+
* Returns all attachments without any content processing
24+
*/
25+
export function extractMessageAttachments(message: any): MicrosoftTeamsAttachment[] {
26+
const attachments = (message.attachments || []).map(transformAttachment)
27+
28+
return attachments
29+
}

apps/sim/tools/microsoft_teams/read_channel.ts

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
import { createLogger } from '@/lib/logs/console-logger'
12
import type { ToolConfig } from '../types'
3+
import { extractMessageAttachments } from './attachment-utils'
24
import type { MicrosoftTeamsReadResponse, MicrosoftTeamsToolParams } from './types'
35

6+
const logger = createLogger('MicrosoftTeamsReadChannel')
7+
48
export const readChannelTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeamsReadResponse> = {
59
id: 'microsoft_teams_read_channel',
610
name: 'Read Microsoft Teams Channel',
711
description: 'Read content from a Microsoft Teams channel',
8-
version: '1.0',
12+
version: '1.1',
913
oauth: {
1014
required: true,
1115
provider: 'microsoft-teams',
@@ -60,10 +64,16 @@ export const readChannelTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeam
6064
}
6165
},
6266
},
63-
transformResponse: async (response: Response) => {
67+
transformResponse: async (response: Response, params?: MicrosoftTeamsToolParams) => {
6468
if (!response.ok) {
6569
const errorText = await response.text()
66-
throw new Error(`Failed to read Microsoft Teams channel: ${errorText}`)
70+
logger.error(
71+
`Microsoft Teams channel API error: ${response.status} ${response.statusText}`,
72+
errorText
73+
)
74+
throw new Error(
75+
`Failed to read Microsoft Teams channel: ${response.status} ${response.statusText} - ${errorText}`
76+
)
6777
}
6878

6979
const data = await response.json()
@@ -81,36 +91,88 @@ export const readChannelTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeam
8191
channelId: '',
8292
messageCount: 0,
8393
messages: [],
94+
totalAttachments: 0,
95+
attachmentTypes: [],
8496
},
8597
},
8698
}
8799
}
88100

89-
// Format the messages into a readable text
90-
const formattedMessages = messages
91-
.map((message: any) => {
101+
if (!params?.teamId || !params?.channelId) {
102+
throw new Error('Missing required parameters: teamId and channelId')
103+
}
104+
// Process messages with attachments
105+
const processedMessages = messages.map((message: any, index: number) => {
106+
try {
92107
const content = message.body?.content || 'No content'
93-
const sender = message.from?.user?.displayName || 'Unknown sender'
94-
const timestamp = message.createdDateTime
95-
? new Date(message.createdDateTime).toLocaleString()
108+
const messageId = message.id
109+
110+
const attachments = extractMessageAttachments(message)
111+
112+
let sender = 'Unknown'
113+
if (message.from?.user?.displayName) {
114+
sender = message.from.user.displayName
115+
} else if (message.messageType === 'systemEventMessage') {
116+
sender = 'System'
117+
}
118+
119+
return {
120+
id: messageId,
121+
content: content,
122+
sender,
123+
timestamp: message.createdDateTime,
124+
messageType: message.messageType || 'message',
125+
attachments,
126+
}
127+
} catch (error) {
128+
logger.error(`Error processing message at index ${index}:`, error)
129+
return {
130+
id: message.id || `unknown-${index}`,
131+
content: 'Error processing message',
132+
sender: 'Unknown',
133+
timestamp: message.createdDateTime || new Date().toISOString(),
134+
messageType: 'error',
135+
attachments: [],
136+
}
137+
}
138+
})
139+
140+
// Format the messages into a readable text (no attachment info in content)
141+
const formattedMessages = processedMessages
142+
.map((message: any) => {
143+
const sender = message.sender
144+
const timestamp = message.timestamp
145+
? new Date(message.timestamp).toLocaleString()
96146
: 'Unknown time'
97147

98-
return `[${timestamp}] ${sender}: ${content}`
148+
return `[${timestamp}] ${sender}: ${message.content}`
99149
})
100150
.join('\n\n')
101151

152+
// Calculate attachment statistics
153+
const allAttachments = processedMessages.flatMap((msg: any) => msg.attachments || [])
154+
const attachmentTypes: string[] = []
155+
const seenTypes = new Set<string>()
156+
157+
allAttachments.forEach((att: any) => {
158+
if (
159+
att.contentType &&
160+
typeof att.contentType === 'string' &&
161+
!seenTypes.has(att.contentType)
162+
) {
163+
attachmentTypes.push(att.contentType)
164+
seenTypes.add(att.contentType)
165+
}
166+
})
167+
102168
// Create document metadata
103169
const metadata = {
104-
teamId: messages[0]?.channelIdentity?.teamId || '',
105-
channelId: messages[0]?.channelIdentity?.channelId || '',
170+
teamId: messages[0]?.channelIdentity?.teamId || params.teamId || '',
171+
channelId: messages[0]?.channelIdentity?.channelId || params.channelId || '',
106172
messageCount: messages.length,
107-
messages: messages.map((msg: any) => ({
108-
id: msg.id,
109-
content: msg.body?.content || '',
110-
sender: msg.from?.user?.displayName || 'Unknown',
111-
timestamp: msg.createdDateTime,
112-
messageType: msg.messageType || 'message',
113-
})),
173+
totalAttachments: allAttachments.length,
174+
attachmentTypes,
175+
messages: processedMessages,
114176
}
115177

116178
return {

apps/sim/tools/microsoft_teams/read_chat.ts

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { ToolConfig } from '../types'
2+
import { extractMessageAttachments } from './attachment-utils'
23
import type { MicrosoftTeamsReadResponse, MicrosoftTeamsToolParams } from './types'
34

45
export const readChatTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeamsReadResponse> = {
56
id: 'microsoft_teams_read_chat',
67
name: 'Read Microsoft Teams Chat',
78
description: 'Read content from a Microsoft Teams chat',
8-
version: '1.0',
9+
version: '1.1',
910
oauth: {
1011
required: true,
1112
provider: 'microsoft-teams',
@@ -44,7 +45,7 @@ export const readChatTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeamsRe
4445
}
4546
},
4647
},
47-
transformResponse: async (response: Response) => {
48+
transformResponse: async (response: Response, params?: MicrosoftTeamsToolParams) => {
4849
if (!response.ok) {
4950
const errorText = await response.text()
5051
throw new Error(`Failed to read Microsoft Teams chat: ${errorText}`)
@@ -64,35 +65,70 @@ export const readChatTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTeamsRe
6465
chatId: '',
6566
messageCount: 0,
6667
messages: [],
68+
totalAttachments: 0,
69+
attachmentTypes: [],
6770
},
6871
},
6972
}
7073
}
7174

72-
// Format the messages into a readable text
73-
const formattedMessages = messages
75+
if (!params?.chatId) {
76+
throw new Error('Missing required parameter: chatId')
77+
}
78+
79+
// Process messages with attachments
80+
const processedMessages = messages.map((message: any) => {
81+
const content = message.body?.content || 'No content'
82+
const messageId = message.id
83+
84+
// Extract attachments without any content processing
85+
const attachments = extractMessageAttachments(message)
86+
87+
return {
88+
id: messageId,
89+
content: content, // Keep original content without modification
90+
sender: message.from?.user?.displayName || 'Unknown',
91+
timestamp: message.createdDateTime,
92+
messageType: message.messageType || 'message',
93+
attachments, // Attachments only stored here
94+
}
95+
})
96+
97+
// Format the messages into a readable text (no attachment info in content)
98+
const formattedMessages = processedMessages
7499
.map((message: any) => {
75-
const content = message.body?.content || 'No content'
76-
const sender = message.from?.user?.displayName || 'Unknown sender'
77-
const timestamp = message.createdDateTime
78-
? new Date(message.createdDateTime).toLocaleString()
100+
const sender = message.sender
101+
const timestamp = message.timestamp
102+
? new Date(message.timestamp).toLocaleString()
79103
: 'Unknown time'
80104

81-
return `[${timestamp}] ${sender}: ${content}`
105+
return `[${timestamp}] ${sender}: ${message.content}`
82106
})
83107
.join('\n\n')
84108

109+
// Calculate attachment statistics
110+
const allAttachments = processedMessages.flatMap((msg: any) => msg.attachments || [])
111+
const attachmentTypes: string[] = []
112+
const seenTypes = new Set<string>()
113+
114+
allAttachments.forEach((att: any) => {
115+
if (
116+
att.contentType &&
117+
typeof att.contentType === 'string' &&
118+
!seenTypes.has(att.contentType)
119+
) {
120+
attachmentTypes.push(att.contentType)
121+
seenTypes.add(att.contentType)
122+
}
123+
})
124+
85125
// Create document metadata
86126
const metadata = {
87-
chatId: messages[0]?.chatId || '',
127+
chatId: messages[0]?.chatId || params.chatId || '',
88128
messageCount: messages.length,
89-
messages: messages.map((msg: any) => ({
90-
id: msg.id,
91-
content: msg.body?.content || '',
92-
sender: msg.from?.user?.displayName || 'Unknown',
93-
timestamp: msg.createdDateTime,
94-
messageType: msg.messageType || 'message',
95-
})),
129+
totalAttachments: allAttachments.length,
130+
attachmentTypes,
131+
messages: processedMessages,
96132
}
97133

98134
return {

apps/sim/tools/microsoft_teams/types.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
import type { ToolResponse } from '../types'
22

3+
export interface MicrosoftTeamsAttachment {
4+
id: string
5+
contentType: string
6+
contentUrl?: string
7+
content?: string
8+
name?: string
9+
thumbnailUrl?: string
10+
size?: number
11+
sourceUrl?: string
12+
providerType?: string
13+
item?: any
14+
}
15+
316
export interface MicrosoftTeamsMetadata {
417
messageId?: string
518
channelId?: string
619
teamId?: string
720
chatId?: string
821
content?: string
922
createdTime?: string
10-
modifiedTime?: string
1123
url?: string
1224
messageCount?: number
1325
messages?: Array<{
@@ -16,7 +28,11 @@ export interface MicrosoftTeamsMetadata {
1628
sender: string
1729
timestamp: string
1830
messageType: string
31+
attachments?: MicrosoftTeamsAttachment[]
1932
}>
33+
// Global attachments summary
34+
totalAttachments?: number
35+
attachmentTypes?: string[]
2036
}
2137

2238
export interface MicrosoftTeamsReadResponse extends ToolResponse {

apps/sim/tools/microsoft_teams/write_channel.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,9 @@ export const writeChannelTool: ToolConfig<MicrosoftTeamsToolParams, MicrosoftTea
4444
throw new Error('Channel ID is required')
4545
}
4646

47-
// URL encode the IDs to handle special characters
4847
const encodedTeamId = encodeURIComponent(teamId)
4948
const encodedChannelId = encodeURIComponent(channelId)
5049

51-
// Send a message to a channel
5250
const url = `https://graph.microsoft.com/v1.0/teams/${encodedTeamId}/channels/${encodedChannelId}/messages`
5351

5452
return url

0 commit comments

Comments
 (0)