@microsoft/agents-hosting 1.1.4-geb1c05c291 → 1.2.0-alpha.19.g9aeee229e8

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 (44) hide show
  1. package/dist/package.json +4 -4
  2. package/dist/src/activityHandler.js +7 -4
  3. package/dist/src/activityHandler.js.map +1 -1
  4. package/dist/src/app/index.d.ts +1 -0
  5. package/dist/src/app/index.js +1 -0
  6. package/dist/src/app/index.js.map +1 -1
  7. package/dist/src/app/streaming/streamingResponse.d.ts +138 -88
  8. package/dist/src/app/streaming/streamingResponse.js +241 -107
  9. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  10. package/dist/src/app/teamsAttachmentDownloader.d.ts +36 -0
  11. package/dist/src/app/teamsAttachmentDownloader.js +103 -0
  12. package/dist/src/app/teamsAttachmentDownloader.js.map +1 -0
  13. package/dist/src/auth/authConfiguration.d.ts +6 -0
  14. package/dist/src/auth/authConfiguration.js +15 -9
  15. package/dist/src/auth/authConfiguration.js.map +1 -1
  16. package/dist/src/auth/authProvider.d.ts +7 -1
  17. package/dist/src/auth/msalTokenProvider.d.ts +7 -1
  18. package/dist/src/auth/msalTokenProvider.js +48 -3
  19. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  20. package/dist/src/cloudAdapter.d.ts +39 -14
  21. package/dist/src/cloudAdapter.js +52 -26
  22. package/dist/src/cloudAdapter.js.map +1 -1
  23. package/dist/src/connector-client/connectorClient.js +10 -9
  24. package/dist/src/connector-client/connectorClient.js.map +1 -1
  25. package/dist/src/errorHelper.d.ts +4 -0
  26. package/dist/src/errorHelper.js +588 -0
  27. package/dist/src/errorHelper.js.map +1 -0
  28. package/dist/src/index.d.ts +1 -0
  29. package/dist/src/index.js +3 -1
  30. package/dist/src/index.js.map +1 -1
  31. package/dist/src/oauth/userTokenClient.js.map +1 -1
  32. package/package.json +4 -4
  33. package/src/activityHandler.ts +8 -5
  34. package/src/app/index.ts +1 -0
  35. package/src/app/streaming/streamingResponse.ts +252 -107
  36. package/src/app/teamsAttachmentDownloader.ts +110 -0
  37. package/src/auth/authConfiguration.ts +13 -2
  38. package/src/auth/authProvider.ts +8 -1
  39. package/src/auth/msalTokenProvider.ts +62 -3
  40. package/src/cloudAdapter.ts +56 -29
  41. package/src/connector-client/connectorClient.ts +11 -10
  42. package/src/errorHelper.ts +674 -0
  43. package/src/index.ts +1 -0
  44. package/src/oauth/userTokenClient.ts +2 -2
@@ -39,6 +39,11 @@ export interface AuthConfiguration {
39
39
  */
40
40
  certKeyFile?: string
41
41
 
42
+ /**
43
+ * Indicates whether to send the X5C param or not (for SNI authentication).
44
+ */
45
+ sendX5C?: boolean
46
+
42
47
  /**
43
48
  * A list of valid issuers for the authentication configuration.
44
49
  */
@@ -104,6 +109,7 @@ export interface AuthConfiguration {
104
109
  *
105
110
  * certPemFile=your-cert-pem-file
106
111
  * certKeyFile=your-cert-key-file
112
+ * sendX5C=false
107
113
  *
108
114
  * FICClientId=your-FIC-client-id
109
115
  *
@@ -182,6 +188,7 @@ export const loadPrevAuthConfigFromEnv: () => AuthConfiguration = () => {
182
188
  clientSecret: process.env.MicrosoftAppPassword,
183
189
  certPemFile: process.env.certPemFile,
184
190
  certKeyFile: process.env.certKeyFile,
191
+ sendX5C: process.env.sendX5C === 'true',
185
192
  connectionName: process.env.connectionName,
186
193
  FICClientId: process.env.MicrosoftAppClientId,
187
194
  authority,
@@ -218,16 +225,18 @@ function loadConnectionsMapFromEnv () {
218
225
  const CONNECTIONS_PREFIX = 'connections__'
219
226
  const CONNECTIONS_MAP_PREFIX = 'connectionsMap__'
220
227
 
221
- for (const [key, value] of Object.entries(envVars)) {
228
+ for (const [key, rawValue] of Object.entries(envVars)) {
222
229
  if (key.startsWith(CONNECTIONS_PREFIX)) {
223
230
  // Convert to dot notation
224
231
  let path = key.substring(CONNECTIONS_PREFIX.length).replace(/__/g, '.')
225
232
  // Remove ".settings." from the path
226
233
  path = path.replace('.settings.', '.')
234
+ // Convert "true"/"false" strings into boolean values
235
+ const value = rawValue === 'true' ? true : rawValue === 'false' ? false : rawValue
227
236
  objectPath.set(connectionsObj, path, value)
228
237
  } else if (key.startsWith(CONNECTIONS_MAP_PREFIX)) {
229
238
  const path = key.substring(CONNECTIONS_MAP_PREFIX.length).replace(/__/g, '.')
230
- objectPath.set(connectionsMap, path, value)
239
+ objectPath.set(connectionsMap, path, rawValue)
231
240
  }
232
241
  }
233
242
 
@@ -274,6 +283,7 @@ function loadConnectionsMapFromEnv () {
274
283
  *
275
284
  * certPemFile=your-cert-pem-file
276
285
  * certKeyFile=your-cert-key-file
286
+ * sendX5C=false
277
287
  *
278
288
  * FICClientId=your-FIC-client-id
279
289
  *
@@ -335,6 +345,7 @@ function buildLegacyAuthConfig (envPrefix: string = '', customConfig?: AuthConfi
335
345
  clientSecret: customConfig?.clientSecret ?? process.env[`${prefix}clientSecret`],
336
346
  certPemFile: customConfig?.certPemFile ?? process.env[`${prefix}certPemFile`],
337
347
  certKeyFile: customConfig?.certKeyFile ?? process.env[`${prefix}certKeyFile`],
348
+ sendX5C: customConfig?.sendX5C ?? (process.env[`${prefix}sendX5C`] === 'true'),
338
349
  connectionName: customConfig?.connectionName ?? process.env[`${prefix}connectionName`],
339
350
  FICClientId: customConfig?.FICClientId ?? process.env[`${prefix}FICClientId`],
340
351
  authority,
@@ -9,13 +9,20 @@ import { AuthConfiguration } from './authConfiguration'
9
9
  * Represents an authentication provider.
10
10
  */
11
11
  export interface AuthProvider {
12
+ /**
13
+ * The AuthConfiguration used for token acquisition.
14
+ */
15
+ connectionSettings?: AuthConfiguration
16
+
12
17
  /**
13
18
  * Gets an access token for the specified authentication configuration and scope.
14
19
  * @param authConfig - The authentication configuration.
15
20
  * @param scope - The scope for which the access token is requested.
16
21
  * @returns A promise that resolves to the access token.
17
22
  */
18
- getAccessToken: (authConfig: AuthConfiguration, scope: string) => Promise<string>
23
+ getAccessToken (authConfig: AuthConfiguration, scope: string): Promise<string>
24
+ getAccessToken (scope: string): Promise<string>
25
+ getAccessToken (authConfigOrScope: AuthConfiguration | string, scope?: string): Promise<string>
19
26
 
20
27
  /**
21
28
  * Get an access token for the agentic application
@@ -10,6 +10,7 @@ import { AuthProvider } from './authProvider'
10
10
  import { debug } from '@microsoft/agents-activity/logger'
11
11
  import { v4 } from 'uuid'
12
12
  import { MemoryCache } from './MemoryCache'
13
+ import jwt from 'jsonwebtoken'
13
14
 
14
15
  import fs from 'fs'
15
16
  import crypto from 'crypto'
@@ -185,7 +186,7 @@ export class MsalTokenProvider implements AuthProvider {
185
186
  * @param tokenBodyParameters
186
187
  * @returns
187
188
  */
188
- private async acquireTokenByForAgenticScenarios (tenantId: string, clientId: string, clientAssertion: string | undefined, scopes: string[], tokenBodyParameters: { [key: string]: any }): Promise<string | null> {
189
+ private async acquireTokenForAgenticScenarios (tenantId: string, clientId: string, clientAssertion: string | undefined, scopes: string[], tokenBodyParameters: { [key: string]: any }): Promise<string | null> {
189
190
  if (!this.connectionSettings) {
190
191
  throw new Error('Connection settings must be provided when calling getAgenticInstanceToken')
191
192
  }
@@ -211,6 +212,10 @@ export class MsalTokenProvider implements AuthProvider {
211
212
  data.client_secret = this.connectionSettings.clientSecret
212
213
  }
213
214
 
215
+ if (data.grant_type !== 'user_fic') {
216
+ data.client_info = '2'
217
+ }
218
+
214
219
  const token = await axios.post(
215
220
  url,
216
221
  data,
@@ -234,7 +239,7 @@ export class MsalTokenProvider implements AuthProvider {
234
239
  const agentToken = await this.getAgenticApplicationToken(tenantId, agentAppInstanceId)
235
240
  const instanceToken = await this.getAgenticInstanceToken(tenantId, agentAppInstanceId)
236
241
 
237
- const token = await this.acquireTokenByForAgenticScenarios(tenantId, agentToken, instanceToken, scopes, {
242
+ const token = await this.acquireTokenForAgenticScenarios(tenantId, agentAppInstanceId, agentToken, scopes, {
238
243
  user_id: agenticUserId,
239
244
  user_federated_identity_credential: instanceToken,
240
245
  grant_type: 'user_fic',
@@ -252,7 +257,19 @@ export class MsalTokenProvider implements AuthProvider {
252
257
  throw new Error('Connection settings must be provided when calling getAgenticApplicationToken')
253
258
  }
254
259
  logger.debug('Getting agentic application token')
255
- const token = await this.acquireTokenByForAgenticScenarios(tenantId, this.connectionSettings.clientId, undefined, ['api://AzureAdTokenExchange/.default'], {
260
+
261
+ let clientAssertion
262
+
263
+ if (this.connectionSettings.WIDAssertionFile !== undefined) {
264
+ clientAssertion = fs.readFileSync(this.connectionSettings.WIDAssertionFile as string, 'utf8')
265
+ } else if (this.connectionSettings.FICClientId !== undefined) {
266
+ clientAssertion = await this.fetchExternalToken(this.connectionSettings.FICClientId as string)
267
+ } else if (this.connectionSettings.certPemFile !== undefined &&
268
+ this.connectionSettings.certKeyFile !== undefined) {
269
+ clientAssertion = this.getAssertionFromCert(this.connectionSettings)
270
+ }
271
+
272
+ const token = await this.acquireTokenForAgenticScenarios(tenantId, this.connectionSettings.clientId, clientAssertion, ['api://AzureAdTokenExchange/.default'], {
256
273
  grant_type: 'client_credentials',
257
274
  fmi_path: agentAppInstanceId,
258
275
  })
@@ -291,6 +308,48 @@ export class MsalTokenProvider implements AuthProvider {
291
308
  }
292
309
  }
293
310
 
311
+ /**
312
+ * Generates the client assertion using the provided certificate.
313
+ * @param authConfig The authentication configuration.
314
+ * @returns The client assertion.
315
+ */
316
+ private getAssertionFromCert (authConfig: AuthConfiguration): string {
317
+ const base64url = (buf: Buffer) =>
318
+ buf.toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
319
+
320
+ const privateKeyPem = fs.readFileSync(authConfig.certKeyFile as string)
321
+
322
+ const pubKeyObject = new crypto.X509Certificate(fs.readFileSync(authConfig.certPemFile as string))
323
+
324
+ const der = pubKeyObject.raw
325
+ const x5tS256 = base64url(crypto.createHash('sha256').update(der).digest())
326
+
327
+ let x5c
328
+ if (authConfig.sendX5C) {
329
+ x5c = Buffer.from(authConfig.certPemFile as string, 'base64').toString()
330
+ }
331
+
332
+ const now = Math.floor(Date.now() / 1000)
333
+ const payload = {
334
+ aud: `${this.resolveAuthority(authConfig.tenantId)}/oauth2/v2.0/token`,
335
+ iss: authConfig.clientId,
336
+ sub: authConfig.clientId,
337
+ jti: v4(),
338
+ nbf: now,
339
+ iat: now,
340
+ exp: now + 600, // 10 minutes
341
+ }
342
+
343
+ return jwt.sign(
344
+ payload,
345
+ privateKeyPem,
346
+ {
347
+ algorithm: 'PS256',
348
+ header: { alg: 'PS256', typ: 'JWT', 'x5t#S256': x5tS256, x5c }
349
+ }
350
+ )
351
+ }
352
+
294
353
  /**
295
354
  * Acquires a token using a user-assigned identity.
296
355
  * @param authConfig The authentication configuration.
@@ -13,19 +13,21 @@ import { AuthConfiguration, getAuthConfigWithDefaults } from './auth/authConfigu
13
13
  import { AuthProvider } from './auth/authProvider'
14
14
  import { ApxProductionScope } from './auth/authConstants'
15
15
  import { MsalConnectionManager } from './auth/msalConnectionManager'
16
- import { Activity, ActivityEventNames, ActivityTypes, Channels, ConversationReference, DeliveryModes, ConversationParameters, RoleTypes } from '@microsoft/agents-activity'
16
+ import { Activity, ActivityEventNames, ActivityTypes, Channels, ConversationReference, DeliveryModes, ConversationParameters, RoleTypes, ExceptionHelper } from '@microsoft/agents-activity'
17
+ import { Errors } from './errorHelper'
17
18
  import { ResourceResponse } from './connector-client/resourceResponse'
18
19
  import * as uuid from 'uuid'
19
20
  import { debug } from '@microsoft/agents-activity/logger'
20
21
  import { StatusCodes } from './statusCodes'
21
22
  import { InvokeResponse } from './invoke/invokeResponse'
22
- import { AttachmentInfo } from './connector-client/attachmentInfo'
23
23
  import { AttachmentData } from './connector-client/attachmentData'
24
+ import { AttachmentInfo } from './connector-client/attachmentInfo'
24
25
  import { normalizeIncomingActivity } from './activityWireCompat'
25
26
  import { UserTokenClient } from './oauth'
26
27
  import { HeaderPropagation, HeaderPropagationCollection, HeaderPropagationDefinition } from './headerPropagation'
27
28
  import { JwtPayload } from 'jsonwebtoken'
28
29
  import { getTokenServiceEndpoint } from './oauth/customUserTokenAPI'
30
+ import { Connections } from './auth/connections'
29
31
  const logger = debug('agents:cloud-adapter')
30
32
 
31
33
  /**
@@ -41,12 +43,13 @@ export class CloudAdapter extends BaseAdapter {
41
43
  /**
42
44
  * Client for connecting to the Azure Bot Service
43
45
  */
44
- connectionManager: MsalConnectionManager
46
+ connectionManager: Connections
45
47
 
46
48
  /**
47
49
  * Creates an instance of CloudAdapter.
48
- * @param authConfig - The authentication configuration for securing communications
49
- * @param authProvider - No longer used
50
+ * @param authConfig - The authentication configuration for securing communications.
51
+ * @param authProvider - No longer used.
52
+ * @param userTokenClient - No longer used.
50
53
  */
51
54
  constructor (authConfig?: AuthConfiguration, authProvider?: AuthProvider, userTokenClient?: UserTokenClient) {
52
55
  super()
@@ -84,10 +87,11 @@ export class CloudAdapter extends BaseAdapter {
84
87
  /**
85
88
  * Creates a connector client for a specific service URL and scope.
86
89
  *
87
- * @param serviceUrl - The URL of the service to connect to
88
- * @param scope - The authentication scope to use
89
- * @param headers - Optional headers to propagate in the request
90
- * @returns A promise that resolves to a ConnectorClient instance
90
+ * @param serviceUrl - The URL of the service to connect to.
91
+ * @param scope - The authentication scope to use.
92
+ * @param identity - The identity used to select the token provider.
93
+ * @param headers - Optional headers to propagate in the request.
94
+ * @returns A promise that resolves to a ConnectorClient instance.
91
95
  * @protected
92
96
  */
93
97
  protected async createConnectorClient (
@@ -107,6 +111,15 @@ export class CloudAdapter extends BaseAdapter {
107
111
  )
108
112
  }
109
113
 
114
+ /**
115
+ * Creates a connector client for a specific identity and activity.
116
+ *
117
+ * @param identity - The identity used to select the token provider.
118
+ * @param activity - The activity used to select the token provider.
119
+ * @param headers - Optional headers to propagate in the request.
120
+ * @returns A promise that resolves to a ConnectorClient instance.
121
+ * @protected
122
+ */
110
123
  protected async createConnectorClientWithIdentity (
111
124
  identity: JwtPayload,
112
125
  activity: Activity,
@@ -161,6 +174,11 @@ export class CloudAdapter extends BaseAdapter {
161
174
  return connectorClient
162
175
  }
163
176
 
177
+ /**
178
+ * Creates the JwtPayload object with the provided appId.
179
+ * @param appId The bot's appId.
180
+ * @returns The JwtPayload object containing the appId as aud.
181
+ */
164
182
  static createIdentity (appId: string) : JwtPayload {
165
183
  return {
166
184
  aud: appId
@@ -170,7 +188,7 @@ export class CloudAdapter extends BaseAdapter {
170
188
  /**
171
189
  * Sets the connector client on the turn context.
172
190
  *
173
- * @param context - The current turn context
191
+ * @param context - The current turn context.
174
192
  * @protected
175
193
  */
176
194
  protected setConnectorClient (
@@ -183,10 +201,12 @@ export class CloudAdapter extends BaseAdapter {
183
201
  /**
184
202
  * Creates a user token client for a specific service URL and scope.
185
203
  *
186
- * @param serviceUrl - The URL of the service to connect to
187
- * @param scope - The authentication scope to use
204
+ * @param identity - The identity used to select the token provider.
205
+ * @param tokenServiceEndpoint - The endpoint to connect to.
206
+ * @param scope - The authentication scope to use.
207
+ * @param audience - No longer used.
188
208
  * @param headers - Optional headers to propagate in the request
189
- * @returns A promise that resolves to a ConnectorClient instance
209
+ * @returns A promise that resolves to a UserTokenClient instance.
190
210
  * @protected
191
211
  */
192
212
  protected async createUserTokenClient (
@@ -220,7 +240,7 @@ export class CloudAdapter extends BaseAdapter {
220
240
  /**
221
241
  * Sets the user token client on the turn context.
222
242
  *
223
- * @param context - The current turn context
243
+ * @param context - The current turn context.
224
244
  * @protected
225
245
  */
226
246
  protected setUserTokenClient (
@@ -235,6 +255,7 @@ export class CloudAdapter extends BaseAdapter {
235
255
  * Creates a TurnContext for the given activity and logic.
236
256
  * @param activity - The activity to process.
237
257
  * @param logic - The logic to execute.
258
+ * @param identity - The identity used for the new context.
238
259
  * @returns The created TurnContext.
239
260
  */
240
261
  createTurnContext (activity: Activity, logic: AgentHandler, identity?: JwtPayload): TurnContext {
@@ -249,15 +270,15 @@ export class CloudAdapter extends BaseAdapter {
249
270
  */
250
271
  async sendActivities (context: TurnContext, activities: Activity[]): Promise<ResourceResponse[]> {
251
272
  if (!context) {
252
- throw new TypeError('`context` parameter required')
273
+ throw ExceptionHelper.generateException(TypeError, Errors.ContextParameterRequired)
253
274
  }
254
275
 
255
276
  if (!activities) {
256
- throw new TypeError('`activities` parameter required')
277
+ throw ExceptionHelper.generateException(TypeError, Errors.ActivitiesParameterRequired)
257
278
  }
258
279
 
259
280
  if (activities.length === 0) {
260
- throw new Error('Expecting one or more activities, but the array was empty.')
281
+ throw ExceptionHelper.generateException(Error, Errors.EmptyActivitiesArray)
261
282
  }
262
283
 
263
284
  const responses: ResourceResponse[] = []
@@ -271,7 +292,7 @@ export class CloudAdapter extends BaseAdapter {
271
292
  // no-op
272
293
  } else {
273
294
  if (!activity.serviceUrl || (activity.conversation == null) || !activity.conversation.id) {
274
- throw new Error('Invalid activity object')
295
+ throw ExceptionHelper.generateException(Error, Errors.InvalidActivityObject)
275
296
  }
276
297
 
277
298
  if (activity.replyToId) {
@@ -395,7 +416,7 @@ export class CloudAdapter extends BaseAdapter {
395
416
  }
396
417
 
397
418
  if (!activity.serviceUrl || (activity.conversation == null) || !activity.conversation.id || !activity.id) {
398
- throw new Error('Invalid activity object')
419
+ throw ExceptionHelper.generateException(Error, Errors.InvalidActivityObject)
399
420
  }
400
421
 
401
422
  const response = await context.turnState.get(this.ConnectorClientKey).updateActivity(
@@ -419,7 +440,7 @@ export class CloudAdapter extends BaseAdapter {
419
440
  }
420
441
 
421
442
  if (!reference || !reference.serviceUrl || (reference.conversation == null) || !reference.conversation.id || !reference.activityId) {
422
- throw new Error('Invalid conversation reference object')
443
+ throw ExceptionHelper.generateException(Error, Errors.InvalidConversationReference)
423
444
  }
424
445
 
425
446
  await context.turnState.get(this.ConnectorClientKey).deleteActivity(reference.conversation.id, reference.activityId)
@@ -427,8 +448,11 @@ export class CloudAdapter extends BaseAdapter {
427
448
 
428
449
  /**
429
450
  * Continues a conversation.
451
+ * @param botAppIdOrIdentity - The bot identity to use when continuing the conversation. This can be either:
452
+ * a string containing the bot's App ID (botId) or a JwtPayload object containing identity claims (must include aud).
430
453
  * @param reference - The conversation reference to continue.
431
454
  * @param logic - The logic to execute.
455
+ * @param isResponse - No longer used.
432
456
  * @returns A promise representing the completion of the continue operation.
433
457
  */
434
458
  async continueConversation (
@@ -437,7 +461,7 @@ export class CloudAdapter extends BaseAdapter {
437
461
  logic: (revocableContext: TurnContext) => Promise<void>,
438
462
  isResponse: Boolean = false): Promise<void> {
439
463
  if (!reference || !reference.serviceUrl || (reference.conversation == null) || !reference.conversation.id) {
440
- throw new Error('continueConversation: Invalid conversation reference object')
464
+ throw ExceptionHelper.generateException(Error, Errors.ContinueConversationInvalidReference)
441
465
  }
442
466
 
443
467
  if (!botAppIdOrIdentity) {
@@ -572,21 +596,22 @@ export class CloudAdapter extends BaseAdapter {
572
596
  /**
573
597
  * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
574
598
  * Uploads an attachment.
599
+ * @param context - The context for the turn.
575
600
  * @param conversationId - The conversation ID.
576
601
  * @param attachmentData - The attachment data.
577
602
  * @returns A promise representing the ResourceResponse for the uploaded attachment.
578
603
  */
579
604
  async uploadAttachment (context: TurnContext, conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
580
605
  if (context === undefined) {
581
- throw new Error('context is required')
606
+ throw ExceptionHelper.generateException(Error, Errors.ContextRequired)
582
607
  }
583
608
 
584
609
  if (conversationId === undefined) {
585
- throw new Error('conversationId is required')
610
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdRequired)
586
611
  }
587
612
 
588
613
  if (attachmentData === undefined) {
589
- throw new Error('attachmentData is required')
614
+ throw ExceptionHelper.generateException(Error, Errors.AttachmentDataRequired)
590
615
  }
591
616
 
592
617
  return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).uploadAttachment(conversationId, attachmentData)
@@ -595,16 +620,17 @@ export class CloudAdapter extends BaseAdapter {
595
620
  /**
596
621
  * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
597
622
  * Gets attachment information.
623
+ * @param context - The context for the turn.
598
624
  * @param attachmentId - The attachment ID.
599
625
  * @returns A promise representing the AttachmentInfo for the requested attachment.
600
626
  */
601
627
  async getAttachmentInfo (context: TurnContext, attachmentId: string): Promise<AttachmentInfo> {
602
628
  if (context === undefined) {
603
- throw new Error('context is required')
629
+ throw ExceptionHelper.generateException(Error, Errors.ContextRequired)
604
630
  }
605
631
 
606
632
  if (attachmentId === undefined) {
607
- throw new Error('attachmentId is required')
633
+ throw ExceptionHelper.generateException(Error, Errors.AttachmentIdRequired)
608
634
  }
609
635
 
610
636
  return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachmentInfo(attachmentId)
@@ -613,21 +639,22 @@ export class CloudAdapter extends BaseAdapter {
613
639
  /**
614
640
  * @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
615
641
  * Gets an attachment.
642
+ * @param context - The context for the turn.
616
643
  * @param attachmentId - The attachment ID.
617
644
  * @param viewId - The view ID.
618
645
  * @returns A promise representing the NodeJS.ReadableStream for the requested attachment.
619
646
  */
620
647
  async getAttachment (context: TurnContext, attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
621
648
  if (context === undefined) {
622
- throw new Error('context is required')
649
+ throw ExceptionHelper.generateException(Error, Errors.ContextRequired)
623
650
  }
624
651
 
625
652
  if (attachmentId === undefined) {
626
- throw new Error('attachmentId is required')
653
+ throw ExceptionHelper.generateException(Error, Errors.AttachmentIdRequired)
627
654
  }
628
655
 
629
656
  if (viewId === undefined) {
630
- throw new Error('viewId is required')
657
+ throw ExceptionHelper.generateException(Error, Errors.ViewIdRequired)
631
658
  }
632
659
 
633
660
  return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachment(attachmentId, viewId)
@@ -3,7 +3,8 @@ 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, RoleTypes, Channels } from '@microsoft/agents-activity'
6
+ import { Activity, ChannelAccount, ConversationParameters, RoleTypes, Channels, ExceptionHelper } from '@microsoft/agents-activity'
7
+ import { Errors } from '../errorHelper'
7
8
  import { ConversationsResult } from './conversationsResult'
8
9
  import { ConversationResourceResponse } from './conversationResourceResponse'
9
10
  import { ResourceResponse } from './resourceResponse'
@@ -143,7 +144,7 @@ export class ConnectorClient {
143
144
 
144
145
  public async getConversationMember (userId: string, conversationId: string): Promise<ChannelAccount> {
145
146
  if (!userId || !conversationId) {
146
- throw new Error('userId and conversationId are required')
147
+ throw ExceptionHelper.generateException(Error, Errors.UserIdAndConversationIdRequired)
147
148
  }
148
149
  const config: AxiosRequestConfig = {
149
150
  method: 'get',
@@ -192,7 +193,7 @@ export class ConnectorClient {
192
193
  ): Promise<ResourceResponse> {
193
194
  logger.debug(`Replying to activity: ${activityId} in conversation: ${conversationId}`)
194
195
  if (!conversationId || !activityId) {
195
- throw new Error('conversationId and activityId are required')
196
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdAndActivityIdRequired)
196
197
  }
197
198
 
198
199
  const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
@@ -242,7 +243,7 @@ export class ConnectorClient {
242
243
  ): Promise<ResourceResponse> {
243
244
  logger.debug(`Send to conversation: ${conversationId} activity: ${body.id}`)
244
245
  if (!conversationId) {
245
- throw new Error('conversationId is required')
246
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdRequired)
246
247
  }
247
248
 
248
249
  const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
@@ -272,7 +273,7 @@ export class ConnectorClient {
272
273
  body: Activity
273
274
  ): Promise<ResourceResponse> {
274
275
  if (!conversationId || !activityId) {
275
- throw new Error('conversationId and activityId are required')
276
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdAndActivityIdRequired)
276
277
  }
277
278
  const config: AxiosRequestConfig = {
278
279
  method: 'put',
@@ -297,7 +298,7 @@ export class ConnectorClient {
297
298
  activityId: string
298
299
  ): Promise<void> {
299
300
  if (!conversationId || !activityId) {
300
- throw new Error('conversationId and activityId are required')
301
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdAndActivityIdRequired)
301
302
  }
302
303
  const config: AxiosRequestConfig = {
303
304
  method: 'delete',
@@ -321,7 +322,7 @@ export class ConnectorClient {
321
322
  body: AttachmentData
322
323
  ): Promise<ResourceResponse> {
323
324
  if (conversationId === undefined) {
324
- throw new Error('conversationId is required')
325
+ throw ExceptionHelper.generateException(Error, Errors.ConversationIdRequired)
325
326
  }
326
327
  const config: AxiosRequestConfig = {
327
328
  method: 'post',
@@ -344,7 +345,7 @@ export class ConnectorClient {
344
345
  attachmentId: string
345
346
  ): Promise<AttachmentInfo> {
346
347
  if (attachmentId === undefined) {
347
- throw new Error('attachmentId is required')
348
+ throw ExceptionHelper.generateException(Error, Errors.AttachmentIdRequired)
348
349
  }
349
350
  const config: AxiosRequestConfig = {
350
351
  method: 'get',
@@ -368,10 +369,10 @@ export class ConnectorClient {
368
369
  viewId: string
369
370
  ): Promise<NodeJS.ReadableStream> {
370
371
  if (attachmentId === undefined) {
371
- throw new Error('attachmentId is required')
372
+ throw ExceptionHelper.generateException(Error, Errors.AttachmentIdRequired)
372
373
  }
373
374
  if (viewId === undefined) {
374
- throw new Error('viewId is required')
375
+ throw ExceptionHelper.generateException(Error, Errors.ViewIdRequired)
375
376
  }
376
377
  const config: AxiosRequestConfig = {
377
378
  method: 'get',