lex-microsoft_teams 0.6.49 → 0.6.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/lib/legion/extensions/microsoft_teams/actors/api_ingest.rb +8 -13
- data/lib/legion/extensions/microsoft_teams/actors/channel_poller.rb +5 -18
- data/lib/legion/extensions/microsoft_teams/actors/direct_chat_poller.rb +4 -13
- data/lib/legion/extensions/microsoft_teams/actors/incremental_sync.rb +6 -17
- data/lib/legion/extensions/microsoft_teams/actors/meeting_ingest.rb +3 -10
- data/lib/legion/extensions/microsoft_teams/actors/observed_chat_poller.rb +4 -14
- data/lib/legion/extensions/microsoft_teams/actors/presence_poller.rb +3 -6
- data/lib/legion/extensions/microsoft_teams/actors/profile_ingest.rb +5 -10
- data/lib/legion/extensions/microsoft_teams/errors.rb +84 -0
- data/lib/legion/extensions/microsoft_teams/faraday/retry_after.rb +209 -0
- data/lib/legion/extensions/microsoft_teams/faraday/throttle_circuit.rb +150 -0
- data/lib/legion/extensions/microsoft_teams/helpers/client.rb +80 -3
- data/lib/legion/extensions/microsoft_teams/helpers/graph_cache.rb +65 -0
- data/lib/legion/extensions/microsoft_teams/helpers/graph_client.rb +20 -0
- data/lib/legion/extensions/microsoft_teams/runners/api_ingest.rb +34 -22
- data/lib/legion/extensions/microsoft_teams/runners/app_installations.rb +17 -7
- data/lib/legion/extensions/microsoft_teams/runners/call_events.rb +70 -11
- data/lib/legion/extensions/microsoft_teams/runners/channel_messages.rb +67 -12
- data/lib/legion/extensions/microsoft_teams/runners/channels.rb +12 -4
- data/lib/legion/extensions/microsoft_teams/runners/chats.rb +42 -6
- data/lib/legion/extensions/microsoft_teams/runners/files.rb +72 -9
- data/lib/legion/extensions/microsoft_teams/runners/meeting_artifacts.rb +32 -5
- data/lib/legion/extensions/microsoft_teams/runners/meetings.rb +34 -4
- data/lib/legion/extensions/microsoft_teams/runners/messages.rb +73 -15
- data/lib/legion/extensions/microsoft_teams/runners/people.rb +14 -2
- data/lib/legion/extensions/microsoft_teams/runners/profile_ingest.rb +23 -11
- data/lib/legion/extensions/microsoft_teams/runners/teams.rb +46 -8
- data/lib/legion/extensions/microsoft_teams/runners/transcripts.rb +35 -6
- data/lib/legion/extensions/microsoft_teams/version.rb +1 -1
- data/lib/legion/extensions/microsoft_teams.rb +59 -0
- metadata +5 -1
|
@@ -15,29 +15,39 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_installed_apps_for_user,
|
|
18
|
-
desc: 'List Teams apps installed for a user',
|
|
18
|
+
desc: 'List Teams apps installed for a user with expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_installed_apps_for_user',
|
|
20
20
|
mcp_category: 'teams_apps',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { expand: { type: 'string',
|
|
24
|
+
description: 'Expand related entities (e.g. teamsApp)' } },
|
|
25
|
+
required: [] },
|
|
23
26
|
trigger_words: %w[apps installed]
|
|
24
27
|
|
|
25
|
-
def list_installed_apps_for_user(user_id: 'me', **)
|
|
26
|
-
|
|
28
|
+
def list_installed_apps_for_user(user_id: 'me', expand: nil, **)
|
|
29
|
+
params = {}
|
|
30
|
+
params['$expand'] = expand if expand
|
|
31
|
+
response = graph_connection(**).get("#{user_path(user_id)}/teamwork/installedApps", params)
|
|
27
32
|
{ result: response.body }
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
definition :list_installed_apps_in_chat,
|
|
31
|
-
desc: 'List Teams apps installed in a specific chat',
|
|
36
|
+
desc: 'List Teams apps installed in a specific chat with expand support',
|
|
32
37
|
mcp_prefix: 'teams.list_installed_apps_in_chat',
|
|
33
38
|
mcp_category: 'teams_apps',
|
|
34
39
|
mcp_tier: :low,
|
|
35
40
|
idempotent: true,
|
|
36
|
-
inputs: { properties: { chat_id: { type: 'string' }
|
|
41
|
+
inputs: { properties: { chat_id: { type: 'string' },
|
|
42
|
+
expand: { type: 'string',
|
|
43
|
+
description: 'Expand related entities (e.g. teamsApp)' } },
|
|
44
|
+
required: ['chat_id'] },
|
|
37
45
|
trigger_words: %w[apps chat]
|
|
38
46
|
|
|
39
|
-
def list_installed_apps_in_chat(chat_id:, **)
|
|
40
|
-
|
|
47
|
+
def list_installed_apps_in_chat(chat_id:, expand: nil, **)
|
|
48
|
+
params = {}
|
|
49
|
+
params['$expand'] = expand if expand
|
|
50
|
+
response = graph_connection(**).get("chats/#{chat_id}/installedApps", params)
|
|
41
51
|
{ result: response.body }
|
|
42
52
|
end
|
|
43
53
|
|
|
@@ -15,17 +15,50 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_call_sessions,
|
|
18
|
-
desc: 'List sessions for a Teams call record',
|
|
18
|
+
desc: 'List sessions for a Teams call record with pagination and expand',
|
|
19
19
|
mcp_prefix: 'teams.list_call_sessions',
|
|
20
20
|
mcp_category: 'teams_calls',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { call_id:
|
|
23
|
+
inputs: { properties: { call_id: { type: 'string' },
|
|
24
|
+
top: { type: 'integer',
|
|
25
|
+
description: 'Sessions per page (default 50)' },
|
|
26
|
+
max_pages: { type: 'integer',
|
|
27
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
28
|
+
expand: { type: 'string',
|
|
29
|
+
description: 'Expand related entities (e.g. segments)' },
|
|
30
|
+
select: { type: 'string',
|
|
31
|
+
description: 'Comma-separated fields to return' } },
|
|
32
|
+
required: ['call_id'] },
|
|
24
33
|
trigger_words: %w[sessions calls records]
|
|
25
34
|
|
|
26
|
-
def list_call_sessions(call_id:, **)
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
def list_call_sessions(call_id:, top: 50, max_pages: 1, expand: nil, select: nil, **)
|
|
36
|
+
params = { '$top' => top }
|
|
37
|
+
params['$expand'] = expand if expand
|
|
38
|
+
params['$select'] = select if select
|
|
39
|
+
conn = graph_connection(**)
|
|
40
|
+
response = conn.get("communications/callRecords/#{call_id}/sessions", params)
|
|
41
|
+
body = response.body
|
|
42
|
+
|
|
43
|
+
return { result: body } if max_pages <= 1
|
|
44
|
+
|
|
45
|
+
all_values = Array(body['value'] || body[:value])
|
|
46
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
47
|
+
pages_fetched = 1
|
|
48
|
+
|
|
49
|
+
while next_link && pages_fetched < max_pages
|
|
50
|
+
response = conn.get(next_link)
|
|
51
|
+
page_body = response.body
|
|
52
|
+
items = page_body['value'] || page_body[:value]
|
|
53
|
+
all_values.concat(Array(items)) if items
|
|
54
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
55
|
+
pages_fetched += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
59
|
+
'value' => all_values }
|
|
60
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
61
|
+
{ result: result }
|
|
29
62
|
end
|
|
30
63
|
|
|
31
64
|
definition :get_call_session,
|
|
@@ -47,21 +80,47 @@ module Legion
|
|
|
47
80
|
end
|
|
48
81
|
|
|
49
82
|
definition :list_session_segments,
|
|
50
|
-
desc: 'List segments for a session in a Teams call record',
|
|
83
|
+
desc: 'List segments for a session in a Teams call record with pagination',
|
|
51
84
|
mcp_prefix: 'teams.list_session_segments',
|
|
52
85
|
mcp_category: 'teams_calls',
|
|
53
86
|
mcp_tier: :standard,
|
|
54
87
|
idempotent: true,
|
|
55
88
|
inputs: { properties: { call_id: { type: 'string' },
|
|
56
|
-
session_id: { type: 'string' }
|
|
89
|
+
session_id: { type: 'string' },
|
|
90
|
+
top: { type: 'integer',
|
|
91
|
+
description: 'Segments per page (default 50)' },
|
|
92
|
+
max_pages: { type: 'integer',
|
|
93
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
57
94
|
required: %w[call_id session_id] },
|
|
58
95
|
trigger_words: %w[segments pstn]
|
|
59
96
|
|
|
60
|
-
def list_session_segments(call_id:, session_id:, **)
|
|
61
|
-
|
|
62
|
-
|
|
97
|
+
def list_session_segments(call_id:, session_id:, top: 50, max_pages: 1, **)
|
|
98
|
+
params = { '$top' => top }
|
|
99
|
+
conn = graph_connection(**)
|
|
100
|
+
response = conn.get(
|
|
101
|
+
"communications/callRecords/#{call_id}/sessions/#{session_id}/segments", params
|
|
63
102
|
)
|
|
64
|
-
|
|
103
|
+
body = response.body
|
|
104
|
+
|
|
105
|
+
return { result: body } if max_pages <= 1
|
|
106
|
+
|
|
107
|
+
all_values = Array(body['value'] || body[:value])
|
|
108
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
109
|
+
pages_fetched = 1
|
|
110
|
+
|
|
111
|
+
while next_link && pages_fetched < max_pages
|
|
112
|
+
response = conn.get(next_link)
|
|
113
|
+
page_body = response.body
|
|
114
|
+
items = page_body['value'] || page_body[:value]
|
|
115
|
+
all_values.concat(Array(items)) if items
|
|
116
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
117
|
+
pages_fetched += 1
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
121
|
+
'value' => all_values }
|
|
122
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
123
|
+
{ result: result }
|
|
65
124
|
end
|
|
66
125
|
|
|
67
126
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -15,20 +15,49 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_channel_messages,
|
|
18
|
-
desc: 'List messages posted in a Teams channel',
|
|
18
|
+
desc: 'List messages posted in a Teams channel with pagination and expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_channel_messages',
|
|
20
20
|
mcp_category: 'teams_channel_messages',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
23
|
inputs: { properties: { team_id: { type: 'string' },
|
|
24
|
-
channel_id: { type: 'string' }
|
|
24
|
+
channel_id: { type: 'string' },
|
|
25
|
+
top: { type: 'integer',
|
|
26
|
+
description: 'Messages per page (default 20, max 50)' },
|
|
27
|
+
max_pages: { type: 'integer',
|
|
28
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
29
|
+
expand: { type: 'string',
|
|
30
|
+
description: 'Expand related entities (e.g. replies)' } },
|
|
25
31
|
required: %w[team_id channel_id] },
|
|
26
32
|
trigger_words: %w[channel history posts feed]
|
|
27
33
|
|
|
28
|
-
def list_channel_messages(team_id:, channel_id:, top: 50, **)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
def list_channel_messages(team_id:, channel_id:, top: 50, max_pages: 1, expand: nil, **)
|
|
35
|
+
per_page = [top, 50].min
|
|
36
|
+
params = { '$top' => per_page }
|
|
37
|
+
params['$expand'] = expand if expand
|
|
38
|
+
conn = graph_connection(**)
|
|
39
|
+
response = conn.get("teams/#{team_id}/channels/#{channel_id}/messages", params)
|
|
40
|
+
body = response.body
|
|
41
|
+
|
|
42
|
+
return { result: body } if max_pages <= 1
|
|
43
|
+
|
|
44
|
+
all_values = Array(body['value'] || body[:value])
|
|
45
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
46
|
+
pages_fetched = 1
|
|
47
|
+
|
|
48
|
+
while next_link && pages_fetched < max_pages
|
|
49
|
+
response = conn.get(next_link)
|
|
50
|
+
page_body = response.body
|
|
51
|
+
items = page_body['value'] || page_body[:value]
|
|
52
|
+
all_values.concat(Array(items)) if items
|
|
53
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
54
|
+
pages_fetched += 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
58
|
+
'value' => all_values }
|
|
59
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
60
|
+
{ result: result }
|
|
32
61
|
end
|
|
33
62
|
|
|
34
63
|
definition :get_channel_message,
|
|
@@ -89,23 +118,49 @@ module Legion
|
|
|
89
118
|
end
|
|
90
119
|
|
|
91
120
|
definition :list_channel_message_replies,
|
|
92
|
-
desc: 'List replies in a Teams channel message thread',
|
|
121
|
+
desc: 'List replies in a Teams channel message thread with pagination',
|
|
93
122
|
mcp_prefix: 'teams.list_channel_message_replies',
|
|
94
123
|
mcp_category: 'teams_channel_messages',
|
|
95
124
|
mcp_tier: :standard,
|
|
96
125
|
idempotent: true,
|
|
97
126
|
inputs: { properties: { team_id: { type: 'string' },
|
|
98
127
|
channel_id: { type: 'string' },
|
|
99
|
-
message_id: { type: 'string' }
|
|
128
|
+
message_id: { type: 'string' },
|
|
129
|
+
top: { type: 'integer',
|
|
130
|
+
description: 'Replies per page (default 50, max 50)' },
|
|
131
|
+
max_pages: { type: 'integer',
|
|
132
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
100
133
|
required: %w[team_id channel_id message_id] },
|
|
101
134
|
trigger_words: %w[replies thread]
|
|
102
135
|
|
|
103
|
-
def list_channel_message_replies(team_id:, channel_id:, message_id:, top: 50, **)
|
|
104
|
-
|
|
105
|
-
|
|
136
|
+
def list_channel_message_replies(team_id:, channel_id:, message_id:, top: 50, max_pages: 1, **)
|
|
137
|
+
per_page = [top, 50].min
|
|
138
|
+
params = { '$top' => per_page }
|
|
139
|
+
conn = graph_connection(**)
|
|
140
|
+
response = conn.get(
|
|
106
141
|
"teams/#{team_id}/channels/#{channel_id}/messages/#{message_id}/replies", params
|
|
107
142
|
)
|
|
108
|
-
|
|
143
|
+
body = response.body
|
|
144
|
+
|
|
145
|
+
return { result: body } if max_pages <= 1
|
|
146
|
+
|
|
147
|
+
all_values = Array(body['value'] || body[:value])
|
|
148
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
149
|
+
pages_fetched = 1
|
|
150
|
+
|
|
151
|
+
while next_link && pages_fetched < max_pages
|
|
152
|
+
response = conn.get(next_link)
|
|
153
|
+
page_body = response.body
|
|
154
|
+
items = page_body['value'] || page_body[:value]
|
|
155
|
+
all_values.concat(Array(items)) if items
|
|
156
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
157
|
+
pages_fetched += 1
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
161
|
+
'value' => all_values }
|
|
162
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
163
|
+
{ result: result }
|
|
109
164
|
end
|
|
110
165
|
|
|
111
166
|
definition :edit_channel_message,
|
|
@@ -15,16 +15,24 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_channels,
|
|
18
|
-
desc: 'List channels in a Team',
|
|
18
|
+
desc: 'List channels in a Team with optional filtering and select',
|
|
19
19
|
mcp_prefix: 'teams.list_channels',
|
|
20
20
|
mcp_category: 'teams_channels',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { team_id: { type: 'string' }
|
|
23
|
+
inputs: { properties: { team_id: { type: 'string' },
|
|
24
|
+
filter: { type: 'string',
|
|
25
|
+
description: 'OData $filter (e.g. membershipType eq \'standard\')' },
|
|
26
|
+
select: { type: 'string',
|
|
27
|
+
description: 'Comma-separated fields to return' } },
|
|
28
|
+
required: ['team_id'] },
|
|
24
29
|
trigger_words: %w[channels list]
|
|
25
30
|
|
|
26
|
-
def list_channels(team_id:, **)
|
|
27
|
-
|
|
31
|
+
def list_channels(team_id:, filter: nil, select: nil, **)
|
|
32
|
+
params = {}
|
|
33
|
+
params['$filter'] = filter if filter
|
|
34
|
+
params['$select'] = select if select
|
|
35
|
+
response = graph_connection(**).get("teams/#{team_id}/channels", params)
|
|
28
36
|
{ result: response.body }
|
|
29
37
|
end
|
|
30
38
|
|
|
@@ -15,18 +15,54 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_chats,
|
|
18
|
-
desc: 'List Teams chats for the current user',
|
|
18
|
+
desc: 'List Teams chats for the current user with pagination, filtering, and expand support',
|
|
19
19
|
mcp_prefix: 'teams.list_chats',
|
|
20
20
|
mcp_category: 'teams_chat',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Number of chats per page (default 50, max 50)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
expand: { type: 'string',
|
|
28
|
+
description: 'Expand related entities: members, lastMessagePreview' },
|
|
29
|
+
filter: { type: 'string',
|
|
30
|
+
description: 'OData $filter expression (e.g. chatType eq \'group\')' },
|
|
31
|
+
orderby: { type: 'string',
|
|
32
|
+
description: 'Sort order (e.g. lastMessagePreview/createdDateTime desc)' } },
|
|
33
|
+
required: [] },
|
|
23
34
|
trigger_words: %w[chats conversations]
|
|
24
35
|
|
|
25
|
-
def list_chats(user_id: 'me', top: 50, **)
|
|
26
|
-
log.debug "list_chats(user_id: #{user_id}, top: #{top})"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
def list_chats(user_id: 'me', top: 50, max_pages: 1, expand: nil, filter: nil, orderby: nil, **)
|
|
37
|
+
log.debug "list_chats(user_id: #{user_id}, top: #{top}, max_pages: #{max_pages})"
|
|
38
|
+
per_page = [top, 50].min
|
|
39
|
+
params = { '$top' => per_page }
|
|
40
|
+
params['$expand'] = expand if expand
|
|
41
|
+
params['$filter'] = filter if filter
|
|
42
|
+
params['$orderby'] = orderby if orderby
|
|
43
|
+
conn = graph_connection(**)
|
|
44
|
+
response = conn.get("#{user_path(user_id)}/chats", params)
|
|
45
|
+
body = response.body
|
|
46
|
+
|
|
47
|
+
return { result: body } if max_pages <= 1
|
|
48
|
+
|
|
49
|
+
all_values = Array(body['value'] || body[:value])
|
|
50
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
51
|
+
pages_fetched = 1
|
|
52
|
+
|
|
53
|
+
while next_link && pages_fetched < max_pages
|
|
54
|
+
response = conn.get(next_link)
|
|
55
|
+
page_body = response.body
|
|
56
|
+
items = page_body['value'] || page_body[:value]
|
|
57
|
+
all_values.concat(Array(items)) if items
|
|
58
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
59
|
+
pages_fetched += 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
63
|
+
'value' => all_values }
|
|
64
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
65
|
+
{ result: result }
|
|
30
66
|
end
|
|
31
67
|
|
|
32
68
|
definition :get_chat,
|
|
@@ -15,17 +15,50 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_drive_items,
|
|
18
|
-
desc: 'List files in the root of a user\'s OneDrive',
|
|
18
|
+
desc: 'List files in the root of a user\'s OneDrive with pagination and filtering',
|
|
19
19
|
mcp_prefix: 'teams.list_drive_items',
|
|
20
20
|
mcp_category: 'teams_files',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Items per page (default 200)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
select: { type: 'string',
|
|
28
|
+
description: 'Comma-separated fields to return' },
|
|
29
|
+
filter: { type: 'string',
|
|
30
|
+
description: 'OData $filter expression' } },
|
|
31
|
+
required: [] },
|
|
23
32
|
trigger_words: %w[files drive onedrive]
|
|
24
33
|
|
|
25
|
-
def list_drive_items(user_id: 'me', **)
|
|
34
|
+
def list_drive_items(user_id: 'me', top: 200, max_pages: 1, select: nil, filter: nil, **)
|
|
26
35
|
log.debug "list_drive_items(user_id: #{user_id})"
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
params = { '$top' => top }
|
|
37
|
+
params['$select'] = select if select
|
|
38
|
+
params['$filter'] = filter if filter
|
|
39
|
+
conn = graph_connection(**)
|
|
40
|
+
response = conn.get("#{user_path(user_id)}/drive/root/children", params)
|
|
41
|
+
body = response.body
|
|
42
|
+
|
|
43
|
+
return { result: body } if max_pages <= 1
|
|
44
|
+
|
|
45
|
+
all_values = Array(body['value'] || body[:value])
|
|
46
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
47
|
+
pages_fetched = 1
|
|
48
|
+
|
|
49
|
+
while next_link && pages_fetched < max_pages
|
|
50
|
+
response = conn.get(next_link)
|
|
51
|
+
page_body = response.body
|
|
52
|
+
items = page_body['value'] || page_body[:value]
|
|
53
|
+
all_values.concat(Array(items)) if items
|
|
54
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
55
|
+
pages_fetched += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
59
|
+
'value' => all_values }
|
|
60
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
61
|
+
{ result: result }
|
|
29
62
|
end
|
|
30
63
|
|
|
31
64
|
definition :get_drive_item,
|
|
@@ -59,18 +92,48 @@ module Legion
|
|
|
59
92
|
end
|
|
60
93
|
|
|
61
94
|
definition :list_team_drive_items,
|
|
62
|
-
desc: 'List files in a Team\'s SharePoint document library',
|
|
95
|
+
desc: 'List files in a Team\'s SharePoint document library with pagination',
|
|
63
96
|
mcp_prefix: 'teams.list_team_drive_items',
|
|
64
97
|
mcp_category: 'teams_files',
|
|
65
98
|
mcp_tier: :standard,
|
|
66
99
|
idempotent: true,
|
|
67
|
-
inputs: { properties: { team_id:
|
|
100
|
+
inputs: { properties: { team_id: { type: 'string' },
|
|
101
|
+
top: { type: 'integer',
|
|
102
|
+
description: 'Items per page (default 200)' },
|
|
103
|
+
max_pages: { type: 'integer',
|
|
104
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
105
|
+
select: { type: 'string',
|
|
106
|
+
description: 'Comma-separated fields to return' } },
|
|
107
|
+
required: ['team_id'] },
|
|
68
108
|
trigger_words: %w[sharepoint documents team]
|
|
69
109
|
|
|
70
|
-
def list_team_drive_items(team_id:, **)
|
|
110
|
+
def list_team_drive_items(team_id:, top: 200, max_pages: 1, select: nil, **)
|
|
71
111
|
log.debug "list_team_drive_items(team_id: #{team_id})"
|
|
72
|
-
|
|
73
|
-
|
|
112
|
+
params = { '$top' => top }
|
|
113
|
+
params['$select'] = select if select
|
|
114
|
+
conn = graph_connection(**)
|
|
115
|
+
response = conn.get("teams/#{team_id}/drive/root/children", params)
|
|
116
|
+
body = response.body
|
|
117
|
+
|
|
118
|
+
return { result: body } if max_pages <= 1
|
|
119
|
+
|
|
120
|
+
all_values = Array(body['value'] || body[:value])
|
|
121
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
122
|
+
pages_fetched = 1
|
|
123
|
+
|
|
124
|
+
while next_link && pages_fetched < max_pages
|
|
125
|
+
response = conn.get(next_link)
|
|
126
|
+
page_body = response.body
|
|
127
|
+
items = page_body['value'] || page_body[:value]
|
|
128
|
+
all_values.concat(Array(items)) if items
|
|
129
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
130
|
+
pages_fetched += 1
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
134
|
+
'value' => all_values }
|
|
135
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
136
|
+
{ result: result }
|
|
74
137
|
end
|
|
75
138
|
|
|
76
139
|
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers, false) &&
|
|
@@ -15,17 +15,44 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_meeting_artifacts,
|
|
18
|
-
desc: 'List artifacts (recordings, whiteboards) for an online meeting',
|
|
18
|
+
desc: 'List artifacts (recordings, whiteboards) for an online meeting with pagination',
|
|
19
19
|
mcp_prefix: 'teams.list_meeting_artifacts',
|
|
20
20
|
mcp_category: 'teams_meetings',
|
|
21
21
|
mcp_tier: :standard,
|
|
22
22
|
idempotent: true,
|
|
23
|
-
inputs: { properties: { meeting_id: { type: 'string' }
|
|
23
|
+
inputs: { properties: { meeting_id: { type: 'string' },
|
|
24
|
+
top: { type: 'integer',
|
|
25
|
+
description: 'Artifacts per page (default 50)' },
|
|
26
|
+
max_pages: { type: 'integer',
|
|
27
|
+
description: 'Maximum pages to fetch (default 1)' } },
|
|
28
|
+
required: ['meeting_id'] },
|
|
24
29
|
trigger_words: %w[artifacts recordings whiteboards]
|
|
25
30
|
|
|
26
|
-
def list_meeting_artifacts(meeting_id:, user_id: 'me', **)
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
def list_meeting_artifacts(meeting_id:, user_id: 'me', top: 50, max_pages: 1, **)
|
|
32
|
+
params = { '$top' => top }
|
|
33
|
+
conn = graph_connection(**)
|
|
34
|
+
response = conn.get("#{user_path(user_id)}/onlineMeetings/#{meeting_id}/artifacts", params)
|
|
35
|
+
body = response.body
|
|
36
|
+
|
|
37
|
+
return { result: body } if max_pages <= 1
|
|
38
|
+
|
|
39
|
+
all_values = Array(body['value'] || body[:value])
|
|
40
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
41
|
+
pages_fetched = 1
|
|
42
|
+
|
|
43
|
+
while next_link && pages_fetched < max_pages
|
|
44
|
+
response = conn.get(next_link)
|
|
45
|
+
page_body = response.body
|
|
46
|
+
items = page_body['value'] || page_body[:value]
|
|
47
|
+
all_values.concat(Array(items)) if items
|
|
48
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
49
|
+
pages_fetched += 1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
53
|
+
'value' => all_values }
|
|
54
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
55
|
+
{ result: result }
|
|
29
56
|
end
|
|
30
57
|
|
|
31
58
|
definition :get_meeting_artifact,
|
|
@@ -15,16 +15,46 @@ module Legion
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
definition :list_meetings,
|
|
18
|
-
desc: 'List online meetings for the current user',
|
|
18
|
+
desc: 'List online meetings for the current user with pagination and filtering',
|
|
19
19
|
mcp_prefix: 'teams.list_meetings',
|
|
20
20
|
mcp_category: 'teams_meetings',
|
|
21
21
|
mcp_tier: :low,
|
|
22
22
|
idempotent: true,
|
|
23
|
+
inputs: { properties: { top: { type: 'integer',
|
|
24
|
+
description: 'Meetings per page (default 50)' },
|
|
25
|
+
max_pages: { type: 'integer',
|
|
26
|
+
description: 'Maximum pages to fetch (default 1)' },
|
|
27
|
+
filter: { type: 'string',
|
|
28
|
+
description: 'OData $filter expression' } },
|
|
29
|
+
required: [] },
|
|
23
30
|
trigger_words: %w[meetings upcoming calendar]
|
|
24
31
|
|
|
25
|
-
def list_meetings(user_id: 'me', **)
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
def list_meetings(user_id: 'me', top: 50, max_pages: 1, filter: nil, **)
|
|
33
|
+
params = { '$top' => top }
|
|
34
|
+
params['$filter'] = filter if filter
|
|
35
|
+
conn = graph_connection(**)
|
|
36
|
+
response = conn.get("#{user_path(user_id)}/onlineMeetings", params)
|
|
37
|
+
body = response.body
|
|
38
|
+
|
|
39
|
+
return { result: body } if max_pages <= 1
|
|
40
|
+
|
|
41
|
+
all_values = Array(body['value'] || body[:value])
|
|
42
|
+
next_link = body['@odata.nextLink'] || body[:'@odata.nextLink']
|
|
43
|
+
pages_fetched = 1
|
|
44
|
+
|
|
45
|
+
while next_link && pages_fetched < max_pages
|
|
46
|
+
response = conn.get(next_link)
|
|
47
|
+
page_body = response.body
|
|
48
|
+
items = page_body['value'] || page_body[:value]
|
|
49
|
+
all_values.concat(Array(items)) if items
|
|
50
|
+
next_link = page_body['@odata.nextLink'] || page_body[:'@odata.nextLink']
|
|
51
|
+
pages_fetched += 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
result = { '@odata.context' => body['@odata.context'] || body[:'@odata.context'],
|
|
55
|
+
'value' => all_values }
|
|
56
|
+
result['@odata.nextLink'] = next_link if next_link
|
|
57
|
+
{ result: result }
|
|
28
58
|
end
|
|
29
59
|
|
|
30
60
|
definition :get_meeting,
|