@microsoft/agents-hosting-extensions-msteams 1.7.0-beta.10.g0c6864b626
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,104 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { AgentErrorDefinition } from '@microsoft/agents-activity'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error definitions for the Teams Extensions system.
|
|
8
|
+
* This contains localized error codes for the Teams Extensions subsystem of the AgentSDK.
|
|
9
|
+
*
|
|
10
|
+
* Each error definition includes an error code (starting from -150000), a description, and a help link
|
|
11
|
+
* pointing to an AKA link to get help for the given error.
|
|
12
|
+
*
|
|
13
|
+
* Usage example:
|
|
14
|
+
* ```
|
|
15
|
+
* throw ExceptionHelper.generateException(
|
|
16
|
+
* Error,
|
|
17
|
+
* Errors.TeamsApiClientNotAvailable
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const Errors: { [key: string]: AgentErrorDefinition } = {
|
|
22
|
+
// Teams Graph Errors (-150012 to -150015, -150017 to -150019)
|
|
23
|
+
/**
|
|
24
|
+
* Error thrown when a Graph authorization handler returns an empty token.
|
|
25
|
+
*/
|
|
26
|
+
TeamsGraphTokenUnavailable: {
|
|
27
|
+
code: -150012,
|
|
28
|
+
description: 'Unable to acquire a Graph access token using authorization handler {handlerName}.'
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Error thrown when no Graph authorization handlers are configured.
|
|
33
|
+
*/
|
|
34
|
+
TeamsGraphAuthorizationHandlerRequired: {
|
|
35
|
+
code: -150013,
|
|
36
|
+
description: 'A Graph client requires at least one configured authorization handler.'
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Error thrown when multiple Graph authorization handlers are configured and no handler name is provided.
|
|
41
|
+
*/
|
|
42
|
+
TeamsGraphAuthorizationHandlerNameRequired: {
|
|
43
|
+
code: -150014,
|
|
44
|
+
description: 'A Graph client requires handlerName when multiple authorization handlers are configured.'
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Error thrown when a required Graph client parameter is missing.
|
|
49
|
+
*/
|
|
50
|
+
TeamsGraphParameterRequired: {
|
|
51
|
+
code: -150015,
|
|
52
|
+
description: 'The {parameterName} parameter is required to create a Graph client.'
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when the Graph base URL is invalid.
|
|
57
|
+
*/
|
|
58
|
+
TeamsGraphInvalidBaseUrl: {
|
|
59
|
+
code: -150017,
|
|
60
|
+
description: 'The graphBaseUrl parameter must be a valid absolute URL.'
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Error thrown when user authorization is unavailable from the current turn.
|
|
65
|
+
*/
|
|
66
|
+
TeamsGraphUserAuthorizationNotConfigured: {
|
|
67
|
+
code: -150018,
|
|
68
|
+
description: 'User authorization is not configured on the AgentApplication. A delegated Graph client requires configured user authorization.'
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Error thrown when token connections are unavailable.
|
|
73
|
+
*/
|
|
74
|
+
TeamsGraphConnectionsNotConfigured: {
|
|
75
|
+
code: -150019,
|
|
76
|
+
description: 'Connections are not configured on the AgentApplication. An app-only Graph client requires a configured token connection.'
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// TaskModule Errors (-150016)
|
|
80
|
+
/**
|
|
81
|
+
* Error thrown when unexpected TaskModules.submit() is triggered.
|
|
82
|
+
*/
|
|
83
|
+
UnexpectedTaskModuleSubmit: {
|
|
84
|
+
code: -150016,
|
|
85
|
+
description: 'Unexpected TaskModules.submit() triggered for activity type: {activityType}'
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// TeamsApiClient Errors (-150010 to -150011)
|
|
89
|
+
/**
|
|
90
|
+
* Error thrown when the Teams SDK client is not available in the context.
|
|
91
|
+
*/
|
|
92
|
+
TeamsApiClientNotAvailable: {
|
|
93
|
+
code: -150010,
|
|
94
|
+
description: 'Teams API client is not available in the context. Add TeamsAgentExtension to populate it before use.'
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Error thrown when Teams API client prerequisites are missing for Teams activities.
|
|
99
|
+
*/
|
|
100
|
+
TeamsApiClientSetupFailed: {
|
|
101
|
+
code: -150011,
|
|
102
|
+
description: 'Teams API client setup failed: missing {missing}.'
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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 { FileConsentCardResponse } from '@microsoft/teams.api'
|
|
7
|
+
import { TeamsTurnContext } from '../teamsTurnContext'
|
|
8
|
+
|
|
9
|
+
type FileConsentHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, response: FileConsentCardResponse) => Promise<void>
|
|
10
|
+
|
|
11
|
+
function isFileConsentAction (context: TurnContext, action: 'accept' | 'decline'): boolean {
|
|
12
|
+
const activityAction = (context.activity.value as any)?.action
|
|
13
|
+
return (
|
|
14
|
+
context.activity.type === ActivityTypes.Invoke &&
|
|
15
|
+
context.activity.channelId === 'msteams' &&
|
|
16
|
+
typeof context.activity.name === 'string' &&
|
|
17
|
+
context.activity.name.toLowerCase() === 'fileconsent/invoke' &&
|
|
18
|
+
typeof activityAction === 'string' &&
|
|
19
|
+
activityAction.toLowerCase() === action
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Registers handlers for Microsoft Teams file consent card actions.
|
|
25
|
+
*
|
|
26
|
+
* @typeParam TState - The turn state type used by the agent application.
|
|
27
|
+
*/
|
|
28
|
+
export class FileConsent<TState extends TurnState = TurnState> {
|
|
29
|
+
private _app: AgentApplication<TState>
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a Teams file consent route helper.
|
|
33
|
+
*
|
|
34
|
+
* @param app - The agent application that receives the registered routes.
|
|
35
|
+
*/
|
|
36
|
+
constructor (app: AgentApplication<TState>) {
|
|
37
|
+
this._app = app
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Registers a handler for accepted file consent cards.
|
|
42
|
+
*
|
|
43
|
+
* @param handler - Handler invoked with the file consent card response.
|
|
44
|
+
* @param rank - Optional route rank used for route ordering.
|
|
45
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
46
|
+
* @returns This file consent helper for chaining.
|
|
47
|
+
*/
|
|
48
|
+
onAccept (handler: FileConsentHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
49
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
50
|
+
return Promise.resolve(isFileConsentAction(context, 'accept'))
|
|
51
|
+
}
|
|
52
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
53
|
+
const cardResponse = context.activity.value as FileConsentCardResponse
|
|
54
|
+
await handler(new TeamsTurnContext(context), state, cardResponse)
|
|
55
|
+
const invokeResponse = new Activity(ActivityTypes.InvokeResponse)
|
|
56
|
+
invokeResponse.value = { status: 200 }
|
|
57
|
+
await context.sendActivity(invokeResponse)
|
|
58
|
+
}
|
|
59
|
+
this._app.addRoute(routeSel, routeHandler, true, rank, authHandlers)
|
|
60
|
+
return this
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Registers a handler for declined file consent cards.
|
|
65
|
+
*
|
|
66
|
+
* @param handler - Handler invoked with the file consent card response.
|
|
67
|
+
* @param rank - Optional route rank used for route ordering.
|
|
68
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
69
|
+
* @returns This file consent helper for chaining.
|
|
70
|
+
*/
|
|
71
|
+
onDecline (handler: FileConsentHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
72
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
73
|
+
return Promise.resolve(isFileConsentAction(context, 'decline'))
|
|
74
|
+
}
|
|
75
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
76
|
+
const cardResponse = context.activity.value as FileConsentCardResponse
|
|
77
|
+
await handler(new TeamsTurnContext(context), state, cardResponse)
|
|
78
|
+
const invokeResponse = new Activity(ActivityTypes.InvokeResponse)
|
|
79
|
+
invokeResponse.value = { status: 200 }
|
|
80
|
+
await context.sendActivity(invokeResponse)
|
|
81
|
+
}
|
|
82
|
+
this._app.addRoute(routeSel, routeHandler, true, rank, authHandlers)
|
|
83
|
+
return this
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import { ExceptionHelper } from '@microsoft/agents-activity'
|
|
5
|
+
import { type AuthProvider, type Authorization, type TurnContext } from '@microsoft/agents-hosting'
|
|
6
|
+
import { Client as GraphClient, type AuthenticationProvider, type ClientOptions } from '@microsoft/microsoft-graph-client'
|
|
7
|
+
import { Errors } from './errorHelper'
|
|
8
|
+
|
|
9
|
+
const DEFAULT_GRAPH_BASE_URL = 'https://graph.microsoft.com/v1.0'
|
|
10
|
+
|
|
11
|
+
class UserTokenProvider implements AuthenticationProvider {
|
|
12
|
+
constructor (
|
|
13
|
+
private readonly authorization: Authorization,
|
|
14
|
+
private readonly context: TurnContext,
|
|
15
|
+
private readonly handlerName?: string
|
|
16
|
+
) {}
|
|
17
|
+
|
|
18
|
+
async getAccessToken (): Promise<string> {
|
|
19
|
+
const handlerName = this.handlerName ?? this.getDefaultHandlerName()
|
|
20
|
+
const { token } = await this.authorization.getToken(this.context, handlerName)
|
|
21
|
+
|
|
22
|
+
if (!token?.trim()) {
|
|
23
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphTokenUnavailable, undefined, { handlerName })
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return token
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private getDefaultHandlerName (): string {
|
|
30
|
+
const authorization = this.authorization as unknown as {
|
|
31
|
+
manager?: { handlers?: Array<{ id: string }> }
|
|
32
|
+
}
|
|
33
|
+
const handlerIds = authorization.manager?.handlers?.map((handler) => handler.id) ?? []
|
|
34
|
+
|
|
35
|
+
if (handlerIds.length === 1) {
|
|
36
|
+
return handlerIds[0]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (handlerIds.length === 0) {
|
|
40
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphAuthorizationHandlerRequired)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphAuthorizationHandlerNameRequired)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class AppTokenProvider implements AuthenticationProvider {
|
|
48
|
+
constructor (
|
|
49
|
+
private readonly tokenProvider: AuthProvider,
|
|
50
|
+
private readonly scope: string
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
async getAccessToken (): Promise<string> {
|
|
54
|
+
return await this.tokenProvider.getAccessToken(this.scope)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a Microsoft Graph client authenticated with a delegated user token.
|
|
60
|
+
*/
|
|
61
|
+
export function createUserGraphClient (
|
|
62
|
+
authorization: Authorization,
|
|
63
|
+
context: TurnContext,
|
|
64
|
+
handlerName?: string,
|
|
65
|
+
graphBaseUrl: string = DEFAULT_GRAPH_BASE_URL
|
|
66
|
+
): GraphClient {
|
|
67
|
+
if (!authorization) {
|
|
68
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'authorization' })
|
|
69
|
+
}
|
|
70
|
+
if (!context) {
|
|
71
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'context' })
|
|
72
|
+
}
|
|
73
|
+
if (!graphBaseUrl) {
|
|
74
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'graphBaseUrl' })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let graphUrl: URL
|
|
78
|
+
try {
|
|
79
|
+
graphUrl = new URL(graphBaseUrl)
|
|
80
|
+
} catch {
|
|
81
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphInvalidBaseUrl)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return GraphClient.initWithMiddleware(createGraphClientOptions(
|
|
85
|
+
new UserTokenProvider(authorization, context, handlerName),
|
|
86
|
+
graphBaseUrl,
|
|
87
|
+
graphUrl
|
|
88
|
+
))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Creates a Microsoft Graph client authenticated with an app-only token.
|
|
93
|
+
*/
|
|
94
|
+
export function createAppGraphClient (
|
|
95
|
+
tokenProvider: AuthProvider,
|
|
96
|
+
graphBaseUrl: string = DEFAULT_GRAPH_BASE_URL
|
|
97
|
+
): GraphClient {
|
|
98
|
+
if (!tokenProvider) {
|
|
99
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'tokenProvider' })
|
|
100
|
+
}
|
|
101
|
+
if (!graphBaseUrl) {
|
|
102
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphParameterRequired, undefined, { parameterName: 'graphBaseUrl' })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let graphUrl: URL
|
|
106
|
+
try {
|
|
107
|
+
graphUrl = new URL(graphBaseUrl)
|
|
108
|
+
} catch {
|
|
109
|
+
throw ExceptionHelper.generateException(Error, Errors.TeamsGraphInvalidBaseUrl)
|
|
110
|
+
}
|
|
111
|
+
const scope = `${graphUrl.origin}/.default`
|
|
112
|
+
|
|
113
|
+
return GraphClient.initWithMiddleware(createGraphClientOptions(
|
|
114
|
+
new AppTokenProvider(tokenProvider, scope),
|
|
115
|
+
graphBaseUrl,
|
|
116
|
+
graphUrl
|
|
117
|
+
))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function createGraphClientOptions (authProvider: AuthenticationProvider, graphBaseUrl: string, graphUrl: URL): ClientOptions {
|
|
121
|
+
return {
|
|
122
|
+
authProvider,
|
|
123
|
+
baseUrl: graphBaseUrl,
|
|
124
|
+
defaultVersion: '',
|
|
125
|
+
customHosts: new Set([graphUrl.hostname])
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
export * from './activity-extensions'
|
|
5
|
+
export * from './app'
|
|
6
|
+
export * from './channels'
|
|
7
|
+
export * from './config'
|
|
8
|
+
export { Errors as TeamsExtensionErrors } from './errorHelper'
|
|
9
|
+
export * from './fileConsents'
|
|
10
|
+
export * from './meetings'
|
|
11
|
+
export * from './meetings/meeting'
|
|
12
|
+
export * from './messageExtensions'
|
|
13
|
+
export * from './messages'
|
|
14
|
+
export * from './models'
|
|
15
|
+
export * from './taskModules'
|
|
16
|
+
export * from './teams'
|
|
17
|
+
export type { TeamsActivity } from './teamsActivity'
|
|
18
|
+
export * from './teamsActivityExtensions'
|
|
19
|
+
export * from './teamsAgentExtension'
|
|
20
|
+
export * from './teamsModelExtensions'
|
|
21
|
+
export * from './teamsTurnContext'
|
|
22
|
+
export { type TeamsRouteHandler } from './teamsRouteHandler'
|
|
23
|
+
export * from './teamsProactiveServiceEndpoints'
|
|
@@ -0,0 +1,146 @@
|
|
|
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 type { MeetingDetails, TeamsChannelAccount } from '@microsoft/teams.api'
|
|
7
|
+
import { TeamsTurnContext } from '../teamsTurnContext'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Details provided by Teams meeting participant join and leave events.
|
|
11
|
+
*/
|
|
12
|
+
export interface MeetingParticipantsEventDetails {
|
|
13
|
+
/**
|
|
14
|
+
* Participants included in the meeting event.
|
|
15
|
+
*/
|
|
16
|
+
members: {
|
|
17
|
+
/**
|
|
18
|
+
* The Teams user account for the participant.
|
|
19
|
+
*/
|
|
20
|
+
user: TeamsChannelAccount
|
|
21
|
+
/**
|
|
22
|
+
* Meeting-specific participant state.
|
|
23
|
+
*/
|
|
24
|
+
meeting: {
|
|
25
|
+
/**
|
|
26
|
+
* Indicates whether the participant is currently in the meeting.
|
|
27
|
+
*/
|
|
28
|
+
inMeeting: boolean
|
|
29
|
+
/**
|
|
30
|
+
* Participant role in the meeting.
|
|
31
|
+
*/
|
|
32
|
+
role: string
|
|
33
|
+
}
|
|
34
|
+
}[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type MeetingStartHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, details: MeetingDetails) => Promise<void>
|
|
38
|
+
type MeetingEndHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, details: MeetingDetails) => Promise<void>
|
|
39
|
+
type MeetingParticipantsHandler<TState extends TurnState> = (context: TeamsTurnContext, state: TState, details: MeetingParticipantsEventDetails) => Promise<void>
|
|
40
|
+
|
|
41
|
+
function isMeetingEvent (context: TurnContext, eventName: string): boolean {
|
|
42
|
+
return (
|
|
43
|
+
context.activity.type === ActivityTypes.Event &&
|
|
44
|
+
context.activity.channelId === 'msteams' &&
|
|
45
|
+
typeof context.activity.name === 'string' &&
|
|
46
|
+
context.activity.name.toLowerCase() === eventName.toLowerCase()
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Registers handlers for Microsoft Teams meeting events.
|
|
52
|
+
*
|
|
53
|
+
* @typeParam TState - The turn state type used by the agent application.
|
|
54
|
+
*/
|
|
55
|
+
export class Meeting<TState extends TurnState> {
|
|
56
|
+
private _app: AgentApplication<TState>
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a Teams meeting route helper.
|
|
60
|
+
*
|
|
61
|
+
* @param app - The agent application that receives the registered routes.
|
|
62
|
+
*/
|
|
63
|
+
constructor (app: AgentApplication<TState>) {
|
|
64
|
+
this._app = app
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Registers a handler for Teams meeting start events.
|
|
69
|
+
*
|
|
70
|
+
* @param handler - Handler invoked with meeting details.
|
|
71
|
+
* @param rank - Optional route rank used for route ordering.
|
|
72
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
73
|
+
* @returns This meeting helper for chaining.
|
|
74
|
+
*/
|
|
75
|
+
onStart (handler: MeetingStartHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
76
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
77
|
+
return Promise.resolve(isMeetingEvent(context, 'application/vnd.microsoft.meetingStart'))
|
|
78
|
+
}
|
|
79
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
80
|
+
const details = context.activity.value as MeetingDetails
|
|
81
|
+
await handler(new TeamsTurnContext(context), state, details)
|
|
82
|
+
}
|
|
83
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Registers a handler for Teams meeting end events.
|
|
89
|
+
*
|
|
90
|
+
* @param handler - Handler invoked with meeting details.
|
|
91
|
+
* @param rank - Optional route rank used for route ordering.
|
|
92
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
93
|
+
* @returns This meeting helper for chaining.
|
|
94
|
+
*/
|
|
95
|
+
onEnd (handler: MeetingEndHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
96
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
97
|
+
return Promise.resolve(isMeetingEvent(context, 'application/vnd.microsoft.meetingEnd'))
|
|
98
|
+
}
|
|
99
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
100
|
+
const details = context.activity.value as MeetingDetails
|
|
101
|
+
await handler(new TeamsTurnContext(context), state, details)
|
|
102
|
+
}
|
|
103
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
104
|
+
return this
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Registers a handler for Teams meeting participant join events.
|
|
109
|
+
*
|
|
110
|
+
* @param handler - Handler invoked with participant event details.
|
|
111
|
+
* @param rank - Optional route rank used for route ordering.
|
|
112
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
113
|
+
* @returns This meeting helper for chaining.
|
|
114
|
+
*/
|
|
115
|
+
onParticipantsJoin (handler: MeetingParticipantsHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
116
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
117
|
+
return Promise.resolve(isMeetingEvent(context, 'application/vnd.microsoft.meetingParticipantJoin'))
|
|
118
|
+
}
|
|
119
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
120
|
+
const details = context.activity.value as MeetingParticipantsEventDetails
|
|
121
|
+
await handler(new TeamsTurnContext(context), state, details)
|
|
122
|
+
}
|
|
123
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
124
|
+
return this
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Registers a handler for Teams meeting participant leave events.
|
|
129
|
+
*
|
|
130
|
+
* @param handler - Handler invoked with participant event details.
|
|
131
|
+
* @param rank - Optional route rank used for route ordering.
|
|
132
|
+
* @param authHandlers - Optional authorization handlers required by the route.
|
|
133
|
+
* @returns This meeting helper for chaining.
|
|
134
|
+
*/
|
|
135
|
+
onParticipantsLeave (handler: MeetingParticipantsHandler<TState>, rank: number = RouteRank.Unspecified, authHandlers: string[] = []) {
|
|
136
|
+
const routeSel: RouteSelector = (context: TurnContext) => {
|
|
137
|
+
return Promise.resolve(isMeetingEvent(context, 'application/vnd.microsoft.meetingParticipantLeave'))
|
|
138
|
+
}
|
|
139
|
+
const routeHandler: RouteHandler<TState> = async (context: TurnContext, state: TState) => {
|
|
140
|
+
const details = context.activity.value as MeetingParticipantsEventDetails
|
|
141
|
+
await handler(new TeamsTurnContext(context), state, details)
|
|
142
|
+
}
|
|
143
|
+
this._app.addRoute(routeSel, routeHandler, false, rank, authHandlers)
|
|
144
|
+
return this
|
|
145
|
+
}
|
|
146
|
+
}
|