@microsoft/agents-hosting 1.1.0-alpha.5 → 1.1.0-alpha.58

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 (139) hide show
  1. package/dist/package.json +10 -6
  2. package/dist/src/activityWireCompat.js +8 -3
  3. package/dist/src/activityWireCompat.js.map +1 -1
  4. package/dist/src/agent-client/agentClient.js +7 -3
  5. package/dist/src/agent-client/agentClient.js.map +1 -1
  6. package/dist/src/agent-client/agentResponseHandler.js +6 -2
  7. package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
  8. package/dist/src/app/agentApplication.d.ts +26 -11
  9. package/dist/src/app/agentApplication.js +93 -82
  10. package/dist/src/app/agentApplication.js.map +1 -1
  11. package/dist/src/app/agentApplicationBuilder.d.ts +2 -2
  12. package/dist/src/app/agentApplicationBuilder.js.map +1 -1
  13. package/dist/src/app/agentApplicationOptions.d.ts +9 -2
  14. package/dist/src/app/appRoute.d.ts +7 -0
  15. package/dist/src/app/{authorization.d.ts → auth/authorization.d.ts} +33 -139
  16. package/dist/src/app/auth/authorization.js +188 -0
  17. package/dist/src/app/auth/authorization.js.map +1 -0
  18. package/dist/src/app/auth/authorizationManager.d.ts +71 -0
  19. package/dist/src/app/auth/authorizationManager.js +170 -0
  20. package/dist/src/app/auth/authorizationManager.js.map +1 -0
  21. package/dist/src/app/auth/handlerStorage.d.ts +36 -0
  22. package/dist/src/app/auth/handlerStorage.js +62 -0
  23. package/dist/src/app/auth/handlerStorage.js.map +1 -0
  24. package/dist/src/app/auth/handlers/agenticAuthorization.d.ts +97 -0
  25. package/dist/src/app/auth/handlers/agenticAuthorization.js +145 -0
  26. package/dist/src/app/auth/handlers/agenticAuthorization.js.map +1 -0
  27. package/dist/src/app/auth/handlers/azureBotAuthorization.d.ts +222 -0
  28. package/dist/src/app/auth/handlers/azureBotAuthorization.js +428 -0
  29. package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -0
  30. package/dist/src/app/auth/handlers/index.d.ts +2 -0
  31. package/dist/src/app/auth/handlers/index.js +19 -0
  32. package/dist/src/app/auth/handlers/index.js.map +1 -0
  33. package/dist/src/app/auth/index.d.ts +2 -0
  34. package/dist/src/app/auth/index.js +19 -0
  35. package/dist/src/app/auth/index.js.map +1 -0
  36. package/dist/src/app/auth/types.d.ts +104 -0
  37. package/dist/src/app/auth/types.js +24 -0
  38. package/dist/src/app/auth/types.js.map +1 -0
  39. package/dist/src/app/index.d.ts +2 -3
  40. package/dist/src/app/index.js +2 -3
  41. package/dist/src/app/index.js.map +1 -1
  42. package/dist/src/app/routeList.d.ts +1 -1
  43. package/dist/src/app/routeList.js +22 -5
  44. package/dist/src/app/routeList.js.map +1 -1
  45. package/dist/src/app/streaming/streamingResponse.js +2 -1
  46. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  47. package/dist/src/auth/MemoryCache.d.ts +16 -0
  48. package/dist/src/auth/MemoryCache.js +58 -0
  49. package/dist/src/auth/MemoryCache.js.map +1 -0
  50. package/dist/src/auth/authConfiguration.d.ts +44 -2
  51. package/dist/src/auth/authConfiguration.js +218 -53
  52. package/dist/src/auth/authConfiguration.js.map +1 -1
  53. package/dist/src/auth/authConstants.d.ts +11 -0
  54. package/dist/src/auth/authConstants.js +15 -0
  55. package/dist/src/auth/authConstants.js.map +1 -0
  56. package/dist/src/auth/authProvider.d.ts +23 -0
  57. package/dist/src/auth/connections.d.ts +40 -0
  58. package/dist/src/auth/connections.js +7 -0
  59. package/dist/src/auth/connections.js.map +1 -0
  60. package/dist/src/auth/index.d.ts +2 -0
  61. package/dist/src/auth/index.js +2 -0
  62. package/dist/src/auth/index.js.map +1 -1
  63. package/dist/src/auth/jwt-middleware.js +31 -18
  64. package/dist/src/auth/jwt-middleware.js.map +1 -1
  65. package/dist/src/auth/msalConnectionManager.d.ts +63 -0
  66. package/dist/src/auth/msalConnectionManager.js +124 -0
  67. package/dist/src/auth/msalConnectionManager.js.map +1 -0
  68. package/dist/src/auth/msalTokenProvider.d.ts +31 -0
  69. package/dist/src/auth/msalTokenProvider.js +167 -16
  70. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  71. package/dist/src/baseAdapter.d.ts +10 -25
  72. package/dist/src/baseAdapter.js +2 -15
  73. package/dist/src/baseAdapter.js.map +1 -1
  74. package/dist/src/cloudAdapter.d.ts +40 -23
  75. package/dist/src/cloudAdapter.js +132 -56
  76. package/dist/src/cloudAdapter.js.map +1 -1
  77. package/dist/src/connector-client/connectorClient.d.ts +9 -0
  78. package/dist/src/connector-client/connectorClient.js +39 -9
  79. package/dist/src/connector-client/connectorClient.js.map +1 -1
  80. package/dist/src/index.d.ts +0 -1
  81. package/dist/src/index.js +0 -1
  82. package/dist/src/index.js.map +1 -1
  83. package/dist/src/oauth/index.d.ts +0 -1
  84. package/dist/src/oauth/index.js +0 -1
  85. package/dist/src/oauth/index.js.map +1 -1
  86. package/dist/src/oauth/userTokenClient.d.ts +30 -13
  87. package/dist/src/oauth/userTokenClient.js +64 -26
  88. package/dist/src/oauth/userTokenClient.js.map +1 -1
  89. package/dist/src/oauth/userTokenClient.types.d.ts +19 -6
  90. package/dist/src/turnContext.d.ts +7 -1
  91. package/dist/src/turnContext.js +11 -4
  92. package/dist/src/turnContext.js.map +1 -1
  93. package/package.json +10 -6
  94. package/src/activityWireCompat.ts +8 -3
  95. package/src/agent-client/agentClient.ts +9 -3
  96. package/src/agent-client/agentResponseHandler.ts +5 -2
  97. package/src/app/agentApplication.ts +97 -75
  98. package/src/app/agentApplicationBuilder.ts +2 -2
  99. package/src/app/agentApplicationOptions.ts +10 -2
  100. package/src/app/appRoute.ts +8 -0
  101. package/src/app/auth/authorization.ts +252 -0
  102. package/src/app/auth/authorizationManager.ts +213 -0
  103. package/src/app/auth/handlerStorage.ts +61 -0
  104. package/src/app/auth/handlers/agenticAuthorization.ts +194 -0
  105. package/src/app/auth/handlers/azureBotAuthorization.ts +599 -0
  106. package/src/app/auth/handlers/index.ts +2 -0
  107. package/src/app/auth/index.ts +2 -0
  108. package/src/app/auth/types.ts +111 -0
  109. package/src/app/index.ts +2 -3
  110. package/src/app/routeList.ts +24 -5
  111. package/src/app/streaming/streamingResponse.ts +2 -1
  112. package/src/auth/MemoryCache.ts +59 -0
  113. package/src/auth/authConfiguration.ts +258 -52
  114. package/src/auth/authConstants.ts +11 -0
  115. package/src/auth/authProvider.ts +31 -0
  116. package/src/auth/connections.ts +46 -0
  117. package/src/auth/index.ts +2 -0
  118. package/src/auth/jwt-middleware.ts +38 -21
  119. package/src/auth/msalConnectionManager.ts +150 -0
  120. package/src/auth/msalTokenProvider.ts +209 -9
  121. package/src/baseAdapter.ts +10 -29
  122. package/src/cloudAdapter.ts +192 -67
  123. package/src/connector-client/connectorClient.ts +49 -10
  124. package/src/index.ts +0 -1
  125. package/src/oauth/index.ts +0 -1
  126. package/src/oauth/userTokenClient.ts +79 -23
  127. package/src/oauth/userTokenClient.types.ts +20 -8
  128. package/src/turnContext.ts +16 -5
  129. package/dist/src/app/authorization.js +0 -387
  130. package/dist/src/app/authorization.js.map +0 -1
  131. package/dist/src/claimsIdentity.d.ts +0 -35
  132. package/dist/src/claimsIdentity.js +0 -43
  133. package/dist/src/claimsIdentity.js.map +0 -1
  134. package/dist/src/oauth/oAuthFlow.d.ts +0 -119
  135. package/dist/src/oauth/oAuthFlow.js +0 -316
  136. package/dist/src/oauth/oAuthFlow.js.map +0 -1
  137. package/src/app/authorization.ts +0 -432
  138. package/src/claimsIdentity.ts +0 -47
  139. package/src/oauth/oAuthFlow.ts +0 -378
@@ -9,11 +9,12 @@ import { TurnContext } from './turnContext'
9
9
  import { Response } from 'express'
10
10
  import { Request } from './auth/request'
11
11
  import { ConnectorClient } from './connector-client/connectorClient'
12
- import { AuthConfiguration, loadAuthConfigFromEnv } from './auth/authConfiguration'
12
+ import { AuthConfiguration, getAuthConfigWithDefaults } from './auth/authConfiguration'
13
13
  import { AuthProvider } from './auth/authProvider'
14
- import { Activity, ActivityEventNames, ActivityTypes, Channels, ConversationReference, DeliveryModes, ConversationParameters } from '@microsoft/agents-activity'
14
+ import { ApxProductionScope } from './auth/authConstants'
15
+ import { MsalConnectionManager } from './auth/msalConnectionManager'
16
+ import { Activity, ActivityEventNames, ActivityTypes, Channels, ConversationReference, DeliveryModes, ConversationParameters, RoleTypes } from '@microsoft/agents-activity'
15
17
  import { ResourceResponse } from './connector-client/resourceResponse'
16
- import { MsalTokenProvider } from './auth/msalTokenProvider'
17
18
  import * as uuid from 'uuid'
18
19
  import { debug } from '@microsoft/agents-activity/logger'
19
20
  import { StatusCodes } from './statusCodes'
@@ -23,6 +24,7 @@ import { AttachmentData } from './connector-client/attachmentData'
23
24
  import { normalizeIncomingActivity } from './activityWireCompat'
24
25
  import { UserTokenClient } from './oauth'
25
26
  import { HeaderPropagation, HeaderPropagationCollection, HeaderPropagationDefinition } from './headerPropagation'
27
+ import { JwtPayload } from 'jsonwebtoken'
26
28
 
27
29
  const logger = debug('agents:cloud-adapter')
28
30
 
@@ -30,27 +32,26 @@ const logger = debug('agents:cloud-adapter')
30
32
  * Adapter for handling agent interactions with various channels through cloud-based services.
31
33
  *
32
34
  * @remarks
33
- * CloudAdapter processes incoming HTTP requests from Microsoft Bot Framework channels,
35
+ * CloudAdapter processes incoming HTTP requests from Azure Bot Service channels,
34
36
  * authenticates them, and generates outgoing responses. It manages the communication
35
37
  * flow between agents and users across different channels, handling activities, attachments,
36
38
  * and conversation continuations.
37
39
  */
38
40
  export class CloudAdapter extends BaseAdapter {
39
41
  /**
40
- * Client for connecting to the Bot Framework Connector service
42
+ * Client for connecting to the Azure Bot Service
41
43
  */
42
- public connectorClient!: ConnectorClient
43
- authConfig: AuthConfiguration
44
+ connectionManager: MsalConnectionManager
45
+
44
46
  /**
45
47
  * Creates an instance of CloudAdapter.
46
48
  * @param authConfig - The authentication configuration for securing communications
47
- * @param authProvider - Optional custom authentication provider. If not specified, a default MsalTokenProvider will be used
49
+ * @param authProvider - No longer used
48
50
  */
49
51
  constructor (authConfig?: AuthConfiguration, authProvider?: AuthProvider, userTokenClient?: UserTokenClient) {
50
52
  super()
51
- this.authConfig = authConfig ?? loadAuthConfigFromEnv()
52
- this.authProvider = authProvider ?? new MsalTokenProvider()
53
- this.userTokenClient = userTokenClient ?? new UserTokenClient(this.authConfig.clientId)
53
+ authConfig = getAuthConfigWithDefaults(authConfig)
54
+ this.connectionManager = new MsalConnectionManager(undefined, undefined, authConfig)
54
55
  }
55
56
 
56
57
  /**
@@ -92,17 +93,84 @@ export class CloudAdapter extends BaseAdapter {
92
93
  protected async createConnectorClient (
93
94
  serviceUrl: string,
94
95
  scope: string,
96
+ audience: string,
95
97
  headers?: HeaderPropagationCollection
96
98
  ): Promise<ConnectorClient> {
97
- return ConnectorClient.createClientWithAuth(
99
+ // get the correct token provider
100
+ const tokenProvider = this.connectionManager.getTokenProvider(audience, serviceUrl)
101
+
102
+ const token = await tokenProvider.getAccessToken(scope)
103
+ return ConnectorClient.createClientWithToken(
98
104
  serviceUrl,
99
- this.authConfig,
100
- this.authProvider,
101
- scope,
105
+ token,
102
106
  headers
103
107
  )
104
108
  }
105
109
 
110
+ protected async createConnectorClientWithIdentity (
111
+ identity: JwtPayload,
112
+ activity: Activity,
113
+ scope: string,
114
+ headers?: HeaderPropagationCollection) {
115
+ let audience
116
+ if (Array.isArray(identity.aud)) {
117
+ audience = identity.aud[0]
118
+ } else {
119
+ audience = identity.aud
120
+ }
121
+
122
+ if (!audience) {
123
+ // anonymous
124
+ return ConnectorClient.createClientWithToken(
125
+ activity.serviceUrl!,
126
+ null!,
127
+ headers
128
+ )
129
+ }
130
+
131
+ let connectorClient
132
+ const tokenProvider = this.connectionManager.getTokenProvider(audience!, activity.serviceUrl ?? '')
133
+ if (activity.isAgenticRequest()) {
134
+ logger.debug('Activity is from an agentic source, using special scope', activity.recipient)
135
+
136
+ if (activity.recipient?.role === RoleTypes.AgenticIdentity && activity.getAgenticInstanceId()) {
137
+ // get agentic instance token
138
+ const token = await tokenProvider.getAgenticInstanceToken(activity.getAgenticInstanceId() ?? '')
139
+ connectorClient = ConnectorClient.createClientWithToken(
140
+ activity.serviceUrl!,
141
+ token,
142
+ headers
143
+ )
144
+ } else if (activity.recipient?.role === RoleTypes.AgenticUser && activity.getAgenticInstanceId() && activity.getAgenticUser()) {
145
+ const scope = tokenProvider.connectionSettings?.scope ?? ApxProductionScope
146
+ const token = await tokenProvider.getAgenticUserToken(activity.getAgenticInstanceId() ?? '', activity.getAgenticUser() ?? '', [scope])
147
+
148
+ connectorClient = ConnectorClient.createClientWithToken(
149
+ activity.serviceUrl!,
150
+ token,
151
+ headers
152
+ )
153
+ } else {
154
+ throw new Error('Could not create connector client for agentic user')
155
+ }
156
+ } else {
157
+ const token = await tokenProvider.getAccessToken(scope)
158
+ connectorClient = ConnectorClient.createClientWithToken(
159
+ activity.serviceUrl!,
160
+ token,
161
+ headers
162
+ )
163
+ }
164
+
165
+ return connectorClient
166
+ }
167
+
168
+ static createIdentity (appId: string) : JwtPayload {
169
+ return {
170
+ aud: appId
171
+ } as JwtPayload
172
+ }
173
+
106
174
  /**
107
175
  * Sets the connector client on the turn context.
108
176
  *
@@ -110,24 +178,60 @@ export class CloudAdapter extends BaseAdapter {
110
178
  * @protected
111
179
  */
112
180
  protected setConnectorClient (
113
- context: TurnContext
181
+ context: TurnContext,
182
+ connectorClient?: ConnectorClient
183
+ ) {
184
+ context.turnState.set(this.ConnectorClientKey, connectorClient)
185
+ }
186
+
187
+ /**
188
+ * Creates a user token client for a specific service URL and scope.
189
+ *
190
+ * @param serviceUrl - The URL of the service to connect to
191
+ * @param scope - The authentication scope to use
192
+ * @param headers - Optional headers to propagate in the request
193
+ * @returns A promise that resolves to a ConnectorClient instance
194
+ * @protected
195
+ */
196
+ protected async createUserTokenClient (
197
+ tokenServiceEndpoint: string = 'https://api.botframework.com',
198
+ scope: string = 'https://api.botframework.com',
199
+ audience: string = 'https://api.botframework.com',
200
+ headers?: HeaderPropagationCollection
201
+ ): Promise<UserTokenClient> {
202
+ // get the correct token provider
203
+ const tokenProvider = this.connectionManager.getTokenProvider(audience, tokenServiceEndpoint)
204
+
205
+ return UserTokenClient.createClientWithScope(
206
+ tokenServiceEndpoint,
207
+ tokenProvider,
208
+ scope,
209
+ headers
210
+ )
211
+ }
212
+
213
+ /**
214
+ * Sets the user token client on the turn context.
215
+ *
216
+ * @param context - The current turn context
217
+ * @protected
218
+ */
219
+ protected setUserTokenClient (
220
+ context: TurnContext,
221
+ userTokenClient?: UserTokenClient
114
222
  ) {
115
- context.turnState.set('connectorClient', this.connectorClient)
223
+ context.turnState.set(this.UserTokenClientKey, userTokenClient)
116
224
  }
117
225
 
118
226
  /**
227
+ * @deprecated This function will not be supported in future versions. Create TurnContext directly.
119
228
  * Creates a TurnContext for the given activity and logic.
120
229
  * @param activity - The activity to process.
121
230
  * @param logic - The logic to execute.
122
231
  * @returns The created TurnContext.
123
232
  */
124
- createTurnContext (activity: Activity, logic: AgentHandler): TurnContext {
125
- return new TurnContext(this, activity)
126
- }
127
-
128
- async createTurnContextWithScope (activity: Activity, logic: AgentHandler, scope: string): Promise<TurnContext> {
129
- this.connectorClient = await ConnectorClient.createClientWithAuth(activity.serviceUrl!, this.authConfig!, this.authProvider, scope)
130
- return new TurnContext(this, activity)
233
+ createTurnContext (activity: Activity, logic: AgentHandler, identity?: JwtPayload): TurnContext {
234
+ return new TurnContext(this, activity, identity)
131
235
  }
132
236
 
133
237
  /**
@@ -165,12 +269,10 @@ export class CloudAdapter extends BaseAdapter {
165
269
  throw new Error('Invalid activity object')
166
270
  }
167
271
 
168
- this.connectorClient = await this.createConnectorClient(activity.serviceUrl, 'https://api.botframework.com')
169
-
170
272
  if (activity.replyToId) {
171
- response = await this.connectorClient.replyToActivity(activity.conversation.id, activity.replyToId, activity)
273
+ response = await context.turnState.get(this.ConnectorClientKey).replyToActivity(activity.conversation.id, activity.replyToId, activity)
172
274
  } else {
173
- response = await this.connectorClient.sendToConversation(activity.conversation.id, activity)
275
+ response = await context.turnState.get(this.ConnectorClientKey).sendToConversation(activity.conversation.id, activity)
174
276
  }
175
277
  }
176
278
 
@@ -184,18 +286,6 @@ export class CloudAdapter extends BaseAdapter {
184
286
  return responses
185
287
  }
186
288
 
187
- /**
188
- * Replies to an activity.
189
- * @param activity - The activity to reply to.
190
- * @returns A promise representing the ResourceResponse for the sent activity.
191
- */
192
- async replyToActivity (activity: Activity): Promise<ResourceResponse> {
193
- if (!activity.serviceUrl || (activity.conversation == null) || !activity.conversation.id || !activity.id) {
194
- throw new Error('Invalid activity object')
195
- }
196
- return await this.connectorClient.replyToActivity(activity.conversation.id, activity.id, activity)
197
- }
198
-
199
289
  /**
200
290
  * Processes an incoming request and sends the response.
201
291
  * @param request - The incoming request.
@@ -236,14 +326,18 @@ export class CloudAdapter extends BaseAdapter {
236
326
  }
237
327
 
238
328
  logger.debug('Received activity: ', activity)
239
- const context = this.createTurnContext(activity, logic)
240
- const scope = request.user?.azp ?? request.user?.appid ?? 'https://api.botframework.com'
241
329
 
330
+ const context = new TurnContext(this, activity, request.user!)
331
+ const scope = request.user?.azp ?? request.user?.appid ?? 'https://api.botframework.com'
242
332
  // if Delivery Mode == ExpectReplies, we don't need a connector client.
243
333
  if (this.resolveIfConnectorClientIsNeeded(activity)) {
244
- logger.debug('Creating connector client with scope: ', scope)
245
- this.connectorClient = await this.createConnectorClient(activity.serviceUrl!, scope, headers)
246
- this.setConnectorClient(context)
334
+ const connectorClient = await this.createConnectorClientWithIdentity(request.user!, activity, scope, headers)
335
+ this.setConnectorClient(context, connectorClient)
336
+ }
337
+
338
+ if (!activity.isAgenticRequest()) {
339
+ const userTokenClient = await this.createUserTokenClient()
340
+ this.setUserTokenClient(context, userTokenClient)
247
341
  }
248
342
 
249
343
  if (
@@ -259,7 +353,6 @@ export class CloudAdapter extends BaseAdapter {
259
353
 
260
354
  await this.runMiddleware(context, logic)
261
355
  const invokeResponse = this.processTurnResults(context)
262
-
263
356
  return end(invokeResponse?.status ?? StatusCodes.OK, invokeResponse?.body)
264
357
  }
265
358
 
@@ -301,7 +394,7 @@ export class CloudAdapter extends BaseAdapter {
301
394
  throw new Error('Invalid activity object')
302
395
  }
303
396
 
304
- const response = await this.connectorClient.updateActivity(
397
+ const response = await context.turnState.get(this.ConnectorClientKey).updateActivity(
305
398
  activity.conversation.id,
306
399
  activity.id,
307
400
  activity
@@ -325,7 +418,7 @@ export class CloudAdapter extends BaseAdapter {
325
418
  throw new Error('Invalid conversation reference object')
326
419
  }
327
420
 
328
- await this.connectorClient.deleteActivity(reference.conversation.id, reference.activityId)
421
+ await context.turnState.get(this.ConnectorClientKey).deleteActivity(reference.conversation.id, reference.activityId)
329
422
  }
330
423
 
331
424
  /**
@@ -334,25 +427,39 @@ export class CloudAdapter extends BaseAdapter {
334
427
  * @param logic - The logic to execute.
335
428
  * @returns A promise representing the completion of the continue operation.
336
429
  */
337
- async continueConversation (reference: ConversationReference, logic: (revocableContext: TurnContext) => Promise<void>, isResponse: Boolean = false): Promise<void> {
430
+ async continueConversation (
431
+ botAppIdOrIdentity: string | JwtPayload,
432
+ reference: ConversationReference,
433
+ logic: (revocableContext: TurnContext) => Promise<void>,
434
+ isResponse: Boolean = false): Promise<void> {
338
435
  if (!reference || !reference.serviceUrl || (reference.conversation == null) || !reference.conversation.id) {
339
436
  throw new Error('Invalid conversation reference object')
340
437
  }
341
438
 
342
- let context
343
- if (isResponse) {
344
- context = await this.createTurnContextWithScope(Activity.getContinuationActivity(reference), logic, 'https://api.botframework.com')
345
- } else {
346
- context = this.createTurnContext(Activity.getContinuationActivity(reference), logic)
347
- }
439
+ const botAppId = typeof botAppIdOrIdentity === 'string' ? botAppIdOrIdentity : botAppIdOrIdentity.aud as string
440
+
441
+ const identity =
442
+ typeof botAppIdOrIdentity !== 'string'
443
+ ? botAppIdOrIdentity
444
+ : CloudAdapter.createIdentity(botAppId)
445
+
446
+ const continuationActivity = Activity.getContinuationActivity(reference)
447
+ const context = new TurnContext(this, Activity.getContinuationActivity(reference), identity)
448
+ const scope = identity.azp ?? identity.appid ?? 'https://api.botframework.com'
449
+ const connectorClient = await this.createConnectorClientWithIdentity(identity, continuationActivity, scope)
450
+ this.setConnectorClient(context, connectorClient)
451
+
452
+ const userTokenClient = await this.createUserTokenClient()
453
+ this.setUserTokenClient(context, userTokenClient)
454
+
348
455
  await this.runMiddleware(context, logic)
349
456
  }
350
457
 
351
458
  /**
352
- * Processes the turn results and returns an InvokeResponse if applicable.
353
- * @param context - The TurnContext for the current turn.
354
- * @returns The InvokeResponse if applicable, otherwise undefined.
355
- */
459
+ * Processes the turn results and returns an InvokeResponse if applicable.
460
+ * @param context - The TurnContext for the current turn.
461
+ * @returns The InvokeResponse if applicable, otherwise undefined.
462
+ */
356
463
  protected processTurnResults (context: TurnContext): InvokeResponse | undefined {
357
464
  logger.info('<--Sending back turn results')
358
465
  // Handle ExpectedReplies scenarios where all activities have been buffered and sent back at once in an invoke response.
@@ -437,7 +544,8 @@ export class CloudAdapter extends BaseAdapter {
437
544
  if (!conversationParameters) throw new TypeError('`conversationParameters` must be defined')
438
545
  if (!logic) throw new TypeError('`logic` must be defined')
439
546
 
440
- const restClient = await this.createConnectorClient(serviceUrl, audience)
547
+ const restClient = await this.createConnectorClient(serviceUrl, audience, audience)
548
+ const userTokenClient = await this.createUserTokenClient()
441
549
  const createConversationResult = await restClient.createConversation(conversationParameters)
442
550
  const createActivity = this.createCreateActivity(
443
551
  createConversationResult.id,
@@ -445,17 +553,24 @@ export class CloudAdapter extends BaseAdapter {
445
553
  serviceUrl,
446
554
  conversationParameters
447
555
  )
448
- const context = new TurnContext(this, createActivity)
556
+ const context = new TurnContext(this, createActivity, CloudAdapter.createIdentity(agentAppId))
557
+ this.setConnectorClient(context, restClient)
558
+ this.setUserTokenClient(context, userTokenClient)
449
559
  await this.runMiddleware(context, logic)
450
560
  }
451
561
 
452
562
  /**
563
+ * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
453
564
  * Uploads an attachment.
454
565
  * @param conversationId - The conversation ID.
455
566
  * @param attachmentData - The attachment data.
456
567
  * @returns A promise representing the ResourceResponse for the uploaded attachment.
457
568
  */
458
- async uploadAttachment (conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
569
+ async uploadAttachment (context: TurnContext, conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
570
+ if (context === undefined) {
571
+ throw new Error('context is required')
572
+ }
573
+
459
574
  if (conversationId === undefined) {
460
575
  throw new Error('conversationId is required')
461
576
  }
@@ -464,29 +579,39 @@ export class CloudAdapter extends BaseAdapter {
464
579
  throw new Error('attachmentData is required')
465
580
  }
466
581
 
467
- return await this.connectorClient.uploadAttachment(conversationId, attachmentData)
582
+ return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).uploadAttachment(conversationId, attachmentData)
468
583
  }
469
584
 
470
585
  /**
586
+ * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
471
587
  * Gets attachment information.
472
588
  * @param attachmentId - The attachment ID.
473
589
  * @returns A promise representing the AttachmentInfo for the requested attachment.
474
590
  */
475
- async getAttachmentInfo (attachmentId: string): Promise<AttachmentInfo> {
591
+ async getAttachmentInfo (context: TurnContext, attachmentId: string): Promise<AttachmentInfo> {
592
+ if (context === undefined) {
593
+ throw new Error('context is required')
594
+ }
595
+
476
596
  if (attachmentId === undefined) {
477
597
  throw new Error('attachmentId is required')
478
598
  }
479
599
 
480
- return await this.connectorClient.getAttachmentInfo(attachmentId)
600
+ return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachmentInfo(attachmentId)
481
601
  }
482
602
 
483
603
  /**
604
+ * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
484
605
  * Gets an attachment.
485
606
  * @param attachmentId - The attachment ID.
486
607
  * @param viewId - The view ID.
487
608
  * @returns A promise representing the NodeJS.ReadableStream for the requested attachment.
488
609
  */
489
- async getAttachment (attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
610
+ async getAttachment (context: TurnContext, attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
611
+ if (context === undefined) {
612
+ throw new Error('context is required')
613
+ }
614
+
490
615
  if (attachmentId === undefined) {
491
616
  throw new Error('attachmentId is required')
492
617
  }
@@ -495,6 +620,6 @@ export class CloudAdapter extends BaseAdapter {
495
620
  throw new Error('viewId is required')
496
621
  }
497
622
 
498
- return await this.connectorClient.getAttachment(attachmentId, viewId)
623
+ return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachment(attachmentId, viewId)
499
624
  }
500
625
  }
@@ -3,7 +3,7 @@ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
3
3
  import { AuthConfiguration } from '../auth/authConfiguration'
4
4
  import { AuthProvider } from '../auth/authProvider'
5
5
  import { debug } from '@microsoft/agents-activity/logger'
6
- import { Activity, ChannelAccount, ConversationParameters } from '@microsoft/agents-activity'
6
+ import { Activity, ChannelAccount, ConversationParameters, RoleTypes, Channels } from '@microsoft/agents-activity'
7
7
  import { ConversationsResult } from './conversationsResult'
8
8
  import { ConversationResourceResponse } from './conversationResourceResponse'
9
9
  import { ResourceResponse } from './resourceResponse'
@@ -91,9 +91,28 @@ export class ConnectorClient {
91
91
  scope: string,
92
92
  headers?: HeaderPropagationCollection
93
93
  ): Promise<ConnectorClient> {
94
+ const token = await authProvider.getAccessToken(authConfig, scope)
95
+ return this.createClientWithToken(baseURL, token, headers)
96
+ }
97
+
98
+ /**
99
+ * Creates a new instance of ConnectorClient with token.
100
+ * @param baseURL - The base URL for the API.
101
+ * @param token - The authentication token.
102
+ * @param headers - Optional headers to propagate in the request.
103
+ * @returns A new instance of ConnectorClient.
104
+ */
105
+ static createClientWithToken (
106
+ baseURL: string,
107
+ token: string,
108
+ headers?: HeaderPropagationCollection
109
+ ): ConnectorClient {
94
110
  const headerPropagation = headers ?? new HeaderPropagation({ 'User-Agent': '' })
95
111
  headerPropagation.concat({ 'User-Agent': getProductInfo() })
96
- headerPropagation.override({ Accept: 'application/json' })
112
+ headerPropagation.override({
113
+ Accept: 'application/json',
114
+ 'Content-Type': 'application/json', // Required by transformRequest
115
+ })
97
116
 
98
117
  const axiosInstance = axios.create({
99
118
  baseURL,
@@ -104,10 +123,10 @@ export class ConnectorClient {
104
123
  }]
105
124
  })
106
125
 
107
- const token = await authProvider.getAccessToken(authConfig, scope)
108
- if (token.length > 1) {
126
+ if (token && token.length > 1) {
109
127
  axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`
110
128
  }
129
+
111
130
  return new ConnectorClient(axiosInstance)
112
131
  }
113
132
 
@@ -147,14 +166,14 @@ export class ConnectorClient {
147
166
  * @returns The conversation resource response.
148
167
  */
149
168
  public async createConversation (body: ConversationParameters): Promise<ConversationResourceResponse> {
150
- // const payload = normalizeOutgoingConvoParams(body)
169
+ const payload = normalizeOutgoingActivity(body)
151
170
  const config: AxiosRequestConfig = {
152
171
  method: 'post',
153
172
  url: '/v3/conversations',
154
173
  headers: {
155
174
  'Content-Type': 'application/json'
156
175
  },
157
- data: body
176
+ data: payload
158
177
  }
159
178
  const response: AxiosResponse = await this._axiosInstance(config)
160
179
  return response.data
@@ -176,19 +195,36 @@ export class ConnectorClient {
176
195
  if (!conversationId || !activityId) {
177
196
  throw new Error('conversationId and activityId are required')
178
197
  }
198
+
199
+ const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
200
+
179
201
  const config: AxiosRequestConfig = {
180
202
  method: 'post',
181
- url: `v3/conversations/${conversationId}/activities/${encodeURIComponent(activityId)}`,
203
+ url: `v3/conversations/${trimmedConversationId}/activities/${encodeURIComponent(activityId)}`,
182
204
  headers: {
183
205
  'Content-Type': 'application/json'
184
206
  },
185
- data: body
207
+ data: normalizeOutgoingActivity(body)
186
208
  }
187
209
  const response = await this._axiosInstance(config)
188
210
  logger.info('Reply to conversation/activity: ', response.data.id!, activityId)
189
211
  return response.data
190
212
  }
191
213
 
214
+ private conditionallyTruncateConversationId (conversationId: string, activity: Activity): string {
215
+ if (
216
+ (activity.channelIdChannel === Channels.Msteams || activity.channelIdChannel === Channels.Agents) &&
217
+ (activity.from?.role === RoleTypes.AgenticIdentity || activity.from?.role === RoleTypes.AgenticUser)) {
218
+ let maxLength = 150
219
+ if (process.env.MAX_APX_CONVERSATION_ID_LENGTH && !isNaN(parseInt(process.env.MAX_APX_CONVERSATION_ID_LENGTH, 10))) {
220
+ maxLength = parseInt(process.env.MAX_APX_CONVERSATION_ID_LENGTH, 10)
221
+ }
222
+ return conversationId.length > maxLength ? conversationId.substring(0, maxLength) : conversationId
223
+ } else {
224
+ return conversationId
225
+ }
226
+ }
227
+
192
228
  /**
193
229
  * Sends an activity to a conversation.
194
230
  * @param conversationId - The ID of the conversation.
@@ -203,13 +239,16 @@ export class ConnectorClient {
203
239
  if (!conversationId) {
204
240
  throw new Error('conversationId is required')
205
241
  }
242
+
243
+ const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
244
+
206
245
  const config: AxiosRequestConfig = {
207
246
  method: 'post',
208
- url: `v3/conversations/${conversationId}/activities`,
247
+ url: `v3/conversations/${trimmedConversationId}/activities`,
209
248
  headers: {
210
249
  'Content-Type': 'application/json'
211
250
  },
212
- data: body
251
+ data: normalizeOutgoingActivity(body)
213
252
  }
214
253
  const response = await this._axiosInstance(config)
215
254
  return response.data
package/src/index.ts CHANGED
@@ -19,7 +19,6 @@ export * from './activityHandler'
19
19
  export * from './baseAdapter'
20
20
  export * from './cloudAdapter'
21
21
  export * from './middlewareSet'
22
- export * from './claimsIdentity'
23
22
  export * from './messageFactory'
24
23
  export * from './statusCodes'
25
24
  export * from './turnContext'
@@ -1,3 +1,2 @@
1
1
  export * from './userTokenClient'
2
- export * from './oAuthFlow'
3
2
  export * from './userTokenClient.types'