@microsoft/agents-hosting-extensions-msteams 1.7.0-beta.8.gc2b086aef6
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.
- package/README.md +147 -0
- package/dist/package.json +46 -0
- package/dist/src/activity-extensions/index.d.ts +1 -0
- package/dist/src/activity-extensions/index.js +8 -0
- package/dist/src/activity-extensions/index.js.map +1 -0
- package/dist/src/activity-extensions/teamsChannelData.d.ts +12 -0
- package/dist/src/activity-extensions/teamsChannelData.js +29 -0
- package/dist/src/activity-extensions/teamsChannelData.js.map +1 -0
- package/dist/src/app/index.d.ts +1 -0
- package/dist/src/app/index.js +20 -0
- package/dist/src/app/index.js.map +1 -0
- package/dist/src/app/teamsAppExtensions.d.ts +145 -0
- package/dist/src/app/teamsAppExtensions.js +201 -0
- package/dist/src/app/teamsAppExtensions.js.map +1 -0
- package/dist/src/channels/index.d.ts +1 -0
- package/dist/src/channels/index.js +20 -0
- package/dist/src/channels/index.js.map +1 -0
- package/dist/src/channels/teamsChannel.d.ts +100 -0
- package/dist/src/channels/teamsChannel.js +210 -0
- package/dist/src/channels/teamsChannel.js.map +1 -0
- package/dist/src/config/config.d.ts +37 -0
- package/dist/src/config/config.js +71 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/index.d.ts +1 -0
- package/dist/src/config/index.js +20 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/errorHelper.d.ts +19 -0
- package/dist/src/errorHelper.js +96 -0
- package/dist/src/errorHelper.js.map +1 -0
- package/dist/src/fileConsents/fileConsent.d.ts +37 -0
- package/dist/src/fileConsents/fileConsent.js +79 -0
- package/dist/src/fileConsents/fileConsent.js.map +1 -0
- package/dist/src/fileConsents/index.d.ts +1 -0
- package/dist/src/fileConsents/index.js +20 -0
- package/dist/src/fileConsents/index.js.map +1 -0
- package/dist/src/graphClientFactory.d.ts +10 -0
- package/dist/src/graphClientFactory.js +98 -0
- package/dist/src/graphClientFactory.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/meetings/index.d.ts +1 -0
- package/dist/src/meetings/index.js +20 -0
- package/dist/src/meetings/index.js.map +1 -0
- package/dist/src/meetings/meeting.d.ts +84 -0
- package/dist/src/meetings/meeting.js +107 -0
- package/dist/src/meetings/meeting.js.map +1 -0
- package/dist/src/messageExtensions/index.d.ts +2 -0
- package/dist/src/messageExtensions/index.js +24 -0
- package/dist/src/messageExtensions/index.js.map +1 -0
- package/dist/src/messageExtensions/messageExtension.d.ts +133 -0
- package/dist/src/messageExtensions/messageExtension.js +326 -0
- package/dist/src/messageExtensions/messageExtension.js.map +1 -0
- package/dist/src/messageExtensions/messagingExtensionQuery.d.ts +87 -0
- package/dist/src/messageExtensions/messagingExtensionQuery.js +35 -0
- package/dist/src/messageExtensions/messagingExtensionQuery.js.map +1 -0
- package/dist/src/messages/index.d.ts +1 -0
- package/dist/src/messages/index.js +20 -0
- package/dist/src/messages/index.js.map +1 -0
- package/dist/src/messages/message.d.ts +67 -0
- package/dist/src/messages/message.js +129 -0
- package/dist/src/messages/message.js.map +1 -0
- package/dist/src/models/index.d.ts +1 -0
- package/dist/src/models/index.js +20 -0
- package/dist/src/models/index.js.map +1 -0
- package/dist/src/models/readReceiptInfo.d.ts +27 -0
- package/dist/src/models/readReceiptInfo.js +44 -0
- package/dist/src/models/readReceiptInfo.js.map +1 -0
- package/dist/src/taskModules/index.d.ts +1 -0
- package/dist/src/taskModules/index.js +20 -0
- package/dist/src/taskModules/index.js.map +1 -0
- package/dist/src/taskModules/taskModule.d.ts +42 -0
- package/dist/src/taskModules/taskModule.js +102 -0
- package/dist/src/taskModules/taskModule.js.map +1 -0
- package/dist/src/teams/index.d.ts +1 -0
- package/dist/src/teams/index.js +20 -0
- package/dist/src/teams/index.js.map +1 -0
- package/dist/src/teams/teamsTeam.d.ts +82 -0
- package/dist/src/teams/teamsTeam.js +172 -0
- package/dist/src/teams/teamsTeam.js.map +1 -0
- package/dist/src/teamsActivity.d.ts +15 -0
- package/dist/src/teamsActivity.js +5 -0
- package/dist/src/teamsActivity.js.map +1 -0
- package/dist/src/teamsActivityExtensions.d.ts +53 -0
- package/dist/src/teamsActivityExtensions.js +101 -0
- package/dist/src/teamsActivityExtensions.js.map +1 -0
- package/dist/src/teamsAgentExtension.d.ts +105 -0
- package/dist/src/teamsAgentExtension.js +178 -0
- package/dist/src/teamsAgentExtension.js.map +1 -0
- package/dist/src/teamsApiClientExtensions.d.ts +13 -0
- package/dist/src/teamsApiClientExtensions.js +41 -0
- package/dist/src/teamsApiClientExtensions.js.map +1 -0
- package/dist/src/teamsHeaderPropagation.d.ts +14 -0
- package/dist/src/teamsHeaderPropagation.js +35 -0
- package/dist/src/teamsHeaderPropagation.js.map +1 -0
- package/dist/src/teamsModelExtensions.d.ts +19 -0
- package/dist/src/teamsModelExtensions.js +38 -0
- package/dist/src/teamsModelExtensions.js.map +1 -0
- package/dist/src/teamsProactiveServiceEndpoints.d.ts +15 -0
- package/dist/src/teamsProactiveServiceEndpoints.js +21 -0
- package/dist/src/teamsProactiveServiceEndpoints.js.map +1 -0
- package/dist/src/teamsRouteHandler.d.ts +13 -0
- package/dist/src/teamsRouteHandler.js +18 -0
- package/dist/src/teamsRouteHandler.js.map +1 -0
- package/dist/src/teamsTurnContext.d.ts +64 -0
- package/dist/src/teamsTurnContext.js +113 -0
- package/dist/src/teamsTurnContext.js.map +1 -0
- package/package.json +46 -0
- package/src/activity-extensions/index.ts +4 -0
- package/src/activity-extensions/teamsChannelData.ts +30 -0
- package/src/app/index.ts +4 -0
- package/src/app/teamsAppExtensions.ts +369 -0
- package/src/channels/index.ts +4 -0
- package/src/channels/teamsChannel.ts +229 -0
- package/src/config/config.ts +79 -0
- package/src/config/index.ts +4 -0
- package/src/errorHelper.ts +104 -0
- package/src/fileConsents/fileConsent.ts +85 -0
- package/src/fileConsents/index.ts +4 -0
- package/src/graphClientFactory.ts +127 -0
- package/src/index.ts +23 -0
- package/src/meetings/index.ts +4 -0
- package/src/meetings/meeting.ts +146 -0
- package/src/messageExtensions/index.ts +5 -0
- package/src/messageExtensions/messageExtension.ts +370 -0
- package/src/messageExtensions/messagingExtensionQuery.ts +34 -0
- package/src/messages/index.ts +4 -0
- package/src/messages/message.ts +148 -0
- package/src/models/index.ts +4 -0
- package/src/models/readReceiptInfo.ts +50 -0
- package/src/taskModules/index.ts +4 -0
- package/src/taskModules/taskModule.ts +113 -0
- package/src/teams/index.ts +4 -0
- package/src/teams/teamsTeam.ts +189 -0
- package/src/teamsActivity.ts +19 -0
- package/src/teamsActivityExtensions.ts +99 -0
- package/src/teamsAgentExtension.ts +205 -0
- package/src/teamsApiClientExtensions.ts +47 -0
- package/src/teamsHeaderPropagation.ts +32 -0
- package/src/teamsModelExtensions.ts +42 -0
- package/src/teamsProactiveServiceEndpoints.ts +18 -0
- package/src/teamsRouteHandler.ts +22 -0
- package/src/teamsTurnContext.ts +125 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { Activity, ActivityTypes } from '@microsoft/agents-activity'
|
|
5
|
+
import { AgentApplication, RouteHandler, RouteRank, RouteSelector, TurnContext, TurnState } from '@microsoft/agents-hosting'
|
|
6
|
+
import type { TaskModuleRequest, TaskModuleResponse } from '@microsoft/teams.api'
|
|
7
|
+
import { TeamsTurnContext } from '../teamsTurnContext'
|
|
8
|
+
|
|
9
|
+
const DEFAULT_TASK_DATA_KEY = 'task'
|
|
10
|
+
|
|
11
|
+
function matchesTaskKeyValue (context: TurnContext, value: string | RegExp, key: string): boolean {
|
|
12
|
+
const taskData = (context.activity.value as any)?.data
|
|
13
|
+
if (!taskData || typeof taskData !== 'object') return false
|
|
14
|
+
const dataValue = taskData[normalizeTaskDataKey(key)]
|
|
15
|
+
if (typeof dataValue !== 'string') return false
|
|
16
|
+
return typeof value === 'string' ? dataValue === value : value.test(dataValue)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isTaskInvoke (context: TurnContext, name: string): boolean {
|
|
20
|
+
return (
|
|
21
|
+
context.activity.type === ActivityTypes.Invoke &&
|
|
22
|
+
context.activity.channelId === 'msteams' &&
|
|
23
|
+
context.activity.name === name &&
|
|
24
|
+
context.activity.value != null
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeTaskDataKey (key: string): string {
|
|
29
|
+
return key.trim() || DEFAULT_TASK_DATA_KEY
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function matchesTaskInvoke (context: TurnContext, name: string, value: string | RegExp | null, key: string): boolean {
|
|
33
|
+
if (!isTaskInvoke(context, name)) {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (value == null || (typeof value === 'string' && value.trim() === '')) {
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return matchesTaskKeyValue(context, value, key)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type FetchHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, request: TaskModuleRequest) => Promise<TaskModuleResponse>
|
|
45
|
+
type SubmitHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, request: TaskModuleRequest) => Promise<TaskModuleResponse>
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Registers handlers for Microsoft Teams task module invoke activities.
|
|
49
|
+
*
|
|
50
|
+
* @typeParam TState - The turn state type used by the agent application.
|
|
51
|
+
*/
|
|
52
|
+
export class TaskModule<TState extends TurnState> {
|
|
53
|
+
_app: AgentApplication<TState>
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a Teams task module route helper.
|
|
57
|
+
*
|
|
58
|
+
* @param app - The agent application that receives the registered routes.
|
|
59
|
+
*/
|
|
60
|
+
constructor (app: AgentApplication<TState>) {
|
|
61
|
+
this._app = app
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Registers a handler for Teams task/fetch invokes.
|
|
66
|
+
*
|
|
67
|
+
* @param value - Optional task data value or regular expression used to match the invoke.
|
|
68
|
+
* @param handler - Handler invoked with the task module request.
|
|
69
|
+
* @param key - Task data key to inspect when matching `value`. Defaults to `task`.
|
|
70
|
+
* @param rank - Optional route rank used for route ordering.
|
|
71
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
72
|
+
* @returns This task module helper for chaining.
|
|
73
|
+
*/
|
|
74
|
+
onFetch (value: string | RegExp | null, handler: FetchHandler<TState>, key: string = DEFAULT_TASK_DATA_KEY, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
75
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
76
|
+
return Promise.resolve(matchesTaskInvoke(context, 'task/fetch', value, key))
|
|
77
|
+
}
|
|
78
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
79
|
+
const request = context.activity.value as TaskModuleRequest
|
|
80
|
+
const response: TaskModuleResponse = await handler(new TeamsTurnContext(context), state, request)
|
|
81
|
+
const invokeResponse = new Activity(ActivityTypes.InvokeResponse)
|
|
82
|
+
invokeResponse.value = { status: 200, body: response }
|
|
83
|
+
await context.sendActivity(invokeResponse)
|
|
84
|
+
}
|
|
85
|
+
this._app.addRoute(routeSel, routeHandler, true, rank, authHandlers)
|
|
86
|
+
return this
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Registers a handler for Teams task/submit invokes.
|
|
91
|
+
*
|
|
92
|
+
* @param value - Optional task data value or regular expression used to match the invoke.
|
|
93
|
+
* @param handler - Handler invoked with the task module request.
|
|
94
|
+
* @param key - Task data key to inspect when matching `value`. Defaults to `task`.
|
|
95
|
+
* @param rank - Optional route rank used for route ordering.
|
|
96
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
97
|
+
* @returns This task module helper for chaining.
|
|
98
|
+
*/
|
|
99
|
+
onSubmit (value: string | RegExp | null, handler: SubmitHandler<TState>, key: string = DEFAULT_TASK_DATA_KEY, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
100
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
101
|
+
return Promise.resolve(matchesTaskInvoke(context, 'task/submit', value, key))
|
|
102
|
+
}
|
|
103
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
104
|
+
const request = context.activity.value as TaskModuleRequest
|
|
105
|
+
const response: TaskModuleResponse = await handler(new TeamsTurnContext(context), state, request)
|
|
106
|
+
const invokeResponse = new Activity(ActivityTypes.InvokeResponse)
|
|
107
|
+
invokeResponse.value = { status: 200, body: response }
|
|
108
|
+
await context.sendActivity(invokeResponse)
|
|
109
|
+
}
|
|
110
|
+
this._app.addRoute(routeSel, routeHandler, true, rank, authHandlers)
|
|
111
|
+
return this
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { ActivityTypes } from '@microsoft/agents-activity'
|
|
5
|
+
import { AgentApplication, RouteHandler, RouteRank, RouteSelector, TurnContext, TurnState } from '@microsoft/agents-hosting'
|
|
6
|
+
import { parseTeamsChannelData } from '../activity-extensions'
|
|
7
|
+
import type { TeamInfo } from '@microsoft/teams.api'
|
|
8
|
+
import { TeamsTurnContext } from '../teamsTurnContext'
|
|
9
|
+
|
|
10
|
+
const TEAM_ARCHIVED_EVENT = 'teamArchived'
|
|
11
|
+
const TEAM_UNARCHIVED_EVENT = 'teamUnarchived'
|
|
12
|
+
const TEAM_RENAMED_EVENT = 'teamRenamed'
|
|
13
|
+
const TEAM_RESTORED_EVENT = 'teamRestored'
|
|
14
|
+
const TEAM_DELETED_EVENT = 'teamDeleted'
|
|
15
|
+
const TEAM_HARD_DELETED_EVENT = 'teamHardDeleted'
|
|
16
|
+
|
|
17
|
+
type TeamUpdateHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, data: TeamInfo) => Promise<void>
|
|
18
|
+
|
|
19
|
+
function isTeamUpdateEvent (context: TurnContext, eventType?: string): boolean {
|
|
20
|
+
const channelData = parseTeamsChannelData(context.activity.channelData)
|
|
21
|
+
const actualEventType = typeof channelData?.eventType === 'string' ? channelData.eventType.toLowerCase() : undefined
|
|
22
|
+
const expectedEventType = eventType?.toLowerCase()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
context.activity.type === ActivityTypes.ConversationUpdate &&
|
|
26
|
+
context.activity.channelId === 'msteams' &&
|
|
27
|
+
channelData?.team != null &&
|
|
28
|
+
(
|
|
29
|
+
expectedEventType != null
|
|
30
|
+
? actualEventType === expectedEventType
|
|
31
|
+
: actualEventType?.startsWith('team') === true
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getTeamInfo (context: TurnContext): TeamInfo {
|
|
37
|
+
return parseTeamsChannelData(context.activity.channelData).team as TeamInfo
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Registers handlers for Microsoft Teams team lifecycle events.
|
|
42
|
+
*
|
|
43
|
+
* @typeParam TState - The turn state type used by the agent application.
|
|
44
|
+
*/
|
|
45
|
+
export class TeamsTeam<TState extends TurnState = TurnState> {
|
|
46
|
+
private _app: AgentApplication<TState>
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates a Teams team route helper.
|
|
50
|
+
*
|
|
51
|
+
* @param app - The agent application that receives the registered routes.
|
|
52
|
+
*/
|
|
53
|
+
constructor (app: AgentApplication<TState>) {
|
|
54
|
+
this._app = app
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Registers a handler for any Teams team update event.
|
|
59
|
+
*
|
|
60
|
+
* @param handler - Handler invoked with the Teams turn context, turn state, and team information.
|
|
61
|
+
* @param rank - Optional route rank used for route ordering.
|
|
62
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
63
|
+
* @returns This team helper for chaining.
|
|
64
|
+
*/
|
|
65
|
+
onTeamEventReceived (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
66
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
67
|
+
return Promise.resolve(isTeamUpdateEvent(context))
|
|
68
|
+
}
|
|
69
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
70
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
71
|
+
}
|
|
72
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Registers a handler for Teams team archived events.
|
|
78
|
+
*
|
|
79
|
+
* @param handler - Handler invoked with the archived team information.
|
|
80
|
+
* @param rank - Optional route rank used for route ordering.
|
|
81
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
82
|
+
* @returns This team helper for chaining.
|
|
83
|
+
*/
|
|
84
|
+
onArchived (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
85
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
86
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_ARCHIVED_EVENT))
|
|
87
|
+
}
|
|
88
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
89
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
90
|
+
}
|
|
91
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
92
|
+
return this
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Registers a handler for Teams team unarchived events.
|
|
97
|
+
*
|
|
98
|
+
* @param handler - Handler invoked with the unarchived team information.
|
|
99
|
+
* @param rank - Optional route rank used for route ordering.
|
|
100
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
101
|
+
* @returns This team helper for chaining.
|
|
102
|
+
*/
|
|
103
|
+
onUnarchived (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
104
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
105
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_UNARCHIVED_EVENT))
|
|
106
|
+
}
|
|
107
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
108
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
109
|
+
}
|
|
110
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
111
|
+
return this
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Registers a handler for Teams team renamed events.
|
|
116
|
+
*
|
|
117
|
+
* @param handler - Handler invoked with the renamed team information.
|
|
118
|
+
* @param rank - Optional route rank used for route ordering.
|
|
119
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
120
|
+
* @returns This team helper for chaining.
|
|
121
|
+
*/
|
|
122
|
+
onRenamed (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
123
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
124
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_RENAMED_EVENT))
|
|
125
|
+
}
|
|
126
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
127
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
128
|
+
}
|
|
129
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
130
|
+
return this
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Registers a handler for Teams team restored events.
|
|
135
|
+
*
|
|
136
|
+
* @param handler - Handler invoked with the restored team information.
|
|
137
|
+
* @param rank - Optional route rank used for route ordering.
|
|
138
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
139
|
+
* @returns This team helper for chaining.
|
|
140
|
+
*/
|
|
141
|
+
onRestored (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
142
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
143
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_RESTORED_EVENT))
|
|
144
|
+
}
|
|
145
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
146
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
147
|
+
}
|
|
148
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
149
|
+
return this
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Registers a handler for Teams team deleted events.
|
|
154
|
+
*
|
|
155
|
+
* @param handler - Handler invoked with the deleted team information.
|
|
156
|
+
* @param rank - Optional route rank used for route ordering.
|
|
157
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
158
|
+
* @returns This team helper for chaining.
|
|
159
|
+
*/
|
|
160
|
+
onDeleted (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
161
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
162
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_DELETED_EVENT))
|
|
163
|
+
}
|
|
164
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
165
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
166
|
+
}
|
|
167
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
168
|
+
return this
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Registers a handler for Teams team hard-deleted events.
|
|
173
|
+
*
|
|
174
|
+
* @param handler - Handler invoked with the hard-deleted team information.
|
|
175
|
+
* @param rank - Optional route rank used for route ordering.
|
|
176
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
177
|
+
* @returns This team helper for chaining.
|
|
178
|
+
*/
|
|
179
|
+
onHardDeleted (handler: TeamUpdateHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
180
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
181
|
+
return Promise.resolve(isTeamUpdateEvent(context, TEAM_HARD_DELETED_EVENT))
|
|
182
|
+
}
|
|
183
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
184
|
+
await handler(new TeamsTurnContext(context), state, getTeamInfo(context))
|
|
185
|
+
}
|
|
186
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
187
|
+
return this
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import type { Activity } from '@microsoft/agents-activity'
|
|
5
|
+
import type { ChannelData } from '@microsoft/teams.api'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A Teams activity whose channel-specific payload uses the Microsoft Teams API model.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* This is a type-only specialization of {@link Activity}. Teams activities keep
|
|
12
|
+
* their original runtime identity; no activity conversion or cloning occurs.
|
|
13
|
+
*/
|
|
14
|
+
export interface TeamsActivity extends Activity {
|
|
15
|
+
/**
|
|
16
|
+
* Channel-specific data for the Teams activity.
|
|
17
|
+
*/
|
|
18
|
+
channelData?: ChannelData
|
|
19
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { Activity } from '@microsoft/agents-activity'
|
|
5
|
+
import type { ChannelData, OnBehalfOf } from '@microsoft/teams.api'
|
|
6
|
+
import { parseTeamsChannelData } from './activity-extensions'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Gets the Teams selected channel ID from the activity's channel data settings.
|
|
10
|
+
*
|
|
11
|
+
* @param activity - Activity containing Teams channel data.
|
|
12
|
+
* @returns The selected channel ID, if present.
|
|
13
|
+
*/
|
|
14
|
+
export function teamsGetSelectedChannelId (activity: Activity): string | undefined {
|
|
15
|
+
const channelData = parseTeamsChannelData(activity.channelData)
|
|
16
|
+
return (channelData as any)?.settings?.selectedChannel?.id
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets the Teams channel ID from the activity's channel data.
|
|
21
|
+
*
|
|
22
|
+
* @param activity - Activity containing Teams channel data.
|
|
23
|
+
* @returns The Teams channel ID, if present.
|
|
24
|
+
*/
|
|
25
|
+
export function teamsGetChannelId (activity: Activity): string | undefined {
|
|
26
|
+
const channelData = parseTeamsChannelData(activity.channelData)
|
|
27
|
+
return (channelData as any)?.channel?.id
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Gets the Teams meeting info from the activity's channel data.
|
|
32
|
+
*
|
|
33
|
+
* @param activity - Activity containing Teams channel data.
|
|
34
|
+
* @returns Teams meeting information, if present.
|
|
35
|
+
*/
|
|
36
|
+
export function teamsGetMeetingInfo (activity: Activity): ChannelData['meeting'] | undefined {
|
|
37
|
+
const channelData = parseTeamsChannelData(activity.channelData)
|
|
38
|
+
return channelData?.meeting
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Gets the Teams team info from the activity's channel data.
|
|
43
|
+
*
|
|
44
|
+
* @param activity - Activity containing Teams channel data.
|
|
45
|
+
* @returns Teams team information, if present.
|
|
46
|
+
*/
|
|
47
|
+
export function teamsGetTeamInfo (activity: Activity): ChannelData['team'] | undefined {
|
|
48
|
+
const channelData = parseTeamsChannelData(activity.channelData)
|
|
49
|
+
return channelData?.team
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Configures the activity to generate a notification within Teams.
|
|
54
|
+
* @param activity - The activity to configure.
|
|
55
|
+
* @param alertInMeeting - If true, renders a popup in meeting chat as well as the chat thread.
|
|
56
|
+
* @param externalResourceUrl - URL to external resource (must be in manifest's valid domains).
|
|
57
|
+
*/
|
|
58
|
+
export function teamsNotifyUser (activity: Activity, alertInMeeting: boolean = false, externalResourceUrl?: string): void {
|
|
59
|
+
if (!activity.channelData || typeof activity.channelData !== 'object') {
|
|
60
|
+
activity.channelData = {}
|
|
61
|
+
}
|
|
62
|
+
const channelData = activity.channelData as Record<string, unknown>
|
|
63
|
+
channelData.notification = {
|
|
64
|
+
alert: !alertInMeeting,
|
|
65
|
+
alertInMeeting,
|
|
66
|
+
...(externalResourceUrl != null && { externalResourceUrl })
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets the Teams OnBehalfOf list from the activity's channel data.
|
|
72
|
+
*
|
|
73
|
+
* @param activity - Activity containing Teams channel data.
|
|
74
|
+
* @returns The Teams on-behalf-of entries, if present.
|
|
75
|
+
*/
|
|
76
|
+
export function teamsGetTeamOnBehalfOf (activity: Activity): OnBehalfOf[] | undefined {
|
|
77
|
+
const channelData = parseTeamsChannelData(activity.channelData)
|
|
78
|
+
return (channelData as any)?.onBehalfOf
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Adds the Teams feedback loop flag to the activity's channel data.
|
|
83
|
+
* Returns false if channel data is already set.
|
|
84
|
+
*
|
|
85
|
+
* @param activity - The activity to configure.
|
|
86
|
+
* @param feedbackLoopType - The feedback loop type value. Defaults to "default".
|
|
87
|
+
* @returns True when feedback loop channel data was added; otherwise false.
|
|
88
|
+
*/
|
|
89
|
+
export function teamsEnableFeedbackLoop (activity: Activity, feedbackLoopType: string = 'default'): boolean {
|
|
90
|
+
if (activity.channelData != null) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
activity.channelData = {
|
|
94
|
+
feedbackLoop: {
|
|
95
|
+
type: feedbackLoopType
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { ExceptionHelper } from '@microsoft/agents-activity'
|
|
5
|
+
import { Client as GraphClient } from '@microsoft/microsoft-graph-client'
|
|
6
|
+
import { AgentApplication, AgentExtension, type Connections, TurnContext, TurnState } from '@microsoft/agents-hosting'
|
|
7
|
+
import { Client as TeamsClient } from '@microsoft/teams.api'
|
|
8
|
+
import { parseTeamsChannelData } from './activity-extensions'
|
|
9
|
+
import { TeamsConfig } from './config/config'
|
|
10
|
+
import { FileConsent } from './fileConsents/fileConsent'
|
|
11
|
+
import { Meeting } from './meetings/meeting'
|
|
12
|
+
import { Message } from './messages/message'
|
|
13
|
+
import { MessageExtension } from './messageExtensions/messageExtension'
|
|
14
|
+
import { TaskModule } from './taskModules/taskModule'
|
|
15
|
+
import { TeamsChannel } from './channels/teamsChannel'
|
|
16
|
+
import { TeamsTeam } from './teams/teamsTeam'
|
|
17
|
+
import { setTeamsApiClient } from './teamsApiClientExtensions'
|
|
18
|
+
import { applyTeamsHeaderPropagation } from './teamsHeaderPropagation'
|
|
19
|
+
import { TeamsTurnContext } from './teamsTurnContext'
|
|
20
|
+
import { createAppGraphClient, createUserGraphClient } from './graphClientFactory'
|
|
21
|
+
import { Errors } from './errorHelper'
|
|
22
|
+
|
|
23
|
+
const DEFAULT_GRAPH_BASE_URL = 'https://graph.microsoft.com/v1.0'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Adds Microsoft Teams-specific routing, context helpers, and API clients to an agent application.
|
|
27
|
+
*
|
|
28
|
+
* Register an instance with `AgentApplication.registerExtension` to configure handlers for Teams
|
|
29
|
+
* events, message extensions, task modules, file consent flows, and related Teams capabilities.
|
|
30
|
+
*
|
|
31
|
+
* @typeParam TState - The turn state type used by the agent application.
|
|
32
|
+
*/
|
|
33
|
+
export class TeamsAgentExtension<TState extends TurnState = TurnState> extends AgentExtension<TState> {
|
|
34
|
+
private _app: AgentApplication<TState>
|
|
35
|
+
private _meetings: Meeting<TState>
|
|
36
|
+
private _messageExtensions: MessageExtension<TState>
|
|
37
|
+
private _taskModules: TaskModule<TState>
|
|
38
|
+
private _channels: TeamsChannel<TState>
|
|
39
|
+
private _teams: TeamsTeam<TState>
|
|
40
|
+
private _messages: Message<TState>
|
|
41
|
+
private _fileConsent: FileConsent<TState>
|
|
42
|
+
private _config: TeamsConfig<TState>
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new Teams extension for the provided agent application.
|
|
46
|
+
*
|
|
47
|
+
* The extension configures Teams header propagation and prepares a Teams API client for each
|
|
48
|
+
* incoming Teams turn.
|
|
49
|
+
*
|
|
50
|
+
* @param app - The agent application to extend with Teams capabilities.
|
|
51
|
+
*/
|
|
52
|
+
constructor (app: AgentApplication<TState>) {
|
|
53
|
+
super('msteams')
|
|
54
|
+
this._app = app
|
|
55
|
+
this._meetings = new Meeting(app)
|
|
56
|
+
this._messageExtensions = new MessageExtension(app)
|
|
57
|
+
this._taskModules = new TaskModule(app)
|
|
58
|
+
this._channels = new TeamsChannel(app)
|
|
59
|
+
this._teams = new TeamsTeam(app)
|
|
60
|
+
this._messages = new Message(app)
|
|
61
|
+
this._fileConsent = new FileConsent(app)
|
|
62
|
+
this._config = new TeamsConfig(app)
|
|
63
|
+
|
|
64
|
+
const headerPropagation = this._app.options.headerPropagation
|
|
65
|
+
this._app.options.headerPropagation = (headers) => {
|
|
66
|
+
headerPropagation?.(headers)
|
|
67
|
+
applyTeamsHeaderPropagation(headers)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this._app.onTurn('beforeTurn', async (context) => {
|
|
71
|
+
if (context.activity.channelId === this.channelId) {
|
|
72
|
+
setTeamsApiClient(context, this.channelId)
|
|
73
|
+
try {
|
|
74
|
+
context.activity.channelData = parseTeamsChannelData(context.activity.channelData)
|
|
75
|
+
} catch {
|
|
76
|
+
// ignore parse errors for unexpected channelData payloads
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return true
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Gets the route registration helper for Teams meeting events.
|
|
85
|
+
*/
|
|
86
|
+
public get meetings (): Meeting<TState> {
|
|
87
|
+
return this._meetings
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Gets the route registration helper for Teams message extension activities.
|
|
92
|
+
*/
|
|
93
|
+
public get messageExtensions (): MessageExtension<TState> {
|
|
94
|
+
return this._messageExtensions
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Gets the route registration helper for Teams task module invoke activities.
|
|
99
|
+
*/
|
|
100
|
+
public get taskModules (): TaskModule<TState> {
|
|
101
|
+
return this._taskModules
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Gets the route registration helper for Teams channel events.
|
|
106
|
+
*/
|
|
107
|
+
public get channels (): TeamsChannel<TState> {
|
|
108
|
+
return this._channels
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Gets the route registration helper for Teams team events.
|
|
113
|
+
*/
|
|
114
|
+
public get teams (): TeamsTeam<TState> {
|
|
115
|
+
return this._teams
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Gets the route registration helper for Teams message lifecycle events.
|
|
120
|
+
*/
|
|
121
|
+
public get messages (): Message<TState> {
|
|
122
|
+
return this._messages
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Gets the route registration helper for Teams file consent card actions.
|
|
127
|
+
*/
|
|
128
|
+
public get fileConsent (): FileConsent<TState> {
|
|
129
|
+
return this._fileConsent
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Gets the route registration helper for Teams app configuration invokes.
|
|
134
|
+
*/
|
|
135
|
+
public get config (): TeamsConfig<TState> {
|
|
136
|
+
return this._config
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Gets the Teams API client associated with the current turn.
|
|
141
|
+
*
|
|
142
|
+
* @param context - The turn context for the current Teams activity.
|
|
143
|
+
* @returns The Teams API client stored on the turn.
|
|
144
|
+
* @throws If the current turn has not been initialized with a Teams API client.
|
|
145
|
+
*/
|
|
146
|
+
public getTeamsClient (context: TurnContext): TeamsClient {
|
|
147
|
+
return new TeamsTurnContext(context).client
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates a Microsoft Graph client that obtains access tokens through the agent authorization system.
|
|
152
|
+
*
|
|
153
|
+
* @param context - The turn context used to acquire the user token.
|
|
154
|
+
* @param handlerName - Optional authorization handler name. Required when multiple handlers are configured.
|
|
155
|
+
* @param graphBaseUrl - Optional Graph base URL. Defaults to Microsoft Graph v1.0.
|
|
156
|
+
* @returns A Microsoft Graph client configured with the resolved authentication provider.
|
|
157
|
+
*/
|
|
158
|
+
public getGraphClient (context: TurnContext, handlerName?: string, graphBaseUrl: string = DEFAULT_GRAPH_BASE_URL): GraphClient {
|
|
159
|
+
if (!context) {
|
|
160
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'context' })
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return createUserGraphClient(this._app.authorization, context, handlerName, graphBaseUrl)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Creates a Microsoft Graph client that obtains an app-only token from the connection resolved for the current turn.
|
|
168
|
+
*
|
|
169
|
+
* @param context - The turn context used to resolve the token connection.
|
|
170
|
+
* @param graphBaseUrl - Optional Graph base URL. Defaults to Microsoft Graph v1.0.
|
|
171
|
+
* @returns A Microsoft Graph client configured with application permissions.
|
|
172
|
+
*/
|
|
173
|
+
public getAppGraphClient (context: TurnContext, graphBaseUrl: string = DEFAULT_GRAPH_BASE_URL): GraphClient {
|
|
174
|
+
if (!context) {
|
|
175
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'context' })
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const tokenProvider = this.getConnections().getTokenProviderFromActivity(context.identity, context.activity)
|
|
179
|
+
return createAppGraphClient(tokenProvider, graphBaseUrl)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Creates a Microsoft Graph client that obtains an app-only token from a named connection.
|
|
184
|
+
*
|
|
185
|
+
* @param connectionName - The configured token connection name.
|
|
186
|
+
* @param graphBaseUrl - Optional Graph base URL. Defaults to Microsoft Graph v1.0.
|
|
187
|
+
* @returns A Microsoft Graph client configured with application permissions.
|
|
188
|
+
*/
|
|
189
|
+
public getAppGraphClientForConnection (connectionName: string, graphBaseUrl: string = DEFAULT_GRAPH_BASE_URL): GraphClient {
|
|
190
|
+
if (!connectionName) {
|
|
191
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'connectionName' })
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return createAppGraphClient(this.getConnections().getConnection(connectionName), graphBaseUrl)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private getConnections (): Connections {
|
|
198
|
+
const connections = this._app.options.connections ?? this._app.adapter.connectionManager
|
|
199
|
+
if (!connections) {
|
|
200
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphConnectionsNotConfigured)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return connections
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { ExceptionHelper } from '@microsoft/agents-activity'
|
|
5
|
+
import { ConnectorClient, TurnContext } from '@microsoft/agents-hosting'
|
|
6
|
+
import { Client as TeamsClient } from '@microsoft/teams.api'
|
|
7
|
+
import { Errors } from './errorHelper'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Turn state key used to store the Teams API client for the current turn.
|
|
11
|
+
*/
|
|
12
|
+
export const TeamsClientKey = Symbol('TeamsClient')
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates and stores a Teams API client for the current Teams turn.
|
|
16
|
+
*
|
|
17
|
+
* @param context - Turn context whose turn state should receive the Teams client.
|
|
18
|
+
* @param channelId - Teams channel ID to match before creating the client. Defaults to `msteams`.
|
|
19
|
+
* @throws If the connector client or service URL required to create the Teams client is missing.
|
|
20
|
+
*/
|
|
21
|
+
export function setTeamsApiClient (context: TurnContext, channelId: string = 'msteams'): void {
|
|
22
|
+
if (context.activity.channelId !== channelId || context.turnState.has(TeamsClientKey)) {
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const connectorClient = context.turnState.get<ConnectorClient>(context.adapter.ConnectorClientKey)
|
|
27
|
+
const serviceUrl = context.activity.serviceUrl ?? connectorClient?.httpClient.baseURL
|
|
28
|
+
|
|
29
|
+
if (!connectorClient) {
|
|
30
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsApiClientSetupFailed, undefined, { missing: 'ConnectorClient in turnState' })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!serviceUrl) {
|
|
34
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsApiClientSetupFailed, undefined, { missing: 'activity.serviceUrl and ConnectorClient baseURL' })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
context.turnState.set(
|
|
38
|
+
TeamsClientKey,
|
|
39
|
+
new TeamsClient(serviceUrl, {
|
|
40
|
+
headers: getClientHeaders(connectorClient)
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getClientHeaders (connectorClient: ConnectorClient): Record<string, string> {
|
|
46
|
+
return { ...connectorClient.httpClient.defaultHeaders }
|
|
47
|
+
}
|