@microsoft/agents-hosting 0.1.49 → 0.2.7-gd7a3e9ef95

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.
Files changed (137) hide show
  1. package/dist/src/activityWireCompat.d.ts +19 -0
  2. package/dist/src/activityWireCompat.js +49 -0
  3. package/dist/src/activityWireCompat.js.map +1 -0
  4. package/dist/src/agent-client/agentClient.d.ts +8 -2
  5. package/dist/src/agent-client/agentClient.js +7 -10
  6. package/dist/src/agent-client/agentClient.js.map +1 -1
  7. package/dist/src/agent-client/{expressApi.d.ts → agentResponseHandler.d.ts} +2 -1
  8. package/dist/src/agent-client/{expressApi.js → agentResponseHandler.js} +16 -12
  9. package/dist/src/agent-client/agentResponseHandler.js.map +1 -0
  10. package/dist/src/agent-client/index.d.ts +1 -1
  11. package/dist/src/agent-client/index.js +1 -1
  12. package/dist/src/agent-client/index.js.map +1 -1
  13. package/dist/src/app/agentApplication.d.ts +9 -8
  14. package/dist/src/app/agentApplication.js +17 -8
  15. package/dist/src/app/agentApplication.js.map +1 -1
  16. package/dist/src/app/{applicationBuilder.d.ts → agentApplicationBuilder.d.ts} +6 -6
  17. package/dist/src/app/{applicationBuilder.js → agentApplicationBuilder.js} +4 -4
  18. package/dist/src/app/agentApplicationBuilder.js.map +1 -0
  19. package/dist/src/app/{applicationOptions.d.ts → agentApplicationOptions.d.ts} +3 -3
  20. package/dist/src/app/{applicationOptions.js → agentApplicationOptions.js} +1 -1
  21. package/dist/src/app/agentApplicationOptions.js.map +1 -0
  22. package/dist/src/app/index.d.ts +4 -3
  23. package/dist/src/app/index.js +4 -3
  24. package/dist/src/app/index.js.map +1 -1
  25. package/dist/src/app/oauth/userIdentity.d.ts +43 -0
  26. package/dist/src/app/oauth/userIdentity.js +54 -0
  27. package/dist/src/app/oauth/userIdentity.js.map +1 -0
  28. package/dist/src/app/turnState.d.ts +1 -1
  29. package/dist/src/app/turnState.js +2 -2
  30. package/dist/src/app/turnState.js.map +1 -1
  31. package/dist/src/app/turnStateProperty.d.ts +40 -0
  32. package/dist/src/app/turnStateProperty.js +57 -0
  33. package/dist/src/app/turnStateProperty.js.map +1 -0
  34. package/dist/src/auth/authConfiguration.d.ts +21 -2
  35. package/dist/src/auth/authConfiguration.js +23 -4
  36. package/dist/src/auth/authConfiguration.js.map +1 -1
  37. package/dist/src/auth/jwt-middleware.js +2 -1
  38. package/dist/src/auth/jwt-middleware.js.map +1 -1
  39. package/dist/src/auth/msalTokenProvider.js +1 -1
  40. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  41. package/dist/src/cards/cardFactory.d.ts +8 -0
  42. package/dist/src/cards/cardFactory.js +22 -1
  43. package/dist/src/cards/cardFactory.js.map +1 -1
  44. package/dist/src/cloudAdapter.d.ts +1 -2
  45. package/dist/src/cloudAdapter.js +7 -2
  46. package/dist/src/cloudAdapter.js.map +1 -1
  47. package/dist/src/connector-client/connectorClient.d.ts +3 -2
  48. package/dist/src/connector-client/connectorClient.js +15 -3
  49. package/dist/src/connector-client/connectorClient.js.map +1 -1
  50. package/dist/src/connector-client/index.d.ts +0 -1
  51. package/dist/src/connector-client/index.js +0 -1
  52. package/dist/src/connector-client/index.js.map +1 -1
  53. package/dist/src/getProductInfo.d.ts +1 -0
  54. package/dist/src/getProductInfo.js +11 -0
  55. package/dist/src/getProductInfo.js.map +1 -0
  56. package/dist/src/index.d.ts +2 -1
  57. package/dist/src/index.js +2 -1
  58. package/dist/src/index.js.map +1 -1
  59. package/dist/src/oauth/index.d.ts +3 -4
  60. package/dist/src/oauth/index.js +3 -4
  61. package/dist/src/oauth/index.js.map +1 -1
  62. package/dist/src/oauth/{oauthCard.d.ts → oAuthCard.d.ts} +1 -2
  63. package/dist/src/oauth/{oauthCard.js → oAuthCard.js} +1 -1
  64. package/dist/src/oauth/oAuthCard.js.map +1 -0
  65. package/dist/src/oauth/oAuthFlow.d.ts +47 -0
  66. package/dist/src/oauth/oAuthFlow.js +158 -0
  67. package/dist/src/oauth/oAuthFlow.js.map +1 -0
  68. package/dist/src/oauth/signingResource.d.ts +27 -3
  69. package/dist/src/oauth/tokenResponse.d.ts +29 -0
  70. package/dist/src/oauth/tokenResponse.js +25 -0
  71. package/dist/src/oauth/tokenResponse.js.map +1 -0
  72. package/dist/src/oauth/userTokenClient.d.ts +4 -3
  73. package/dist/src/oauth/userTokenClient.js +23 -13
  74. package/dist/src/oauth/userTokenClient.js.map +1 -1
  75. package/dist/src/state/agentState.d.ts +8 -3
  76. package/dist/src/state/agentState.js +17 -6
  77. package/dist/src/state/agentState.js.map +1 -1
  78. package/dist/src/state/agentStatePropertyAccesor.d.ts +58 -5
  79. package/dist/src/state/agentStatePropertyAccesor.js +6 -6
  80. package/dist/src/state/agentStatePropertyAccesor.js.map +1 -1
  81. package/package.json +3 -6
  82. package/src/activityWireCompat.ts +45 -0
  83. package/src/agent-client/agentClient.ts +21 -13
  84. package/src/agent-client/{expressApi.ts → agentResponseHandler.ts} +20 -12
  85. package/src/agent-client/index.ts +1 -1
  86. package/src/app/agentApplication.ts +24 -15
  87. package/src/app/{applicationBuilder.ts → agentApplicationBuilder.ts} +5 -5
  88. package/src/app/{applicationOptions.ts → agentApplicationOptions.ts} +3 -3
  89. package/src/app/index.ts +4 -3
  90. package/src/app/oauth/userIdentity.ts +78 -0
  91. package/src/app/turnState.ts +2 -2
  92. package/src/app/turnStateProperty.ts +72 -0
  93. package/src/auth/authConfiguration.ts +23 -4
  94. package/src/auth/jwt-middleware.ts +2 -1
  95. package/src/auth/msalTokenProvider.ts +1 -1
  96. package/src/cards/cardFactory.ts +26 -2
  97. package/src/cloudAdapter.ts +8 -4
  98. package/src/connector-client/connectorClient.ts +15 -5
  99. package/src/connector-client/index.ts +0 -1
  100. package/src/getProductInfo.ts +3 -0
  101. package/src/index.ts +2 -2
  102. package/src/oauth/index.ts +3 -4
  103. package/src/oauth/{oauthCard.ts → oAuthCard.ts} +1 -3
  104. package/src/oauth/oAuthFlow.ts +175 -0
  105. package/src/oauth/signingResource.ts +28 -3
  106. package/src/oauth/tokenResponse.ts +43 -0
  107. package/src/oauth/userTokenClient.ts +26 -16
  108. package/src/state/agentState.ts +25 -6
  109. package/src/state/agentStatePropertyAccesor.ts +65 -8
  110. package/dist/src/agent-client/expressApi.js.map +0 -1
  111. package/dist/src/app/applicationBuilder.js.map +0 -1
  112. package/dist/src/app/applicationOptions.js.map +0 -1
  113. package/dist/src/app/oauth/authenticationOptions.d.ts +0 -7
  114. package/dist/src/app/oauth/authenticationOptions.js +0 -7
  115. package/dist/src/app/oauth/authenticationOptions.js.map +0 -1
  116. package/dist/src/app/oauth/webChatOAuthFlowAppStyle.d.ts +0 -11
  117. package/dist/src/app/oauth/webChatOAuthFlowAppStyle.js +0 -85
  118. package/dist/src/app/oauth/webChatOAuthFlowAppStyle.js.map +0 -1
  119. package/dist/src/connector-client/conversationParameters.d.ts +0 -38
  120. package/dist/src/connector-client/conversationParameters.js +0 -7
  121. package/dist/src/connector-client/conversationParameters.js.map +0 -1
  122. package/dist/src/oauth/oauthCard.js.map +0 -1
  123. package/dist/src/oauth/tokenExchangeResource.d.ts +0 -17
  124. package/dist/src/oauth/tokenExchangeResource.js +0 -5
  125. package/dist/src/oauth/tokenExchangeResource.js.map +0 -1
  126. package/dist/src/oauth/tokenPostResource.d.ts +0 -9
  127. package/dist/src/oauth/tokenPostResource.js +0 -5
  128. package/dist/src/oauth/tokenPostResource.js.map +0 -1
  129. package/dist/src/oauth/webChatOAuthFlow.d.ts +0 -41
  130. package/dist/src/oauth/webChatOAuthFlow.js +0 -117
  131. package/dist/src/oauth/webChatOAuthFlow.js.map +0 -1
  132. package/src/app/oauth/authenticationOptions.ts +0 -8
  133. package/src/app/oauth/webChatOAuthFlowAppStyle.ts +0 -90
  134. package/src/connector-client/conversationParameters.ts +0 -40
  135. package/src/oauth/tokenExchangeResource.ts +0 -20
  136. package/src/oauth/tokenPostResource.ts +0 -12
  137. package/src/oauth/webChatOAuthFlow.ts +0 -123
@@ -0,0 +1,175 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT License.
3
+ import { debug } from './../logger'
4
+ import { Activity, ActivityTypes, Attachment } from '@microsoft/agents-activity'
5
+ import {
6
+ CardFactory,
7
+ AgentStatePropertyAccessor,
8
+ UserState,
9
+ TurnContext,
10
+ MessageFactory,
11
+ SigningResource,
12
+ TokenExchangeRequest,
13
+ UserTokenClient
14
+ } from '../'
15
+ import { TokenRequestStatus, TokenResponse } from './tokenResponse'
16
+
17
+ const logger = debug('agents:oauth-flow')
18
+
19
+ export class FlowState {
20
+ public flowStarted: boolean = false
21
+ public flowExpires: number = 0
22
+ }
23
+
24
+ interface TokenVerifyState {
25
+ state: string
26
+ }
27
+ /**
28
+ * Manages the OAuth flow for Teams.
29
+ */
30
+ export class OAuthFlow {
31
+ userTokenClient?: UserTokenClient
32
+ state: FlowState | null
33
+ flowStateAccessor: AgentStatePropertyAccessor<FlowState | null>
34
+ tokenExchangeId: string | null = null
35
+ absOauthConnectionName: string
36
+ /**
37
+ * Creates a new instance of OAuthFlow.
38
+ * @param userState The user state.
39
+ */
40
+ constructor (userState: UserState, absOauthConnectionName: string, tokenClient?: UserTokenClient) {
41
+ this.state = null
42
+ this.flowStateAccessor = userState.createProperty('flowState')
43
+ this.absOauthConnectionName = absOauthConnectionName
44
+ this.userTokenClient = tokenClient
45
+ }
46
+
47
+ public async getUserToken (context: TurnContext): Promise<TokenResponse> {
48
+ await this.initializeTokenClient(context)
49
+ return await this.userTokenClient?.getUserToken(this.absOauthConnectionName, context.activity.channelId!, context.activity.from?.id!)!
50
+ }
51
+
52
+ /**
53
+ * Begins the OAuth flow.
54
+ * @param context The turn context.
55
+ * @returns A promise that resolves to the user token.
56
+ */
57
+ public async beginFlow (context: TurnContext): Promise<TokenResponse> {
58
+ logger.info('Starting OAuth flow')
59
+ this.state = await this.getUserState(context)
60
+
61
+ const authConfig = context.adapter.authConfig
62
+ if (this.absOauthConnectionName === '') {
63
+ throw new Error('connectionName is not set in the auth config, review your environment variables')
64
+ }
65
+ await this.initializeTokenClient(context)
66
+
67
+ const tokenResponse = await this.userTokenClient!.getUserToken(this.absOauthConnectionName, context.activity.channelId!, context.activity.from?.id!)
68
+ if (tokenResponse?.status === TokenRequestStatus.Success) {
69
+ this.state.flowStarted = false
70
+ this.state.flowExpires = 0
71
+ await this.flowStateAccessor.set(context, this.state)
72
+ logger.info('User token retrieved successfully from service')
73
+ return tokenResponse
74
+ }
75
+
76
+ const signingResource: SigningResource = await this.userTokenClient!.getSignInResource(authConfig.clientId!, this.absOauthConnectionName, context.activity)
77
+ const oCard: Attachment = CardFactory.oauthCard(this.absOauthConnectionName, 'Sign in', 'login', signingResource)
78
+ const cardActivity : Activity = MessageFactory.attachment(oCard)
79
+ await context.sendActivity(cardActivity)
80
+ this.state.flowStarted = true
81
+ this.state.flowExpires = Date.now() + 30000
82
+ await this.flowStateAccessor.set(context, this.state)
83
+ logger.info('OAuth begin flow completed, waiting for user to sign in')
84
+ return {
85
+ token: undefined,
86
+ status: TokenRequestStatus.InProgress
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Continues the OAuth flow.
92
+ * @param context The turn context.
93
+ * @returns A promise that resolves to the user token.
94
+ */
95
+ public async continueFlow (context: TurnContext): Promise<TokenResponse> {
96
+ this.state = await this.getUserState(context)
97
+ await this.initializeTokenClient(context)
98
+ if (this.state?.flowExpires !== 0 && Date.now() > this.state!.flowExpires) {
99
+ logger.warn('Flow expired')
100
+ this.state!.flowStarted = false
101
+ await context.sendActivity(MessageFactory.text('Sign-in session expired. Please try again.'))
102
+ return { status: TokenRequestStatus.Expired, token: undefined }
103
+ }
104
+ const contFlowActivity = context.activity
105
+ if (contFlowActivity.type === ActivityTypes.Message) {
106
+ const magicCode = contFlowActivity.text as string
107
+ const result = await this.userTokenClient?.getUserToken(this.absOauthConnectionName, contFlowActivity.channelId!, contFlowActivity.from?.id!, magicCode)!
108
+ return result
109
+ }
110
+
111
+ if (contFlowActivity.type === ActivityTypes.Invoke && contFlowActivity.name === 'signin/verifyState') {
112
+ logger.info('Continuing OAuth flow with verifyState')
113
+ const tokenVerifyState = contFlowActivity.value as TokenVerifyState
114
+ const magicCode = tokenVerifyState.state
115
+ const result = await this.userTokenClient?.getUserToken(this.absOauthConnectionName, contFlowActivity.channelId!, contFlowActivity.from?.id!, magicCode)!
116
+ return result
117
+ }
118
+
119
+ if (contFlowActivity.type === ActivityTypes.Invoke && contFlowActivity.name === 'signin/tokenExchange') {
120
+ logger.info('Continuing OAuth flow with tokenExchange')
121
+ const tokenExchangeRequest = contFlowActivity.value as TokenExchangeRequest
122
+ if (this.tokenExchangeId === tokenExchangeRequest.id) { // dedupe
123
+ return { status: TokenRequestStatus.InProgress, token: undefined }
124
+ }
125
+ this.tokenExchangeId = tokenExchangeRequest.id!
126
+ const userTokenResp = await this.userTokenClient?.exchangeTokenAsync(contFlowActivity.from?.id!, this.absOauthConnectionName, contFlowActivity.channelId!, tokenExchangeRequest)
127
+ if (userTokenResp?.status === TokenRequestStatus.Success) {
128
+ logger.info('Token exchanged')
129
+ this.state!.flowStarted = false
130
+ await this.flowStateAccessor.set(context, this.state)
131
+ return userTokenResp
132
+ } else {
133
+ logger.warn('Token exchange failed')
134
+ this.state!.flowStarted = true
135
+ return { status: TokenRequestStatus.Failed, token: undefined }
136
+ }
137
+ }
138
+ return { status: TokenRequestStatus.Failed, token: undefined }
139
+ }
140
+
141
+ /**
142
+ * Signs the user out.
143
+ * @param context The turn context.
144
+ * @returns A promise that resolves when the sign-out operation is complete.
145
+ */
146
+ public async signOut (context: TurnContext): Promise<void> {
147
+ this.state = await this.getUserState(context)
148
+ await this.initializeTokenClient(context)
149
+ await this.userTokenClient?.signOut(context.activity.from?.id as string, this.absOauthConnectionName, context.activity.channelId as string)
150
+ this.state!.flowExpires = 0
151
+ await this.flowStateAccessor.set(context, this.state)
152
+ logger.info('User signed out successfully')
153
+ }
154
+
155
+ /**
156
+ * Gets the user state.
157
+ * @param context The turn context.
158
+ * @returns A promise that resolves to the user state.
159
+ */
160
+ private async getUserState (context: TurnContext) {
161
+ let userProfile: FlowState | null = await this.flowStateAccessor.get(context, null)
162
+ if (userProfile === null) {
163
+ userProfile = new FlowState()
164
+ }
165
+ return userProfile
166
+ }
167
+
168
+ private async initializeTokenClient (context: TurnContext) {
169
+ if (this.userTokenClient === undefined) {
170
+ const scope = 'https://api.botframework.com'
171
+ const accessToken = await context.adapter.authProvider.getAccessToken(context.adapter.authConfig, scope)
172
+ this.userTokenClient = new UserTokenClient(accessToken)
173
+ }
174
+ }
175
+ }
@@ -1,8 +1,33 @@
1
1
  // Copyright (c) Microsoft Corporation. All rights reserved.
2
2
  // Licensed under the MIT License.
3
3
 
4
- import { TokenExchangeResource } from './tokenExchangeResource'
5
- import { TokenPostResource } from './tokenPostResource'
4
+ /**
5
+ * Represents a resource for exchanging tokens.
6
+ */
7
+ export interface TokenExchangeResource {
8
+ /**
9
+ * The ID of the token exchange resource.
10
+ */
11
+ id?: string
12
+ /**
13
+ * The URI of the token exchange resource.
14
+ */
15
+ uri?: string
16
+ /**
17
+ * The provider ID for the token exchange resource.
18
+ */
19
+ providerId?: string
20
+ }
21
+
22
+ /**
23
+ * Represents a resource for posting tokens.
24
+ */
25
+ export interface TokenPostResource {
26
+ /**
27
+ * The SAS URL for the token post resource.
28
+ */
29
+ sasUrl?: string
30
+ }
6
31
 
7
32
  /**
8
33
  * Represents a resource for signing in.
@@ -11,7 +36,7 @@ export interface SigningResource {
11
36
  /**
12
37
  * The link for signing in.
13
38
  */
14
- singingLink: string,
39
+ signInLink: string,
15
40
  /**
16
41
  * The resource for token exchange.
17
42
  */
@@ -0,0 +1,43 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT License.
3
+
4
+ /**
5
+ * Represents the status of an OAuth token request.
6
+ */
7
+ export enum TokenRequestStatus {
8
+ /**
9
+ * Indicates that the token request was successful.
10
+ */
11
+ Success = 'Success',
12
+
13
+ /**
14
+ * Indicates that the token request failed.
15
+ */
16
+ Failed = 'Failed',
17
+
18
+ /**
19
+ * Indicates that the token request is pending.
20
+ */
21
+ InProgress = 'InProgress',
22
+
23
+ Expired = 'Expired',
24
+ }
25
+
26
+ /**
27
+ * Represents the response containing OAuth token information.
28
+ * This interface encapsulates all data related to an OAuth token response.
29
+ */
30
+ export interface TokenResponse {
31
+
32
+ status: TokenRequestStatus
33
+
34
+ /**
35
+ * The OAuth token string, or null if no token is available.
36
+ */
37
+ token: string | undefined
38
+
39
+ /**
40
+ * The expiration time of the token, represented as a numeric timestamp.
41
+ */
42
+ // expires: number
43
+ }
@@ -6,8 +6,11 @@ import { SigningResource } from './signingResource'
6
6
  import { Activity } from '@microsoft/agents-activity'
7
7
  import { debug } from '../logger'
8
8
  import { TokenExchangeRequest } from './tokenExchangeRequest'
9
+ import { normalizeTokenExchangeState } from '../activityWireCompat'
10
+ import { TokenRequestStatus, TokenResponse } from './tokenResponse'
11
+ import { getProductInfo } from '../getProductInfo'
9
12
 
10
- const logger = debug('agents:userTokenClient')
13
+ const logger = debug('agents:user-token-client')
11
14
 
12
15
  /**
13
16
  * Client for managing user tokens.
@@ -24,7 +27,8 @@ export class UserTokenClient {
24
27
  const axiosInstance = axios.create({
25
28
  baseURL,
26
29
  headers: {
27
- Accept: 'application/json'
30
+ Accept: 'application/json',
31
+ 'User-Agent': getProductInfo(),
28
32
  }
29
33
  })
30
34
  axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`
@@ -39,16 +43,19 @@ export class UserTokenClient {
39
43
  * @param code The optional code.
40
44
  * @returns A promise that resolves to the user token.
41
45
  */
42
- async getUserToken (connectionName: string, channelId: string, userId: string, code?: string) {
46
+ async getUserToken (connectionName: string, channelId: string, userId: string, code?: string) : Promise<TokenResponse> {
43
47
  try {
44
48
  const params = { connectionName, channelId, userId, code }
45
49
  const response = await this.client.get('/api/usertoken/GetToken', { params })
46
- return response.data
50
+ return { ...response.data, status: TokenRequestStatus.Success }
47
51
  } catch (error: any) {
48
52
  if (error.response?.status !== 404) {
49
53
  logger.error(error)
50
54
  }
51
- return null
55
+ return {
56
+ status: TokenRequestStatus.Failed,
57
+ token: undefined
58
+ }
52
59
  }
53
60
  }
54
61
 
@@ -59,14 +66,16 @@ export class UserTokenClient {
59
66
  * @param channelId The channel ID.
60
67
  * @returns A promise that resolves when the sign-out operation is complete.
61
68
  */
62
- async signOut (userId: string, connectionName: string, channelId: string) {
69
+ async signOut (userId: string, connectionName: string, channelId: string) : Promise<void> {
63
70
  try {
64
71
  const params = { userId, connectionName, channelId }
65
72
  const response = await this.client.delete('/api/usertoken/SignOut', { params })
66
- return response.data
73
+ if (response.status !== 200) {
74
+ throw new Error('Failed to sign out')
75
+ }
67
76
  } catch (error: any) {
68
77
  logger.error(error)
69
- return null
78
+ throw new Error('Failed to sign out')
70
79
  }
71
80
  }
72
81
 
@@ -80,12 +89,13 @@ export class UserTokenClient {
80
89
  async getSignInResource (appId: string, cnxName: string, activity: Activity) : Promise<SigningResource> {
81
90
  try {
82
91
  const tokenExchangeState = {
83
- ConnectionName: cnxName,
84
- Conversation: activity.getConversationReference(),
85
- RelatesTo: activity.RelatesTo,
86
- MsAppId: appId
92
+ connectionName: cnxName,
93
+ conversation: activity.getConversationReference(),
94
+ relatesTo: activity.RelatesTo,
95
+ msAppId: appId
87
96
  }
88
- const state = Buffer.from(JSON.stringify(tokenExchangeState)).toString('base64')
97
+ const tokenExchangeStateNormalized = normalizeTokenExchangeState(tokenExchangeState)
98
+ const state = Buffer.from(JSON.stringify(tokenExchangeStateNormalized)).toString('base64')
89
99
  const params = { state }
90
100
  const response = await this.client.get('/api/botsignin/GetSignInResource', { params })
91
101
  return response.data as SigningResource
@@ -103,14 +113,14 @@ export class UserTokenClient {
103
113
  * @param tokenExchangeRequest The token exchange request.
104
114
  * @returns A promise that resolves to the exchanged token.
105
115
  */
106
- async exchangeTokenAsync (userId: string, connectionName: string, channelId: string, tokenExchangeRequest: TokenExchangeRequest) {
116
+ async exchangeTokenAsync (userId: string, connectionName: string, channelId: string, tokenExchangeRequest: TokenExchangeRequest) : Promise<TokenResponse> {
107
117
  try {
108
118
  const params = { userId, connectionName, channelId }
109
119
  const response = await this.client.post('/api/usertoken/exchange', tokenExchangeRequest, { params })
110
- return response.data
120
+ return { ...response.data, status: TokenRequestStatus.Success }
111
121
  } catch (error: any) {
112
122
  logger.error(error)
113
- return null
123
+ return { status: TokenRequestStatus.Failed, token: undefined }
114
124
  }
115
125
  }
116
126
  }
@@ -16,6 +16,12 @@ export interface CachedAgentState {
16
16
  hash: string
17
17
  }
18
18
 
19
+ export interface CustomKey {
20
+ channelId: string;
21
+ conversationId: string;
22
+ // TODO: namespace needs to be added
23
+ }
24
+
19
25
  /**
20
26
  * Manages the state of an Agent.
21
27
  */
@@ -45,11 +51,11 @@ export class AgentState {
45
51
  * @param force Whether to force loading the state.
46
52
  * @returns A promise that resolves to the loaded state.
47
53
  */
48
- public async load (context: TurnContext, force = false): Promise<any> {
54
+ public async load (context: TurnContext, force = false, customKey?: CustomKey): Promise<any> {
49
55
  const cached: CachedAgentState = context.turnState.get(this.stateKey)
50
56
 
51
57
  if (force || !cached || !cached.state) {
52
- const key = await this.storageKey(context)
58
+ const key: string = await this.getStorageOrCustomKey(customKey, context)
53
59
  logger.info(`Reading storage with key ${key}`)
54
60
  const storedItem = await this.storage.read([key])
55
61
 
@@ -69,7 +75,7 @@ export class AgentState {
69
75
  * @param force Whether to force saving the state.
70
76
  * @returns A promise that resolves when the save operation is complete.
71
77
  */
72
- public async saveChanges (context: TurnContext, force = false): Promise<void> {
78
+ public async saveChanges (context: TurnContext, force = false, customKey?: CustomKey): Promise<void> {
73
79
  let cached: CachedAgentState = context.turnState.get(this.stateKey)
74
80
  if (force || (cached && cached.hash !== this.calculateChangeHash(cached?.state))) {
75
81
  if (!cached) {
@@ -78,7 +84,8 @@ export class AgentState {
78
84
  cached.state.eTag = '*'
79
85
  const changes: StoreItem = {} as StoreItem
80
86
 
81
- const key = await this.storageKey(context)
87
+ const key: string = await this.getStorageOrCustomKey(customKey, context)
88
+
82
89
  changes[key] = cached.state
83
90
 
84
91
  logger.info(`Writing storage with key ${key}`)
@@ -88,6 +95,17 @@ export class AgentState {
88
95
  }
89
96
  }
90
97
 
98
+ private async getStorageOrCustomKey (customKey: CustomKey | undefined, context: TurnContext) {
99
+ let key: string | undefined
100
+ if (customKey && customKey.channelId && customKey.conversationId) {
101
+ // TODO check ConversationState.ts line 40. This line below should follow the same pattern
102
+ key = `${customKey!.channelId}/conversations/${customKey!.conversationId}`
103
+ } else {
104
+ key = await this.storageKey(context)
105
+ }
106
+ return key
107
+ }
108
+
91
109
  /**
92
110
  * Clears the state from the turn context.
93
111
  * @param context The turn context.
@@ -95,6 +113,7 @@ export class AgentState {
95
113
  */
96
114
  public async clear (context: TurnContext): Promise<void> {
97
115
  const emptyObjectToForceSave = { state: {}, hash: '' }
116
+
98
117
  context.turnState.set(this.stateKey, emptyObjectToForceSave)
99
118
  }
100
119
 
@@ -103,11 +122,11 @@ export class AgentState {
103
122
  * @param context The turn context.
104
123
  * @returns A promise that resolves when the delete operation is complete.
105
124
  */
106
- public async delete (context: TurnContext): Promise<void> {
125
+ public async delete (context: TurnContext, customKey?: CustomKey): Promise<void> {
107
126
  if (context.turnState.has(this.stateKey)) {
108
127
  context.turnState.delete(this.stateKey)
109
128
  }
110
- const key = await this.storageKey(context)
129
+ const key = await this.getStorageOrCustomKey(customKey, context)
111
130
  logger.info(`Deleting storage with key ${key}`)
112
131
  await this.storage.delete([key])
113
132
  }
@@ -4,12 +4,69 @@
4
4
  */
5
5
 
6
6
  import { TurnContext } from '../turnContext'
7
- import { AgentState } from './agentState'
7
+ import { AgentState, CustomKey } from './agentState'
8
+
9
+ export interface StatePropertyAccessor<T = any> {
10
+ /**
11
+ * Deletes the persisted property from its backing storage object.
12
+ *
13
+ * @remarks
14
+ * The properties backing storage object SHOULD be loaded into memory on first access.
15
+ *
16
+ * ```JavaScript
17
+ * await myProperty.delete(context);
18
+ * ```
19
+ * @param context Context for the current turn of conversation with the user.
20
+ */
21
+ delete(context: TurnContext): Promise<void>;
22
+
23
+ /**
24
+ * Reads a persisted property from its backing storage object.
25
+ *
26
+ * @remarks
27
+ * The properties backing storage object SHOULD be loaded into memory on first access.
28
+ *
29
+ * If the property does not currently exist on the storage object and a `defaultValue` has been
30
+ * specified, a clone of the `defaultValue` SHOULD be copied to the storage object. If a
31
+ * `defaultValue` has not been specified then a value of `undefined` SHOULD be returned.
32
+ *
33
+ * ```JavaScript
34
+ * const value = await myProperty.get(context, { count: 0 });
35
+ * ```
36
+ * @param context Context for the current turn of conversation with the user.
37
+ */
38
+ get(context: TurnContext): Promise<T | undefined>;
39
+
40
+ /**
41
+ * Reads a persisted property from its backing storage object.
42
+ *
43
+ * @param context Context for the current turn of conversation with the user.
44
+ * @param defaultValue (Optional) default value to copy to the backing storage object if the property isn't found.
45
+ */
46
+ get(context: TurnContext, defaultValue: T): Promise<T>;
47
+
48
+ /**
49
+ * Assigns a new value to the properties backing storage object.
50
+ *
51
+ * @remarks
52
+ * The properties backing storage object SHOULD be loaded into memory on first access.
53
+ *
54
+ * Depending on the state systems implementation, an additional step may be required to
55
+ * persist the actual changes to disk.
56
+ *
57
+ * ```JavaScript
58
+ * await myProperty.set(context, value);
59
+ * ```
60
+ * @param context Context for the current turn of conversation with the user.
61
+ * @param value Value to assign.
62
+ */
63
+ set(context: TurnContext, value: T): Promise<void>;
64
+ }
8
65
 
9
66
  /**
10
67
  * Provides access to an Agent state property.
11
68
  */
12
- export class AgentStatePropertyAccessor<T = any> {
69
+ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccessor<T> {
13
70
  /**
14
71
  * Creates a new instance of AgentStatePropertyAccessor.
15
72
  * @param state The agent state.
@@ -22,8 +79,8 @@ export class AgentStatePropertyAccessor<T = any> {
22
79
  * @param context The turn context.
23
80
  * @returns A promise that resolves when the delete operation is complete.
24
81
  */
25
- async delete (context: TurnContext): Promise<void> {
26
- const obj: any = await this.state.load(context)
82
+ async delete (context: TurnContext, customKey?: CustomKey): Promise<void> {
83
+ const obj: any = await this.state.load(context, false, customKey)
27
84
  if (Object.prototype.hasOwnProperty.call(obj, this.name)) {
28
85
  delete obj[this.name]
29
86
  }
@@ -35,8 +92,8 @@ export class AgentStatePropertyAccessor<T = any> {
35
92
  * @param defaultValue The default value to return if the property is not found.
36
93
  * @returns A promise that resolves to the value of the property.
37
94
  */
38
- async get (context: TurnContext, defaultValue?: T): Promise<T> {
39
- const obj: any = await this.state.load(context)
95
+ async get (context: TurnContext, defaultValue?: T, customKey?: CustomKey): Promise<T> {
96
+ const obj: any = await this.state.load(context, false, customKey)
40
97
  if (!Object.prototype.hasOwnProperty.call(obj, this.name) && defaultValue !== undefined) {
41
98
  const clone: any =
42
99
  typeof defaultValue === 'object' || Array.isArray(defaultValue)
@@ -54,8 +111,8 @@ export class AgentStatePropertyAccessor<T = any> {
54
111
  * @param value The value to set.
55
112
  * @returns A promise that resolves when the set operation is complete.
56
113
  */
57
- async set (context: TurnContext, value: T): Promise<void> {
58
- const obj: any = await this.state.load(context)
114
+ async set (context: TurnContext, value: T, customKey?: CustomKey): Promise<void> {
115
+ const obj: any = await this.state.load(context, false, customKey)
59
116
  obj[this.name] = value
60
117
  }
61
118
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"expressApi.js","sourceRoot":"","sources":["../../../src/agent-client/expressApi.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"applicationBuilder.js","sourceRoot":"","sources":["../../../src/app/applicationBuilder.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yDAAqD;AAMrD,MAAa,kBAAkB;IAA/B;QACY,aAAQ,GAAwC,EAAE,CAAA;IA6B9D,CAAC;IA3BC,IAAc,OAAO;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAEM,WAAW,CAAE,OAAgB;QAClC,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAA;QAC/B,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,oBAAoB,CAAE,gBAA8B;QACzD,IAAI,CAAC,QAAQ,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,mBAAmB,CAAE,gBAAyB;QACnD,IAAI,CAAC,QAAQ,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,kBAAkB,CAAE,qBAA4C;QACrE,IAAI,CAAC,QAAQ,CAAC,cAAc,GAAG,qBAAqB,CAAA;QACpD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,mCAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC5C,CAAC;CACF;AA9BD,gDA8BC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"applicationOptions.js","sourceRoot":"","sources":["../../../src/app/applicationOptions.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export interface AuthenticationOptions {
6
- enableSSO: boolean;
7
- }
@@ -1,7 +0,0 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Microsoft Corporation. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- //# sourceMappingURL=authenticationOptions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authenticationOptions.js","sourceRoot":"","sources":["../../../../src/app/oauth/authenticationOptions.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
@@ -1,11 +0,0 @@
1
- import { UserTokenClient } from '../../oauth/userTokenClient';
2
- import { TurnContext } from '../../turnContext';
3
- import { TurnState } from '../turnState';
4
- import { Storage } from '../../storage';
5
- export declare class WebChatOAuthFlowAppStyle {
6
- userTokenClient?: UserTokenClient;
7
- storage: Storage;
8
- constructor(storage: Storage);
9
- getOAuthToken(context: TurnContext, state: TurnState): Promise<string>;
10
- signOut(context: TurnContext, state: TurnState): Promise<void>;
11
- }