@microsoft/agents-hosting 1.1.0-alpha.2 → 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 (150) 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 +94 -86
  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/attachmentDownloader.d.ts +13 -3
  16. package/dist/src/app/attachmentDownloader.js +16 -3
  17. package/dist/src/app/attachmentDownloader.js.map +1 -1
  18. package/dist/src/app/{authorization.d.ts → auth/authorization.d.ts} +33 -139
  19. package/dist/src/app/auth/authorization.js +188 -0
  20. package/dist/src/app/auth/authorization.js.map +1 -0
  21. package/dist/src/app/auth/authorizationManager.d.ts +71 -0
  22. package/dist/src/app/auth/authorizationManager.js +170 -0
  23. package/dist/src/app/auth/authorizationManager.js.map +1 -0
  24. package/dist/src/app/auth/handlerStorage.d.ts +36 -0
  25. package/dist/src/app/auth/handlerStorage.js +62 -0
  26. package/dist/src/app/auth/handlerStorage.js.map +1 -0
  27. package/dist/src/app/auth/handlers/agenticAuthorization.d.ts +97 -0
  28. package/dist/src/app/auth/handlers/agenticAuthorization.js +145 -0
  29. package/dist/src/app/auth/handlers/agenticAuthorization.js.map +1 -0
  30. package/dist/src/app/auth/handlers/azureBotAuthorization.d.ts +222 -0
  31. package/dist/src/app/auth/handlers/azureBotAuthorization.js +428 -0
  32. package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -0
  33. package/dist/src/app/auth/handlers/index.d.ts +2 -0
  34. package/dist/src/app/auth/handlers/index.js +19 -0
  35. package/dist/src/app/auth/handlers/index.js.map +1 -0
  36. package/dist/src/app/auth/index.d.ts +2 -0
  37. package/dist/src/app/auth/index.js +19 -0
  38. package/dist/src/app/auth/index.js.map +1 -0
  39. package/dist/src/app/auth/types.d.ts +104 -0
  40. package/dist/src/app/auth/types.js +24 -0
  41. package/dist/src/app/auth/types.js.map +1 -0
  42. package/dist/src/app/index.d.ts +2 -3
  43. package/dist/src/app/index.js +2 -3
  44. package/dist/src/app/index.js.map +1 -1
  45. package/dist/src/app/inputFileDownloader.d.ts +10 -3
  46. package/dist/src/app/routeList.d.ts +1 -1
  47. package/dist/src/app/routeList.js +22 -5
  48. package/dist/src/app/routeList.js.map +1 -1
  49. package/dist/src/app/streaming/streamingResponse.d.ts +11 -1
  50. package/dist/src/app/streaming/streamingResponse.js +17 -2
  51. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  52. package/dist/src/app/turnState.d.ts +2 -38
  53. package/dist/src/app/turnState.js +1 -46
  54. package/dist/src/app/turnState.js.map +1 -1
  55. package/dist/src/auth/MemoryCache.d.ts +16 -0
  56. package/dist/src/auth/MemoryCache.js +58 -0
  57. package/dist/src/auth/MemoryCache.js.map +1 -0
  58. package/dist/src/auth/authConfiguration.d.ts +44 -2
  59. package/dist/src/auth/authConfiguration.js +218 -53
  60. package/dist/src/auth/authConfiguration.js.map +1 -1
  61. package/dist/src/auth/authConstants.d.ts +11 -0
  62. package/dist/src/auth/authConstants.js +15 -0
  63. package/dist/src/auth/authConstants.js.map +1 -0
  64. package/dist/src/auth/authProvider.d.ts +23 -0
  65. package/dist/src/auth/connections.d.ts +40 -0
  66. package/dist/src/auth/connections.js +7 -0
  67. package/dist/src/auth/connections.js.map +1 -0
  68. package/dist/src/auth/index.d.ts +2 -0
  69. package/dist/src/auth/index.js +2 -0
  70. package/dist/src/auth/index.js.map +1 -1
  71. package/dist/src/auth/jwt-middleware.js +31 -18
  72. package/dist/src/auth/jwt-middleware.js.map +1 -1
  73. package/dist/src/auth/msalConnectionManager.d.ts +63 -0
  74. package/dist/src/auth/msalConnectionManager.js +124 -0
  75. package/dist/src/auth/msalConnectionManager.js.map +1 -0
  76. package/dist/src/auth/msalTokenProvider.d.ts +31 -0
  77. package/dist/src/auth/msalTokenProvider.js +167 -16
  78. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  79. package/dist/src/baseAdapter.d.ts +10 -25
  80. package/dist/src/baseAdapter.js +2 -15
  81. package/dist/src/baseAdapter.js.map +1 -1
  82. package/dist/src/cloudAdapter.d.ts +40 -23
  83. package/dist/src/cloudAdapter.js +132 -56
  84. package/dist/src/cloudAdapter.js.map +1 -1
  85. package/dist/src/connector-client/connectorClient.d.ts +9 -0
  86. package/dist/src/connector-client/connectorClient.js +39 -9
  87. package/dist/src/connector-client/connectorClient.js.map +1 -1
  88. package/dist/src/index.d.ts +0 -1
  89. package/dist/src/index.js +0 -1
  90. package/dist/src/index.js.map +1 -1
  91. package/dist/src/oauth/index.d.ts +0 -1
  92. package/dist/src/oauth/index.js +0 -1
  93. package/dist/src/oauth/index.js.map +1 -1
  94. package/dist/src/oauth/userTokenClient.d.ts +30 -13
  95. package/dist/src/oauth/userTokenClient.js +64 -26
  96. package/dist/src/oauth/userTokenClient.js.map +1 -1
  97. package/dist/src/oauth/userTokenClient.types.d.ts +19 -6
  98. package/dist/src/turnContext.d.ts +7 -1
  99. package/dist/src/turnContext.js +11 -4
  100. package/dist/src/turnContext.js.map +1 -1
  101. package/package.json +10 -6
  102. package/src/activityWireCompat.ts +8 -3
  103. package/src/agent-client/agentClient.ts +9 -3
  104. package/src/agent-client/agentResponseHandler.ts +5 -2
  105. package/src/app/agentApplication.ts +98 -79
  106. package/src/app/agentApplicationBuilder.ts +2 -2
  107. package/src/app/agentApplicationOptions.ts +10 -2
  108. package/src/app/appRoute.ts +8 -0
  109. package/src/app/attachmentDownloader.ts +18 -3
  110. package/src/app/auth/authorization.ts +252 -0
  111. package/src/app/auth/authorizationManager.ts +213 -0
  112. package/src/app/auth/handlerStorage.ts +61 -0
  113. package/src/app/auth/handlers/agenticAuthorization.ts +194 -0
  114. package/src/app/auth/handlers/azureBotAuthorization.ts +599 -0
  115. package/src/app/auth/handlers/index.ts +2 -0
  116. package/src/app/auth/index.ts +2 -0
  117. package/src/app/auth/types.ts +111 -0
  118. package/src/app/index.ts +2 -3
  119. package/src/app/inputFileDownloader.ts +11 -3
  120. package/src/app/routeList.ts +24 -5
  121. package/src/app/streaming/streamingResponse.ts +20 -3
  122. package/src/app/turnState.ts +2 -61
  123. package/src/auth/MemoryCache.ts +59 -0
  124. package/src/auth/authConfiguration.ts +258 -52
  125. package/src/auth/authConstants.ts +11 -0
  126. package/src/auth/authProvider.ts +31 -0
  127. package/src/auth/connections.ts +46 -0
  128. package/src/auth/index.ts +2 -0
  129. package/src/auth/jwt-middleware.ts +38 -21
  130. package/src/auth/msalConnectionManager.ts +150 -0
  131. package/src/auth/msalTokenProvider.ts +209 -9
  132. package/src/baseAdapter.ts +10 -29
  133. package/src/cloudAdapter.ts +192 -67
  134. package/src/connector-client/connectorClient.ts +49 -10
  135. package/src/index.ts +0 -1
  136. package/src/oauth/index.ts +0 -1
  137. package/src/oauth/userTokenClient.ts +79 -23
  138. package/src/oauth/userTokenClient.types.ts +20 -8
  139. package/src/turnContext.ts +16 -5
  140. package/dist/src/app/authorization.js +0 -387
  141. package/dist/src/app/authorization.js.map +0 -1
  142. package/dist/src/claimsIdentity.d.ts +0 -35
  143. package/dist/src/claimsIdentity.js +0 -43
  144. package/dist/src/claimsIdentity.js.map +0 -1
  145. package/dist/src/oauth/oAuthFlow.d.ts +0 -119
  146. package/dist/src/oauth/oAuthFlow.js +0 -316
  147. package/dist/src/oauth/oAuthFlow.js.map +0 -1
  148. package/src/app/authorization.ts +0 -432
  149. package/src/claimsIdentity.ts +0 -47
  150. package/src/oauth/oAuthFlow.ts +0 -378
@@ -12,7 +12,6 @@ import { AdaptiveCardsActions } from './adaptiveCards'
12
12
  import { AgentApplicationOptions } from './agentApplicationOptions'
13
13
  import { ConversationUpdateEvents } from './conversationUpdateEvents'
14
14
  import { AgentExtension } from './extensions'
15
- import { Authorization, SignInState } from './authorization'
16
15
  import { RouteHandler } from './routeHandler'
17
16
  import { RouteSelector } from './routeSelector'
18
17
  import { TurnEvents } from './turnEvents'
@@ -21,6 +20,8 @@ import { RouteRank } from './routeRank'
21
20
  import { RouteList } from './routeList'
22
21
  import { TranscriptLoggerMiddleware } from '../transcript'
23
22
  import { CloudAdapter } from '../cloudAdapter'
23
+ import { Authorization, AuthorizationManager } from './auth'
24
+ import { JwtPayload } from 'jsonwebtoken'
24
25
 
25
26
  const logger = debug('agents:app')
26
27
 
@@ -74,6 +75,7 @@ export class AgentApplication<TState extends TurnState> {
74
75
  protected readonly _beforeTurn: ApplicationEventHandler<TState>[] = []
75
76
  protected readonly _afterTurn: ApplicationEventHandler<TState>[] = []
76
77
  private readonly _adapter?: CloudAdapter
78
+ private readonly _authorizationManager?: AuthorizationManager
77
79
  private readonly _authorization?: Authorization
78
80
  private _typingTimer: NodeJS.Timeout | undefined
79
81
  protected readonly _extensions: AgentExtension<TState>[] = []
@@ -125,7 +127,8 @@ export class AgentApplication<TState extends TurnState> {
125
127
  }
126
128
 
127
129
  if (this._options.authorization) {
128
- this._authorization = new Authorization(this._options.storage!, this._options.authorization, this._adapter?.userTokenClient!)
130
+ this._authorizationManager = new AuthorizationManager(this, this._adapter.connectionManager)
131
+ this._authorization = new Authorization(this._authorizationManager)
129
132
  }
130
133
 
131
134
  if (this._options.longRunningMessages && !this._adapter && !this._options.agentAppId) {
@@ -227,6 +230,7 @@ export class AgentApplication<TState extends TurnState> {
227
230
  * @param isInvokeRoute - Whether this route is for invoke activities. Defaults to false.
228
231
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
229
232
  * @param authHandlers - Array of authentication handler names for this route. Defaults to empty array.
233
+ * @param isAgenticRoute - Whether this route is for agentic requests only. Defaults to false.
230
234
  * @returns The current instance of the application.
231
235
  *
232
236
  * @remarks
@@ -247,8 +251,8 @@ export class AgentApplication<TState extends TurnState> {
247
251
  * ```
248
252
  *
249
253
  */
250
- public addRoute (selector: RouteSelector, handler: RouteHandler<TState>, isInvokeRoute: boolean = false, rank: number = RouteRank.Unspecified, authHandlers: string[] = []): this {
251
- this._routes.addRoute(selector, handler, isInvokeRoute, rank, authHandlers)
254
+ public addRoute (selector: RouteSelector, handler: RouteHandler<TState>, isInvokeRoute: boolean = false, rank: number = RouteRank.Unspecified, authHandlers: string[] = [], isAgenticRoute: boolean = false): this {
255
+ this._routes.addRoute(selector, handler, isInvokeRoute, rank, authHandlers, isAgenticRoute)
252
256
  return this
253
257
  }
254
258
 
@@ -259,6 +263,7 @@ export class AgentApplication<TState extends TurnState> {
259
263
  * @param handler - The handler function that will be called when the specified activity type is received.
260
264
  * @param authHandlers - Array of authentication handler names for this activity. Defaults to empty array.
261
265
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
266
+ * @param isAgenticRoute - Indicates if this handler is for agentic requests only. Defaults to false.
262
267
  * @returns The current instance of the application.
263
268
  *
264
269
  * @remarks
@@ -277,11 +282,12 @@ export class AgentApplication<TState extends TurnState> {
277
282
  type: string | RegExp | RouteSelector | (string | RegExp | RouteSelector)[],
278
283
  handler: (context: TurnContext, state: TState) => Promise<void>,
279
284
  authHandlers: string[] = [],
280
- rank: RouteRank = RouteRank.Unspecified
285
+ rank: RouteRank = RouteRank.Unspecified,
286
+ isAgenticRoute: boolean = false
281
287
  ): this {
282
288
  (Array.isArray(type) ? type : [type]).forEach((t) => {
283
- const selector = this.createActivitySelector(t)
284
- this.addRoute(selector, handler, false, rank, authHandlers)
289
+ const selector = this.createActivitySelector(t, isAgenticRoute)
290
+ this.addRoute(selector, handler, false, rank, authHandlers, isAgenticRoute)
285
291
  })
286
292
  return this
287
293
  }
@@ -293,6 +299,7 @@ export class AgentApplication<TState extends TurnState> {
293
299
  * @param handler - The handler function that will be called when the specified event occurs.
294
300
  * @param authHandlers - Array of authentication handler names for this event. Defaults to empty array.
295
301
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
302
+ * @param isAgenticRoute - Indicates if this handler is for agentic requests only. Defaults to false.
296
303
  * @returns The current instance of the application.
297
304
  * @throws Error if the handler is not a function.
298
305
  *
@@ -316,7 +323,8 @@ export class AgentApplication<TState extends TurnState> {
316
323
  event: ConversationUpdateEvents,
317
324
  handler: (context: TurnContext, state: TState) => Promise<void>,
318
325
  authHandlers: string[] = [],
319
- rank: RouteRank = RouteRank.Unspecified
326
+ rank: RouteRank = RouteRank.Unspecified,
327
+ isAgenticRoute: boolean = false
320
328
  ): this {
321
329
  if (typeof handler !== 'function') {
322
330
  throw new Error(
@@ -324,8 +332,8 @@ export class AgentApplication<TState extends TurnState> {
324
332
  )
325
333
  }
326
334
 
327
- const selector = this.createConversationUpdateSelector(event)
328
- this.addRoute(selector, handler, false, rank, authHandlers)
335
+ const selector = this.createConversationUpdateSelector(event, isAgenticRoute)
336
+ this.addRoute(selector, handler, false, rank, authHandlers, isAgenticRoute)
329
337
  return this
330
338
  }
331
339
 
@@ -338,6 +346,7 @@ export class AgentApplication<TState extends TurnState> {
338
346
  * @throws Error if the adapter is not configured.
339
347
  */
340
348
  protected async continueConversationAsync (
349
+ botAppIdOrIdentity: string | JwtPayload,
341
350
  conversationReferenceOrContext: ConversationReference | TurnContext,
342
351
  logic: (context: TurnContext) => Promise<void>
343
352
  ): Promise<void> {
@@ -359,7 +368,7 @@ export class AgentApplication<TState extends TurnState> {
359
368
  reference = conversationReferenceOrContext
360
369
  }
361
370
 
362
- await this._adapter.continueConversation(reference, logic)
371
+ await this._adapter.continueConversation(botAppIdOrIdentity, reference, logic)
363
372
  }
364
373
 
365
374
  /**
@@ -370,6 +379,7 @@ export class AgentApplication<TState extends TurnState> {
370
379
  * @param handler - The handler function that will be called when a matching message is received.
371
380
  * @param authHandlers - Array of authentication handler names for this message handler. Defaults to empty array.
372
381
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
382
+ * @param isAgenticRoute - Indicates if this handler is for agentic requests only. Defaults to false.
373
383
  * @returns The current instance of the application.
374
384
  *
375
385
  * @remarks
@@ -394,11 +404,12 @@ export class AgentApplication<TState extends TurnState> {
394
404
  keyword: string | RegExp | RouteSelector | (string | RegExp | RouteSelector)[],
395
405
  handler: (context: TurnContext, state: TState) => Promise<void>,
396
406
  authHandlers: string[] = [],
397
- rank: RouteRank = RouteRank.Unspecified
407
+ rank: RouteRank = RouteRank.Unspecified,
408
+ isAgenticRoute: boolean = false
398
409
  ): this {
399
410
  (Array.isArray(keyword) ? keyword : [keyword]).forEach((k) => {
400
- const selector = this.createMessageSelector(k)
401
- this.addRoute(selector, handler, false, rank, authHandlers)
411
+ const selector = this.createMessageSelector(k, isAgenticRoute)
412
+ this.addRoute(selector, handler, false, rank, authHandlers, isAgenticRoute)
402
413
  })
403
414
  return this
404
415
  }
@@ -468,6 +479,7 @@ export class AgentApplication<TState extends TurnState> {
468
479
  *
469
480
  * @param handler - The handler function that will be called when a message reaction is added.
470
481
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
482
+ * @param isAgenticRoute - Indicates if this handler is for agentic requests only. Defaults to false.
471
483
  * @returns The current instance of the application.
472
484
  *
473
485
  * @remarks
@@ -487,14 +499,16 @@ export class AgentApplication<TState extends TurnState> {
487
499
  */
488
500
  public onMessageReactionAdded (
489
501
  handler: (context: TurnContext, state: TState) => Promise<void>,
490
- rank: RouteRank = RouteRank.Unspecified): this {
502
+ rank: RouteRank = RouteRank.Unspecified,
503
+ isAgenticRoute: boolean = false): this {
491
504
  const selector = async (context: TurnContext): Promise<boolean> => {
492
505
  return context.activity.type === ActivityTypes.MessageReaction &&
493
506
  Array.isArray(context.activity.reactionsAdded) &&
494
- context.activity.reactionsAdded.length > 0
507
+ context.activity.reactionsAdded.length > 0 &&
508
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))
495
509
  }
496
510
 
497
- this.addRoute(selector, handler, false, rank)
511
+ this.addRoute(selector, handler, false, rank, [], isAgenticRoute)
498
512
  return this
499
513
  }
500
514
 
@@ -503,6 +517,7 @@ export class AgentApplication<TState extends TurnState> {
503
517
  *
504
518
  * @param handler - The handler function that will be called when a message reaction is removed.
505
519
  * @param rank - The rank of the route, used to determine the order of evaluation. Defaults to RouteRank.Unspecified.
520
+ * @param isAgenticRoute - Indicates if this handler is for agentic requests only. Defaults to false.
506
521
  * @returns The current instance of the application.
507
522
  *
508
523
  * @remarks
@@ -522,14 +537,16 @@ export class AgentApplication<TState extends TurnState> {
522
537
  */
523
538
  public onMessageReactionRemoved (
524
539
  handler: (context: TurnContext, state: TState) => Promise<void>,
525
- rank: RouteRank = RouteRank.Unspecified): this {
540
+ rank: RouteRank = RouteRank.Unspecified,
541
+ isAgenticRoute: boolean = false): this {
526
542
  const selector = async (context: TurnContext): Promise<boolean> => {
527
543
  return context.activity.type === ActivityTypes.MessageReaction &&
528
544
  Array.isArray(context.activity.reactionsRemoved) &&
529
- context.activity.reactionsRemoved.length > 0
545
+ context.activity.reactionsRemoved.length > 0 &&
546
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))
530
547
  }
531
548
 
532
- this.addRoute(selector, handler, false, rank)
549
+ this.addRoute(selector, handler, false, rank, undefined, isAgenticRoute)
533
550
  return this
534
551
  }
535
552
 
@@ -571,8 +588,8 @@ export class AgentApplication<TState extends TurnState> {
571
588
  * 2. Processes mentions if configured
572
589
  * 3. Loads turn state
573
590
  * 4. Handles authentication flows
574
- * 5. Executes before-turn event handlers
575
- * 6. Downloads files if file downloaders are configured
591
+ * 5. Downloads files if file downloaders are configured
592
+ * 6. Executes before-turn event handlers
576
593
  * 7. Routes to appropriate handlers
577
594
  * 8. Executes after-turn event handlers
578
595
  * 9. Saves turn state
@@ -587,6 +604,10 @@ export class AgentApplication<TState extends TurnState> {
587
604
  *
588
605
  */
589
606
  public async runInternal (turnContext: TurnContext): Promise<boolean> {
607
+ if (turnContext.activity.type === ActivityTypes.Typing) {
608
+ return false
609
+ }
610
+
590
611
  logger.info('Running application with activity:', turnContext.activity.id!)
591
612
  return await this.startLongRunningCall(turnContext, async (context) => {
592
613
  try {
@@ -606,71 +627,43 @@ export class AgentApplication<TState extends TurnState> {
606
627
  const state = turnStateFactory()
607
628
  await state.load(context, storage)
608
629
 
609
- const signInState : SignInState = state.getValue('user.__SIGNIN_STATE_')
610
- logger.debug('SignIn State:', signInState)
611
- if (this._authorization && signInState && signInState.completed === false) {
612
- const flowState = await this._authorization.authHandlers[signInState.handlerId!]?.flow?.getFlowState(context)
613
- logger.debug('Flow State:', flowState)
614
- if (flowState && flowState.flowStarted === true) {
615
- const tokenResponse = await this._authorization.beginOrContinueFlow(turnContext, state, signInState?.handlerId!)
616
- const savedAct = Activity.fromObject(signInState?.continuationActivity!)
617
- if (tokenResponse?.token && tokenResponse.token.length > 0) {
618
- logger.info('resending continuation activity:', savedAct.text)
619
- await this.run(new TurnContext(context.adapter, savedAct))
620
- await state.deleteValue('user.__SIGNIN_STATE_')
621
- return true
622
- }
623
- }
630
+ const { authorized } = await this._authorizationManager?.process(context, async activity => {
631
+ // The incoming activity may come from the storage, so we need to restore the auth handlers.
632
+ // Since the current route may not have auth handlers.
633
+ const route = await this.getRoute(new TurnContext(context.adapter, activity, turnContext.identity))
634
+ return route?.authHandlers ?? []
635
+ }) ?? { authorized: true } // Default to authorized if no auth manager
624
636
 
625
- // return true
637
+ if (!authorized) {
638
+ await state.save(context, storage)
639
+ return false
626
640
  }
627
641
 
628
- if (!(await this.callEventHandlers(context, state, this._beforeTurn))) {
629
- await state.save(context, storage)
642
+ const route = await this.getRoute(context)
643
+
644
+ if (!route) {
645
+ logger.debug('No matching route found for activity:', context.activity)
630
646
  return false
631
647
  }
632
648
 
633
649
  if (Array.isArray(this._options.fileDownloaders) && this._options.fileDownloaders.length > 0) {
634
- const inputFiles = state.temp.inputFiles ?? []
635
650
  for (let i = 0; i < this._options.fileDownloaders.length; i++) {
636
- const files = await this._options.fileDownloaders[i].downloadFiles(context, state)
637
- inputFiles.push(...files)
651
+ await this._options.fileDownloaders[i].downloadAndStoreFiles(context, state)
638
652
  }
639
- state.temp.inputFiles = inputFiles
640
653
  }
641
654
 
642
- for (const route of this._routes) {
643
- if (await route.selector(context)) {
644
- if (route.authHandlers === undefined || route.authHandlers.length === 0) {
645
- await route.handler(context, state)
646
- } else {
647
- let signInComplete = false
648
- for (const authHandlerId of route.authHandlers) {
649
- logger.info(`Executing route handler for authHandlerId: ${authHandlerId}`)
650
- const tokenResponse = await this._authorization?.beginOrContinueFlow(turnContext, state, authHandlerId)
651
- signInComplete = (tokenResponse?.token !== undefined && tokenResponse?.token.length > 0)
652
- if (!signInComplete) {
653
- break
654
- }
655
- }
656
- if (signInComplete) {
657
- await route.handler(context, state)
658
- }
659
- }
660
-
661
- if (await this.callEventHandlers(context, state, this._afterTurn)) {
662
- await state.save(context, storage)
663
- }
664
-
665
- return true
666
- }
655
+ if (!(await this.callEventHandlers(context, state, this._beforeTurn))) {
656
+ await state.save(context, storage)
657
+ return false
667
658
  }
668
659
 
660
+ await route.handler(context, state)
661
+
669
662
  if (await this.callEventHandlers(context, state, this._afterTurn)) {
670
663
  await state.save(context, storage)
671
664
  }
672
665
 
673
- return false
666
+ return true
674
667
  } catch (err: any) {
675
668
  logger.error(err)
676
669
  throw err
@@ -680,6 +673,17 @@ export class AgentApplication<TState extends TurnState> {
680
673
  })
681
674
  }
682
675
 
676
+ /**
677
+ * Finds the appropriate route for the given context.
678
+ */
679
+ private async getRoute (context: TurnContext) {
680
+ for (const route of this._routes) {
681
+ if (await route.selector(context)) {
682
+ return route
683
+ }
684
+ }
685
+ }
686
+
683
687
  /**
684
688
  * Sends a proactive message to a conversation.
685
689
  *
@@ -703,13 +707,14 @@ export class AgentApplication<TState extends TurnState> {
703
707
  *
704
708
  */
705
709
  public async sendProactiveActivity (
710
+ botAppIdOrIdentity: string | JwtPayload,
706
711
  context: TurnContext | ConversationReference,
707
712
  activityOrText: string | Activity,
708
713
  speak?: string,
709
714
  inputHint?: string
710
715
  ): Promise<ResourceResponse | undefined> {
711
716
  let response: ResourceResponse | undefined
712
- await this.continueConversationAsync(context, async (ctx) => {
717
+ await this.continueConversationAsync(botAppIdOrIdentity, context, async (ctx) => {
713
718
  response = await ctx.sendActivity(activityOrText, speak, inputHint)
714
719
  })
715
720
 
@@ -908,7 +913,7 @@ export class AgentApplication<TState extends TurnState> {
908
913
  ): Promise<boolean> {
909
914
  if (context.activity.type === ActivityTypes.Message && this._options.longRunningMessages) {
910
915
  return new Promise<boolean>((resolve, reject) => {
911
- this.continueConversationAsync(context, async (ctx) => {
916
+ this.continueConversationAsync(context.identity, context, async (ctx) => {
912
917
  try {
913
918
  for (const key in context.activity) {
914
919
  (ctx.activity as any)[key] = (context.activity as any)[key]
@@ -931,20 +936,25 @@ export class AgentApplication<TState extends TurnState> {
931
936
  * Creates a selector function for activity types.
932
937
  *
933
938
  * @param type - The activity type to match. Can be a string, RegExp, or RouteSelector function.
939
+ * @param isAgenticRoute - Indicates if the route is for agentic requests only. Defaults to false.
934
940
  * @returns A RouteSelector function that matches the specified activity type.
935
941
  */
936
- private createActivitySelector (type: string | RegExp | RouteSelector): RouteSelector {
942
+ private createActivitySelector (type: string | RegExp | RouteSelector, isAgenticRoute: boolean = false): RouteSelector {
937
943
  if (typeof type === 'function') {
938
944
  return type
939
945
  } else if (type instanceof RegExp) {
940
946
  return (context: TurnContext) => {
941
- return Promise.resolve(context?.activity?.type ? type.test(context.activity.type) : false)
947
+ return Promise.resolve(context?.activity?.type
948
+ ? type.test(context.activity.type) && (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))
949
+ : false)
942
950
  }
943
951
  } else {
944
952
  const typeName = type.toString().toLocaleLowerCase()
945
953
  return (context: TurnContext) => {
946
954
  return Promise.resolve(
947
- context?.activity?.type ? context.activity.type.toLocaleLowerCase() === typeName : false
955
+ context?.activity?.type
956
+ ? context.activity.type.toLocaleLowerCase() === typeName && (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))
957
+ : false
948
958
  )
949
959
  }
950
960
  }
@@ -954,13 +964,15 @@ export class AgentApplication<TState extends TurnState> {
954
964
  * Creates a selector function for conversation update events.
955
965
  *
956
966
  * @param event - The conversation update event to match.
967
+ * @param isAgenticRoute - Indicates if the route is for agentic requests only. Defaults to false.
957
968
  * @returns A RouteSelector function that matches the specified conversation update event.
958
969
  */
959
- private createConversationUpdateSelector (event: ConversationUpdateEvents): RouteSelector {
970
+ private createConversationUpdateSelector (event: ConversationUpdateEvents, isAgenticRoute: boolean = false): RouteSelector {
960
971
  switch (event) {
961
972
  case 'membersAdded':
962
973
  return (context: TurnContext): Promise<boolean> => {
963
974
  return Promise.resolve(
975
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest())) &&
964
976
  context?.activity?.type === ActivityTypes.ConversationUpdate &&
965
977
  Array.isArray(context?.activity?.membersAdded) &&
966
978
  context.activity.membersAdded.length > 0
@@ -969,6 +981,7 @@ export class AgentApplication<TState extends TurnState> {
969
981
  case 'membersRemoved':
970
982
  return (context: TurnContext): Promise<boolean> => {
971
983
  return Promise.resolve(
984
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest())) &&
972
985
  context?.activity?.type === ActivityTypes.ConversationUpdate &&
973
986
  Array.isArray(context?.activity?.membersRemoved) &&
974
987
  context.activity.membersRemoved.length > 0
@@ -977,6 +990,7 @@ export class AgentApplication<TState extends TurnState> {
977
990
  default:
978
991
  return (context: TurnContext): Promise<boolean> => {
979
992
  return Promise.resolve(
993
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest())) &&
980
994
  context?.activity?.type === ActivityTypes.ConversationUpdate &&
981
995
  context?.activity?.channelData?.eventType === event
982
996
  )
@@ -988,14 +1002,17 @@ export class AgentApplication<TState extends TurnState> {
988
1002
  * Creates a selector function for message content matching.
989
1003
  *
990
1004
  * @param keyword - The keyword, pattern, or selector function to match against message text.
1005
+ * @param isAgenticRoute - Indicates if the route is for agentic requests only. Defaults to false.
991
1006
  * @returns A RouteSelector function that matches messages based on the specified keyword.
992
1007
  */
993
- private createMessageSelector (keyword: string | RegExp | RouteSelector): RouteSelector {
1008
+ private createMessageSelector (keyword: string | RegExp | RouteSelector, isAgenticRoute: boolean = false): RouteSelector {
994
1009
  if (typeof keyword === 'function') {
995
1010
  return keyword
996
1011
  } else if (keyword instanceof RegExp) {
997
1012
  return (context: TurnContext) => {
998
- if (context?.activity?.type === ActivityTypes.Message && context.activity.text) {
1013
+ if (context?.activity?.type === ActivityTypes.Message &&
1014
+ context.activity.text &&
1015
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))) {
999
1016
  return Promise.resolve(keyword.test(context.activity.text))
1000
1017
  } else {
1001
1018
  return Promise.resolve(false)
@@ -1004,7 +1021,9 @@ export class AgentApplication<TState extends TurnState> {
1004
1021
  } else {
1005
1022
  const k = keyword.toString().toLocaleLowerCase()
1006
1023
  return (context: TurnContext) => {
1007
- if (context?.activity?.type === ActivityTypes.Message && context.activity.text) {
1024
+ if (context?.activity?.type === ActivityTypes.Message &&
1025
+ context.activity.text &&
1026
+ (!isAgenticRoute || (isAgenticRoute && context.activity.isAgenticRequest()))) {
1008
1027
  return Promise.resolve(context.activity.text.toLocaleLowerCase() === k)
1009
1028
  } else {
1010
1029
  return Promise.resolve(false)
@@ -6,7 +6,7 @@
6
6
  import { Storage } from '../storage'
7
7
  import { AgentApplication } from './agentApplication'
8
8
  import { AgentApplicationOptions } from './agentApplicationOptions'
9
- import { AuthorizationHandlers } from './authorization'
9
+ import { AuthorizationOptions } from './auth/types'
10
10
  import { TurnState } from './turnState'
11
11
 
12
12
  /**
@@ -59,7 +59,7 @@ export class AgentApplicationBuilder<TState extends TurnState = TurnState> {
59
59
  * @param authHandlers The user identity authentication options
60
60
  * @returns This builder instance for chaining
61
61
  */
62
- public withAuthorization (authHandlers: AuthorizationHandlers): this {
62
+ public withAuthorization (authHandlers: AuthorizationOptions): this {
63
63
  this._options.authorization = authHandlers
64
64
  return this
65
65
  }
@@ -8,9 +8,10 @@ import { Storage } from '../storage'
8
8
  import { TranscriptLogger } from '../transcript'
9
9
  import { AdaptiveCardsOptions } from './adaptiveCards'
10
10
  import { InputFileDownloader } from './inputFileDownloader'
11
- import { AuthorizationHandlers } from './authorization'
12
11
  import { TurnState } from './turnState'
13
12
  import { HeaderPropagationDefinition } from '../headerPropagation'
13
+ import { AuthorizationOptions } from './auth/types'
14
+ import { Connections } from '../auth/connections'
14
15
 
15
16
  /**
16
17
  * Configuration options for creating and initializing an Agent Application.
@@ -95,7 +96,7 @@ export interface AgentApplicationOptions<TState extends TurnState> {
95
96
  *
96
97
  * @default undefined (no authorization required)
97
98
  */
98
- authorization?: AuthorizationHandlers;
99
+ authorization?: AuthorizationOptions;
99
100
 
100
101
  /**
101
102
  * Configuration options for handling Adaptive Card actions and interactions.
@@ -139,4 +140,11 @@ export interface AgentApplicationOptions<TState extends TurnState> {
139
140
  * @default undefined
140
141
  */
141
142
  headerPropagation?: HeaderPropagationDefinition
143
+
144
+ /**
145
+ * Optional. Configuration for managing multiple authentication connections within the agent.
146
+ * This allows the agent to handle authentication across different services or
147
+ * identity providers.
148
+ */
149
+ connections?: Connections
142
150
  }
@@ -51,6 +51,14 @@ export interface AppRoute<TState extends TurnState> {
51
51
  */
52
52
  handler: RouteHandler<TState>;
53
53
 
54
+ /**
55
+ * Indicates whether this route is an agentic-only route.
56
+ *
57
+ * @default false
58
+ *
59
+ */
60
+ isAgenticRoute?: boolean;
61
+
54
62
  /**
55
63
  * Indicates whether this route is an invoke route.
56
64
  *
@@ -26,23 +26,26 @@ const logger = debug('agents:attachmentDownloader')
26
26
  */
27
27
  export class AttachmentDownloader<TState extends TurnState = TurnState> implements InputFileDownloader<TState> {
28
28
  private _httpClient: AxiosInstance
29
+ private _stateKey: string
29
30
 
30
31
  /**
31
32
  * Creates an instance of AttachmentDownloader.
32
33
  * This class is responsible for downloading input files from attachments.
34
+ *
35
+ * @param stateKey The key to store files in state. Defaults to 'inputFiles'.
33
36
  */
34
- public constructor () {
37
+ public constructor (stateKey: string = 'inputFiles') {
35
38
  this._httpClient = axios.create()
39
+ this._stateKey = stateKey
36
40
  }
37
41
 
38
42
  /**
39
43
  * Downloads files from the attachments in the current turn context.
40
44
  *
41
45
  * @param context The turn context containing the activity with attachments.
42
- * @param state The turn state for the current conversation.
43
46
  * @returns A promise that resolves to an array of downloaded input files.
44
47
  */
45
- public async downloadFiles (context: TurnContext, state: TState): Promise<InputFile[]> {
48
+ public async downloadFiles (context: TurnContext): Promise<InputFile[]> {
46
49
  const attachments = context.activity.attachments?.filter((a) => !a.contentType.startsWith('text/html'))
47
50
  if (!attachments || attachments.length === 0) {
48
51
  logger.info('No Attachments to download')
@@ -66,6 +69,18 @@ export class AttachmentDownloader<TState extends TurnState = TurnState> implemen
66
69
  return files
67
70
  }
68
71
 
72
+ /**
73
+ * Downloads files from the attachments in the current turn context and stores them in state.
74
+ *
75
+ * @param context The turn context containing the activity with attachments.
76
+ * @param state The turn state to store the files in.
77
+ * @returns A promise that resolves when the downloaded files are stored.
78
+ */
79
+ public async downloadAndStoreFiles (context: TurnContext, state: TState): Promise<void> {
80
+ const files = await this.downloadFiles(context)
81
+ state.setValue(this._stateKey, files)
82
+ }
83
+
69
84
  private async downloadFile (attachment: Attachment, accessToken: string): Promise<InputFile | undefined> {
70
85
  if (
71
86
  (attachment.contentUrl && attachment.contentUrl.startsWith('https://')) ||