@microsoft/agents-hosting 1.9.0-beta.3.gb2d23c1c44 → 1.9.1

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/README.md +182 -4
  2. package/dist/package.json +3 -3
  3. package/dist/src/app/agentApplication.d.ts +4 -3
  4. package/dist/src/app/agentApplication.js +24 -21
  5. package/dist/src/app/agentApplication.js.map +1 -1
  6. package/dist/src/app/agentApplicationBuilder.d.ts +9 -2
  7. package/dist/src/app/agentApplicationBuilder.js +9 -0
  8. package/dist/src/app/agentApplicationBuilder.js.map +1 -1
  9. package/dist/src/app/agentApplicationOptions.d.ts +16 -4
  10. package/dist/src/app/auth/authorization.d.ts +54 -0
  11. package/dist/src/app/auth/authorization.js +63 -2
  12. package/dist/src/app/auth/authorization.js.map +1 -1
  13. package/dist/src/app/auth/authorizationManager.d.ts +0 -8
  14. package/dist/src/app/auth/authorizationManager.js +104 -178
  15. package/dist/src/app/auth/authorizationManager.js.map +1 -1
  16. package/dist/src/app/auth/handlerStorage.d.ts +5 -3
  17. package/dist/src/app/auth/handlerStorage.js +36 -10
  18. package/dist/src/app/auth/handlerStorage.js.map +1 -1
  19. package/dist/src/app/auth/types.d.ts +2 -2
  20. package/dist/src/app/index.d.ts +1 -0
  21. package/dist/src/app/proactive/proactive.js +10 -6
  22. package/dist/src/app/proactive/proactive.js.map +1 -1
  23. package/dist/src/app/proactive/proactiveOptions.d.ts +2 -2
  24. package/dist/src/app/rateLimit.d.ts +315 -0
  25. package/dist/src/app/rateLimit.js +333 -0
  26. package/dist/src/app/rateLimit.js.map +1 -0
  27. package/dist/src/app/turnState.d.ts +6 -3
  28. package/dist/src/app/turnState.js +43 -4
  29. package/dist/src/app/turnState.js.map +1 -1
  30. package/dist/src/auth/authConfiguration.d.ts +10 -3
  31. package/dist/src/auth/authConfiguration.js +292 -259
  32. package/dist/src/auth/authConfiguration.js.map +1 -1
  33. package/dist/src/auth/delegatedTokenCredential.d.ts +29 -0
  34. package/dist/src/auth/delegatedTokenCredential.js +49 -0
  35. package/dist/src/auth/delegatedTokenCredential.js.map +1 -0
  36. package/dist/src/auth/msal/msalTokenCredential.js +1 -1
  37. package/dist/src/auth/msal/msalTokenCredential.js.map +1 -1
  38. package/dist/src/auth/settings.d.ts +8 -70
  39. package/dist/src/auth/settings.js +5 -67
  40. package/dist/src/auth/settings.js.map +1 -1
  41. package/dist/src/cloudAdapter.d.ts +5 -0
  42. package/dist/src/cloudAdapter.js +13 -103
  43. package/dist/src/cloudAdapter.js.map +1 -1
  44. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.d.ts +23 -0
  45. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js +183 -0
  46. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js.map +1 -0
  47. package/dist/src/configuration/configuration.d.ts +83 -0
  48. package/dist/src/configuration/configuration.js +836 -0
  49. package/dist/src/configuration/configuration.js.map +1 -0
  50. package/dist/src/configuration/configurationSource.d.ts +57 -0
  51. package/dist/src/configuration/configurationSource.js +7 -0
  52. package/dist/src/configuration/configurationSource.js.map +1 -0
  53. package/dist/src/configuration/environmentConfiguration.d.ts +14 -0
  54. package/dist/src/configuration/environmentConfiguration.js +271 -0
  55. package/dist/src/configuration/environmentConfiguration.js.map +1 -0
  56. package/dist/src/configuration/index.d.ts +7 -0
  57. package/dist/src/configuration/index.js +14 -0
  58. package/dist/src/configuration/index.js.map +1 -0
  59. package/dist/src/configuration/jsonFileConfigurationSource.d.ts +15 -0
  60. package/dist/src/configuration/jsonFileConfigurationSource.js +58 -0
  61. package/dist/src/configuration/jsonFileConfigurationSource.js.map +1 -0
  62. package/dist/src/createCloudAdapter.d.ts +30 -5
  63. package/dist/src/createCloudAdapter.js +17 -10
  64. package/dist/src/createCloudAdapter.js.map +1 -1
  65. package/dist/src/errorHelper.js +124 -5
  66. package/dist/src/errorHelper.js.map +1 -1
  67. package/dist/src/index.d.ts +1 -0
  68. package/dist/src/index.js +1 -0
  69. package/dist/src/index.js.map +1 -1
  70. package/dist/src/observability/traces.d.ts +6 -4
  71. package/dist/src/observability/traces.js +10 -9
  72. package/dist/src/observability/traces.js.map +1 -1
  73. package/dist/src/outboundHostValidator.d.ts +4 -1
  74. package/dist/src/outboundHostValidator.js +25 -48
  75. package/dist/src/outboundHostValidator.js.map +1 -1
  76. package/dist/src/state/agentState.d.ts +8 -3
  77. package/dist/src/state/agentState.js +26 -8
  78. package/dist/src/state/agentState.js.map +1 -1
  79. package/dist/src/state/conversationState.d.ts +2 -2
  80. package/dist/src/state/conversationState.js.map +1 -1
  81. package/dist/src/state/userState.d.ts +2 -2
  82. package/dist/src/state/userState.js.map +1 -1
  83. package/dist/src/statusCodes.d.ts +5 -0
  84. package/dist/src/statusCodes.js +5 -0
  85. package/dist/src/statusCodes.js.map +1 -1
  86. package/dist/src/storage/fileStorage.d.ts +83 -68
  87. package/dist/src/storage/fileStorage.js +279 -105
  88. package/dist/src/storage/fileStorage.js.map +1 -1
  89. package/dist/src/storage/index.d.ts +1 -0
  90. package/dist/src/storage/index.js +1 -0
  91. package/dist/src/storage/index.js.map +1 -1
  92. package/dist/src/storage/memoryStorage.d.ts +85 -60
  93. package/dist/src/storage/memoryStorage.js +244 -87
  94. package/dist/src/storage/memoryStorage.js.map +1 -1
  95. package/dist/src/storage/storage.d.ts +100 -2
  96. package/dist/src/storage/storage.js +25 -0
  97. package/dist/src/storage/storage.js.map +1 -1
  98. package/dist/src/storage/storageCompatibility.d.ts +17 -0
  99. package/dist/src/storage/storageCompatibility.js +157 -0
  100. package/dist/src/storage/storageCompatibility.js.map +1 -0
  101. package/dist/src/storage/storageExpiry.d.ts +6 -0
  102. package/dist/src/storage/storageExpiry.js +20 -0
  103. package/dist/src/storage/storageExpiry.js.map +1 -0
  104. package/dist/src/utils/env.d.ts +43 -0
  105. package/dist/src/utils/env.js +42 -6
  106. package/dist/src/utils/env.js.map +1 -1
  107. package/dist/src/utils.d.ts +1 -0
  108. package/dist/src/utils.js +10 -1
  109. package/dist/src/utils.js.map +1 -1
  110. package/package.json +3 -3
  111. package/src/app/agentApplication.ts +27 -14
  112. package/src/app/agentApplicationBuilder.ts +13 -2
  113. package/src/app/agentApplicationOptions.ts +18 -4
  114. package/src/app/auth/authorization.ts +67 -2
  115. package/src/app/auth/authorizationManager.ts +126 -204
  116. package/src/app/auth/handlerStorage.ts +51 -7
  117. package/src/app/auth/types.ts +2 -2
  118. package/src/app/index.ts +7 -0
  119. package/src/app/proactive/proactive.ts +19 -9
  120. package/src/app/proactive/proactiveOptions.ts +2 -2
  121. package/src/app/rateLimit.ts +659 -0
  122. package/src/app/turnState.ts +50 -7
  123. package/src/auth/authConfiguration.ts +415 -260
  124. package/src/auth/delegatedTokenCredential.ts +49 -0
  125. package/src/auth/msal/msalTokenCredential.ts +1 -1
  126. package/src/auth/settings.ts +5 -82
  127. package/src/cloudAdapter.ts +38 -113
  128. package/src/configuration/botFrameworkEnvironmentCompatibility.ts +245 -0
  129. package/src/configuration/configuration.ts +1076 -0
  130. package/src/configuration/configurationSource.ts +76 -0
  131. package/src/configuration/environmentConfiguration.ts +377 -0
  132. package/src/configuration/index.ts +19 -0
  133. package/src/configuration/jsonFileConfigurationSource.ts +74 -0
  134. package/src/createCloudAdapter.ts +52 -9
  135. package/src/errorHelper.ts +151 -5
  136. package/src/index.ts +1 -0
  137. package/src/observability/traces.ts +8 -7
  138. package/src/outboundHostValidator.ts +37 -44
  139. package/src/state/agentState.ts +39 -13
  140. package/src/state/conversationState.ts +2 -2
  141. package/src/state/userState.ts +2 -2
  142. package/src/statusCodes.ts +6 -0
  143. package/src/storage/fileStorage.ts +299 -106
  144. package/src/storage/index.ts +1 -0
  145. package/src/storage/memoryStorage.ts +268 -85
  146. package/src/storage/storage.ts +114 -2
  147. package/src/storage/storageCompatibility.ts +185 -0
  148. package/src/storage/storageExpiry.ts +21 -0
  149. package/src/utils/env.ts +63 -0
  150. package/src/utils.ts +10 -0
@@ -20,6 +20,7 @@ import { TranscriptLoggerMiddleware } from '../transcript'
20
20
  import { CloudAdapter } from '../cloudAdapter'
21
21
  import { Authorization, UserAuthorization, AuthorizationManager } from './auth'
22
22
  import { Proactive } from './proactive'
23
+ import { AgentApplicationRateLimiter } from './rateLimit'
23
24
  import { JwtPayload } from 'jsonwebtoken'
24
25
  import { trace, debug, redactString } from '@microsoft/agents-telemetry'
25
26
  import { AgentApplicationTraceDefinitions } from '../observability'
@@ -104,6 +105,7 @@ export class AgentApplication<TState extends TurnState> {
104
105
  private readonly _proactive?: Proactive<TState>
105
106
  protected readonly _extensions: AgentExtension<TState>[] = []
106
107
  private readonly _adaptiveCards: AdaptiveCardsActions<TState>
108
+ private readonly _rateLimiter?: AgentApplicationRateLimiter
107
109
 
108
110
  /**
109
111
  * Creates a new instance of AgentApplication.
@@ -141,6 +143,7 @@ export class AgentApplication<TState extends TurnState> {
141
143
  longRunningMessages: options?.longRunningMessages !== undefined ? options.longRunningMessages : false,
142
144
  removeRecipientMention: options?.removeRecipientMention !== undefined ? options.removeRecipientMention : true,
143
145
  transcriptLogger: options?.transcriptLogger || undefined,
146
+ rateLimit: options?.rateLimit || undefined,
144
147
  }
145
148
 
146
149
  this._adaptiveCards = new AdaptiveCardsActions<TState>(this)
@@ -148,11 +151,20 @@ export class AgentApplication<TState extends TurnState> {
148
151
  if (this._options.adapter) {
149
152
  this._adapter = this._options.adapter
150
153
  } else {
151
- this._adapter = new CloudAdapter()
154
+ this._adapter = new CloudAdapter(
155
+ undefined,
156
+ undefined,
157
+ undefined,
158
+ { configurationContext: this._options.configurationContext }
159
+ )
152
160
  }
153
161
 
154
162
  this._adapter.setAgentName(this._options.agentName)
155
163
 
164
+ if (this._options.rateLimit && this._options.rateLimit.length > 0) {
165
+ this._rateLimiter = new AgentApplicationRateLimiter(this._options.rateLimit, this._options.storage)
166
+ }
167
+
156
168
  // Create Proactive whenever proactive options are explicitly configured or a storage
157
169
  // backend is available — no explicit `proactive` option is required.
158
170
  if (this._options.proactive !== undefined || this._options.storage !== undefined) {
@@ -201,6 +213,7 @@ export class AgentApplication<TState extends TurnState> {
201
213
  fileDownloaders: this._options.fileDownloaders ? 'configured' : undefined,
202
214
  turnStateFactory: options?.turnStateFactory ? 'custom' : 'default',
203
215
  adaptiveCardsOptions: this._options.adaptiveCardsOptions,
216
+ rateLimitRules: this._options.rateLimit?.length,
204
217
  })
205
218
  }
206
219
 
@@ -208,7 +221,7 @@ export class AgentApplication<TState extends TurnState> {
208
221
  * Gets the authorization instance for the application.
209
222
  *
210
223
  * @returns The authorization instance.
211
- * @throws Error if no authentication options were configured.
224
+ * @throws Error if no authorization handlers were resolved.
212
225
  */
213
226
  public get authorization (): Authorization {
214
227
  if (this._authorizationManager.handlers.length === 0) {
@@ -495,7 +508,7 @@ export class AgentApplication<TState extends TurnState> {
495
508
  *
496
509
  * @param handler - The handler function to be called after successful sign-in.
497
510
  * @returns The current instance of the application.
498
- * @throws Error if authentication options were not configured.
511
+ * @throws Error if no authorization handlers were resolved.
499
512
  *
500
513
  * @remarks
501
514
  * This method allows you to perform actions after a user has successfully authenticated.
@@ -510,11 +523,7 @@ export class AgentApplication<TState extends TurnState> {
510
523
  *
511
524
  */
512
525
  public onSignInSuccess (handler: (context: TurnContext, state: TurnState, id?: string) => Promise<void>): this {
513
- if (this.options.authorization) {
514
- this.authorization.onSignInSuccess(handler)
515
- } else {
516
- throw ExceptionHelper.generateException(Error, Errors.AuthorizationOptionNotAvailable)
517
- }
526
+ this.authorization.onSignInSuccess(handler)
518
527
  return this
519
528
  }
520
529
 
@@ -523,7 +532,7 @@ export class AgentApplication<TState extends TurnState> {
523
532
  *
524
533
  * @param handler - The handler function to be called after a failed sign-in attempt.
525
534
  * @returns The current instance of the application.
526
- * @throws Error if authentication options were not configured.
535
+ * @throws Error if no authorization handlers were resolved.
527
536
  *
528
537
  * @remarks
529
538
  * This method allows you to handle cases where a user fails to authenticate,
@@ -538,11 +547,7 @@ export class AgentApplication<TState extends TurnState> {
538
547
  *
539
548
  */
540
549
  public onSignInFailure (handler: (context: TurnContext, state: TurnState, id?: string) => Promise<void>): this {
541
- if (this.options.authorization) {
542
- this.authorization.onSignInFailure(handler)
543
- } else {
544
- throw ExceptionHelper.generateException(Error, Errors.AuthorizationOptionNotAvailable)
545
- }
550
+ this.authorization.onSignInFailure(handler)
546
551
  return this
547
552
  }
548
553
 
@@ -675,6 +680,14 @@ export class AgentApplication<TState extends TurnState> {
675
680
  * ```
676
681
  */
677
682
  public async runInternal (turnContext: TurnContext): Promise<boolean> {
683
+ if (this._rateLimiter) {
684
+ const rateLimitDecision = await this._rateLimiter.shouldAllowTurn(turnContext)
685
+ if (!rateLimitDecision.allowed) {
686
+ await this._rateLimiter.handleThrottledTurn(turnContext, rateLimitDecision.rule!, rateLimitDecision.result!)
687
+ return false
688
+ }
689
+ }
690
+
678
691
  const { authorized, context } = await this.handleAuthorization(turnContext)
679
692
 
680
693
  if (!authorized) {
@@ -3,11 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Storage } from '../storage'
6
+ import { StorageProvider } from '../storage'
7
7
  import { AgentApplication } from './agentApplication'
8
8
  import { AgentApplicationOptions } from './agentApplicationOptions'
9
9
  import { AuthorizationOptions } from './auth/types'
10
10
  import { ProactiveOptions } from './proactive'
11
+ import { RateLimitRule } from './rateLimit'
11
12
  import { TurnState } from './turnState'
12
13
  import { TypingOptions } from './agentApplicationOptions'
13
14
 
@@ -31,7 +32,7 @@ export class AgentApplicationBuilder<TState extends TurnState = TurnState> {
31
32
  * @param storage The storage implementation to use
32
33
  * @returns This builder instance for chaining
33
34
  */
34
- public withStorage (storage: Storage): this {
35
+ public withStorage (storage: StorageProvider): this {
35
36
  this._options.storage = storage
36
37
  return this
37
38
  }
@@ -86,6 +87,16 @@ export class AgentApplicationBuilder<TState extends TurnState = TurnState> {
86
87
  return this
87
88
  }
88
89
 
90
+ /**
91
+ * Configures rate limit rules for incoming turns.
92
+ * @param rules The rate limit rules to apply
93
+ * @returns This builder instance for chaining
94
+ */
95
+ public withRateLimit (rules: RateLimitRule[]): this {
96
+ this._options.rateLimit = rules
97
+ return this
98
+ }
99
+
89
100
  /**
90
101
  * Builds and returns a new AgentApplication instance configured with the provided options.
91
102
  * @returns A new AgentApplication instance
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { CloudAdapter } from '../cloudAdapter'
7
- import { Storage } from '../storage'
7
+ import { StorageProvider } from '../storage'
8
8
  import { TranscriptLogger } from '../transcript'
9
9
  import { AdaptiveCardsOptions } from './adaptiveCards'
10
10
  import { InputFileDownloader } from './inputFileDownloader'
@@ -13,6 +13,8 @@ import { HeaderPropagationDefinition } from '../headerPropagation'
13
13
  import { AuthorizationOptions } from './auth/types'
14
14
  import { Connections } from '../auth/connections'
15
15
  import { ProactiveOptions } from './proactive'
16
+ import { RateLimitRule } from './rateLimit'
17
+ import { ConfigurationContext } from '../configuration/configuration'
16
18
 
17
19
  /**
18
20
  * Typing timer settings for a specific channel or the global default.
@@ -52,6 +54,12 @@ export interface TypingOptions extends TypingTimingOptions {
52
54
  * custom state management specific to your agent's needs.
53
55
  */
54
56
  export interface AgentApplicationOptions<TState extends TurnState> {
57
+ /**
58
+ * Optional host-scoped external configuration used by the application's
59
+ * default adapter and authorization handlers.
60
+ */
61
+ configurationContext?: ConfigurationContext;
62
+
55
63
  /**
56
64
  * The adapter used for handling bot interactions with various messaging platforms.
57
65
  * This adapter manages the communication layer between your agent and the Bot Framework.
@@ -72,12 +80,12 @@ export interface AgentApplicationOptions<TState extends TurnState> {
72
80
 
73
81
  /**
74
82
  * The storage mechanism for persisting conversation and user state across turns.
75
- * This can be any implementation of the Storage interface, such as memory storage
76
- * for development or blob storage for production scenarios.
83
+ * This can be a legacy Storage implementation, a StorageV2 implementation,
84
+ * or a built-in storage provider.
77
85
  *
78
86
  * @default undefined (no persistence)
79
87
  */
80
- storage?: Storage;
88
+ storage?: StorageProvider;
81
89
 
82
90
  /**
83
91
  * Whether to start a typing indicator timer when the bot begins processing a message.
@@ -201,4 +209,10 @@ export interface AgentApplicationOptions<TState extends TurnState> {
201
209
  * When provided, `app.proactive` will be available.
202
210
  */
203
211
  proactive?: ProactiveOptions
212
+
213
+ /**
214
+ * Optional. Rate limit rules for incoming turns.
215
+ * When omitted or empty, no rate limiting is applied.
216
+ */
217
+ rateLimit?: RateLimitRule[]
204
218
  }
@@ -3,21 +3,25 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { debug } from '@microsoft/agents-telemetry'
6
+ import { TokenCredential } from '@azure/core-auth'
7
7
  import { ExceptionHelper } from '@microsoft/agents-activity'
8
+ import { debug } from '@microsoft/agents-telemetry'
9
+ import { DelegatedTokenCredential } from '../../auth/delegatedTokenCredential'
10
+ import { Errors } from '../../errorHelper'
8
11
  import { TokenResponse } from '../../oauth'
9
12
  import { TurnContext } from '../../turnContext'
10
13
  import { TurnState } from '../turnState'
11
14
  import { AuthorizationManager } from './authorizationManager'
12
15
  import { AuthorizationHandlerTokenOptions } from './types'
13
- import { Errors } from '../../errorHelper'
14
16
 
15
17
  const logger = debug('agents:authorization')
16
18
 
17
19
  export interface Authorization {
18
20
  getToken(context: TurnContext, authHandlerId: string): Promise<TokenResponse>
21
+ getTokenAsTokenCredential?(context: TurnContext, authHandlerId: string): TokenCredential
19
22
  exchangeToken(context: TurnContext, scopes: string[], authHandlerId: string): Promise<TokenResponse>
20
23
  exchangeToken(context: TurnContext, authHandlerId: string, options?: AuthorizationHandlerTokenOptions): Promise<TokenResponse>
24
+ exchangeTokenAsTokenCredential?(context: TurnContext, authHandlerId: string, options?: AuthorizationHandlerTokenOptions): TokenCredential
21
25
  signOut(context: TurnContext, state: TurnState, authHandlerId?: string): Promise<void>
22
26
  onSignInSuccess(handler: (context: TurnContext, state: TurnState, authHandlerId?: string) => Promise<void>): void
23
27
  onSignInFailure(handler: (context: TurnContext, state: TurnState, authHandlerId?: string, errorMessage?: string) => Promise<void>): void
@@ -75,6 +79,31 @@ export class UserAuthorization implements Authorization {
75
79
  return { token }
76
80
  }
77
81
 
82
+ /**
83
+ * Creates a token credential backed by the current turn's user token.
84
+ *
85
+ * @param context - The context object for the current turn.
86
+ * @param authHandlerId - ID of the auth handler to use.
87
+ * @returns A {@link TokenCredential} that resolves to the current turn's user token.
88
+ * @throws {Error} If the auth handler is not configured.
89
+ *
90
+ * @remarks
91
+ * The returned credential is scoped to this `context` and should only be used during the
92
+ * current turn. Do not cache it or pass it to a client that outlives the turn; create a new
93
+ * credential in each turn instead.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const credential = auth.getTokenAsTokenCredential(context, 'microsoft');
98
+ * const client = new SomeAzureClient(endpoint, credential);
99
+ * ```
100
+ *
101
+ * @public
102
+ */
103
+ public getTokenAsTokenCredential (context: TurnContext, authHandlerId: string): TokenCredential {
104
+ return new DelegatedTokenCredential(async () => await this.getToken(context, authHandlerId))
105
+ }
106
+
78
107
  /**
79
108
  * @deprecated
80
109
  * Exchanges a token for a new token with different scopes.
@@ -153,6 +182,42 @@ export class UserAuthorization implements Authorization {
153
182
  throw ExceptionHelper.generateException(Error, Errors.InvalidExchangeTokenParameters)
154
183
  }
155
184
 
185
+ /**
186
+ * Creates a token credential that exchanges the user token for requested scopes during the current turn.
187
+ *
188
+ * @param context - The context object for the current turn.
189
+ * @param authHandlerId - ID of the auth handler to use.
190
+ * @param options - Optional token options. If `connection` and `scopes` are NOT provided, the auth handler's
191
+ * configured `obo` options are used. Provide `options` only to override them for a specific credential.
192
+ * @returns A {@link TokenCredential} that exchanges the current turn's user token for the requested scopes.
193
+ * @throws {Error} If the auth handler is not configured.
194
+ *
195
+ * @remarks
196
+ * The returned credential is scoped to this `context` and should only be used during the current turn.
197
+ * Do not cache it or pass it to a client that outlives the turn; create a new credential in each turn instead.
198
+ * Scopes requested from the credential (via `TokenCredential.getToken`) are combined with `options.scopes`,
199
+ * and duplicate scopes are removed.
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const credential = auth.exchangeTokenAsTokenCredential(
204
+ * context,
205
+ * 'microsoft',
206
+ * { connection: 'oboConnection', scopes: ['https://graph.microsoft.com/.default'] }
207
+ * );
208
+ * const client = new SomeAzureClient(endpoint, credential);
209
+ * ```
210
+ *
211
+ * @public
212
+ */
213
+ public exchangeTokenAsTokenCredential (context: TurnContext, authHandlerId: string, options?: AuthorizationHandlerTokenOptions): TokenCredential {
214
+ return new DelegatedTokenCredential(async (scopes) => {
215
+ const scopeSet = new Set([...scopes, ...(options?.scopes ?? [])])
216
+ const mergedScopes = Array.from(scopeSet)
217
+ return await this.exchangeToken(context, authHandlerId, { connection: options?.connection, scopes: mergedScopes })
218
+ })
219
+ }
220
+
156
221
  /**
157
222
  * Signs out the current user.
158
223
  *