@microsoft/agents-hosting 1.1.0-alpha.9.g154c2c8a32 → 1.1.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.
- package/dist/package.json +10 -6
- package/dist/src/activityWireCompat.d.ts +1 -1
- package/dist/src/activityWireCompat.js +11 -3
- package/dist/src/activityWireCompat.js.map +1 -1
- package/dist/src/agent-client/agentClient.js +7 -3
- package/dist/src/agent-client/agentClient.js.map +1 -1
- package/dist/src/agent-client/agentResponseHandler.js +6 -2
- package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
- package/dist/src/app/agentApplication.d.ts +26 -11
- package/dist/src/app/agentApplication.js +90 -79
- package/dist/src/app/agentApplication.js.map +1 -1
- package/dist/src/app/agentApplicationBuilder.d.ts +2 -2
- package/dist/src/app/agentApplicationBuilder.js.map +1 -1
- package/dist/src/app/agentApplicationOptions.d.ts +9 -2
- package/dist/src/app/appRoute.d.ts +7 -0
- package/dist/src/app/{authorization.d.ts → auth/authorization.d.ts} +41 -139
- package/dist/src/app/auth/authorization.js +188 -0
- package/dist/src/app/auth/authorization.js.map +1 -0
- package/dist/src/app/auth/authorizationManager.d.ts +71 -0
- package/dist/src/app/auth/authorizationManager.js +170 -0
- package/dist/src/app/auth/authorizationManager.js.map +1 -0
- package/dist/src/app/auth/handlerStorage.d.ts +36 -0
- package/dist/src/app/auth/handlerStorage.js +62 -0
- package/dist/src/app/auth/handlerStorage.js.map +1 -0
- package/dist/src/app/auth/handlers/agenticAuthorization.d.ts +93 -0
- package/dist/src/app/auth/handlers/agenticAuthorization.js +134 -0
- package/dist/src/app/auth/handlers/agenticAuthorization.js.map +1 -0
- package/dist/src/app/auth/handlers/azureBotAuthorization.d.ts +226 -0
- package/dist/src/app/auth/handlers/azureBotAuthorization.js +429 -0
- package/dist/src/app/auth/handlers/azureBotAuthorization.js.map +1 -0
- package/dist/src/app/auth/handlers/index.d.ts +2 -0
- package/dist/src/app/auth/handlers/index.js +19 -0
- package/dist/src/app/auth/handlers/index.js.map +1 -0
- package/dist/src/app/auth/index.d.ts +2 -0
- package/dist/src/app/auth/index.js +19 -0
- package/dist/src/app/auth/index.js.map +1 -0
- package/dist/src/app/auth/types.d.ts +104 -0
- package/dist/src/app/auth/types.js +24 -0
- package/dist/src/app/auth/types.js.map +1 -0
- package/dist/src/app/index.d.ts +3 -3
- package/dist/src/app/index.js +2 -3
- package/dist/src/app/index.js.map +1 -1
- package/dist/src/app/routeList.d.ts +1 -1
- package/dist/src/app/routeList.js +22 -5
- package/dist/src/app/routeList.js.map +1 -1
- package/dist/src/app/streaming/streamingResponse.js +2 -1
- package/dist/src/app/streaming/streamingResponse.js.map +1 -1
- package/dist/src/auth/MemoryCache.d.ts +16 -0
- package/dist/src/auth/MemoryCache.js +58 -0
- package/dist/src/auth/MemoryCache.js.map +1 -0
- package/dist/src/auth/authConfiguration.d.ts +44 -2
- package/dist/src/auth/authConfiguration.js +209 -53
- package/dist/src/auth/authConfiguration.js.map +1 -1
- package/dist/src/auth/authConstants.d.ts +11 -0
- package/dist/src/auth/authConstants.js +15 -0
- package/dist/src/auth/authConstants.js.map +1 -0
- package/dist/src/auth/authProvider.d.ts +26 -0
- package/dist/src/auth/connections.d.ts +41 -0
- package/dist/src/auth/connections.js +7 -0
- package/dist/src/auth/connections.js.map +1 -0
- package/dist/src/auth/index.d.ts +2 -0
- package/dist/src/auth/index.js +2 -0
- package/dist/src/auth/index.js.map +1 -1
- package/dist/src/auth/jwt-middleware.js +31 -18
- package/dist/src/auth/jwt-middleware.js.map +1 -1
- package/dist/src/auth/msalConnectionManager.d.ts +64 -0
- package/dist/src/auth/msalConnectionManager.js +148 -0
- package/dist/src/auth/msalConnectionManager.js.map +1 -0
- package/dist/src/auth/msalTokenProvider.d.ts +38 -0
- package/dist/src/auth/msalTokenProvider.js +186 -16
- package/dist/src/auth/msalTokenProvider.js.map +1 -1
- package/dist/src/baseAdapter.d.ts +10 -25
- package/dist/src/baseAdapter.js +2 -15
- package/dist/src/baseAdapter.js.map +1 -1
- package/dist/src/cards/cardFactory.d.ts +2 -1
- package/dist/src/cards/cardFactory.js +3 -2
- package/dist/src/cards/cardFactory.js.map +1 -1
- package/dist/src/cloudAdapter.d.ts +40 -23
- package/dist/src/cloudAdapter.js +143 -63
- package/dist/src/cloudAdapter.js.map +1 -1
- package/dist/src/connector-client/connectorClient.d.ts +15 -0
- package/dist/src/connector-client/connectorClient.js +49 -15
- package/dist/src/connector-client/connectorClient.js.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauth/customUserTokenAPI.d.ts +1 -0
- package/dist/src/oauth/customUserTokenAPI.js +11 -0
- package/dist/src/oauth/customUserTokenAPI.js.map +1 -0
- package/dist/src/oauth/index.d.ts +0 -1
- package/dist/src/oauth/index.js +0 -1
- package/dist/src/oauth/index.js.map +1 -1
- package/dist/src/oauth/userTokenClient.d.ts +30 -13
- package/dist/src/oauth/userTokenClient.js +62 -26
- package/dist/src/oauth/userTokenClient.js.map +1 -1
- package/dist/src/oauth/userTokenClient.types.d.ts +19 -6
- package/dist/src/transcript/fileTranscriptLogger.d.ts +109 -0
- package/dist/src/transcript/fileTranscriptLogger.js +398 -0
- package/dist/src/transcript/fileTranscriptLogger.js.map +1 -0
- package/dist/src/turnContext.d.ts +7 -1
- package/dist/src/turnContext.js +11 -4
- package/dist/src/turnContext.js.map +1 -1
- package/package.json +10 -6
- package/src/activityWireCompat.ts +12 -4
- package/src/agent-client/agentClient.ts +9 -3
- package/src/agent-client/agentResponseHandler.ts +5 -2
- package/src/app/agentApplication.ts +95 -74
- package/src/app/agentApplicationBuilder.ts +2 -2
- package/src/app/agentApplicationOptions.ts +10 -2
- package/src/app/appRoute.ts +8 -0
- package/src/app/auth/authorization.ts +261 -0
- package/src/app/auth/authorizationManager.ts +213 -0
- package/src/app/auth/handlerStorage.ts +61 -0
- package/src/app/auth/handlers/agenticAuthorization.ts +183 -0
- package/src/app/auth/handlers/azureBotAuthorization.ts +606 -0
- package/src/app/auth/handlers/index.ts +2 -0
- package/src/app/auth/index.ts +2 -0
- package/src/app/auth/types.ts +111 -0
- package/src/app/index.ts +3 -3
- package/src/app/routeList.ts +24 -5
- package/src/app/streaming/streamingResponse.ts +2 -1
- package/src/auth/MemoryCache.ts +59 -0
- package/src/auth/authConfiguration.ts +245 -52
- package/src/auth/authConstants.ts +11 -0
- package/src/auth/authProvider.ts +34 -0
- package/src/auth/connections.ts +47 -0
- package/src/auth/index.ts +2 -0
- package/src/auth/jwt-middleware.ts +38 -21
- package/src/auth/msalConnectionManager.ts +175 -0
- package/src/auth/msalTokenProvider.ts +228 -9
- package/src/baseAdapter.ts +10 -29
- package/src/cards/cardFactory.ts +3 -2
- package/src/cloudAdapter.ts +207 -72
- package/src/connector-client/connectorClient.ts +59 -15
- package/src/index.ts +0 -1
- package/src/oauth/customUserTokenAPI.ts +5 -0
- package/src/oauth/index.ts +0 -1
- package/src/oauth/userTokenClient.ts +76 -22
- package/src/oauth/userTokenClient.types.ts +20 -8
- package/src/transcript/fileTranscriptLogger.ts +409 -0
- package/src/turnContext.ts +16 -5
- package/dist/src/app/authorization.js +0 -387
- package/dist/src/app/authorization.js.map +0 -1
- package/dist/src/claimsIdentity.d.ts +0 -35
- package/dist/src/claimsIdentity.js +0 -43
- package/dist/src/claimsIdentity.js.map +0 -1
- package/dist/src/oauth/oAuthFlow.d.ts +0 -119
- package/dist/src/oauth/oAuthFlow.js +0 -316
- package/dist/src/oauth/oAuthFlow.js.map +0 -1
- package/src/app/authorization.ts +0 -432
- package/src/claimsIdentity.ts +0 -47
- package/src/oauth/oAuthFlow.ts +0 -378
package/src/cloudAdapter.ts
CHANGED
|
@@ -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,
|
|
12
|
+
import { AuthConfiguration, getAuthConfigWithDefaults } from './auth/authConfiguration'
|
|
13
13
|
import { AuthProvider } from './auth/authProvider'
|
|
14
|
-
import {
|
|
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,34 +24,34 @@ 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'
|
|
26
|
-
|
|
27
|
+
import { JwtPayload } from 'jsonwebtoken'
|
|
28
|
+
import { getTokenServiceEndpoint } from './oauth/customUserTokenAPI'
|
|
27
29
|
const logger = debug('agents:cloud-adapter')
|
|
28
30
|
|
|
29
31
|
/**
|
|
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
|
|
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
|
|
42
|
+
* Client for connecting to the Azure Bot Service
|
|
41
43
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
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 -
|
|
49
|
+
* @param authProvider - No longer used
|
|
48
50
|
*/
|
|
49
51
|
constructor (authConfig?: AuthConfiguration, authProvider?: AuthProvider, userTokenClient?: UserTokenClient) {
|
|
50
52
|
super()
|
|
51
|
-
|
|
52
|
-
this.
|
|
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,80 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
92
93
|
protected async createConnectorClient (
|
|
93
94
|
serviceUrl: string,
|
|
94
95
|
scope: string,
|
|
96
|
+
identity: JwtPayload,
|
|
95
97
|
headers?: HeaderPropagationCollection
|
|
96
98
|
): Promise<ConnectorClient> {
|
|
97
|
-
|
|
99
|
+
// get the correct token provider
|
|
100
|
+
const tokenProvider = this.connectionManager.getTokenProvider(identity, serviceUrl)
|
|
101
|
+
|
|
102
|
+
const token = await tokenProvider.getAccessToken(scope)
|
|
103
|
+
return ConnectorClient.createClientWithToken(
|
|
98
104
|
serviceUrl,
|
|
99
|
-
|
|
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
|
+
headers?: HeaderPropagationCollection) {
|
|
114
|
+
if (!identity?.aud) {
|
|
115
|
+
// anonymous
|
|
116
|
+
return ConnectorClient.createClientWithToken(
|
|
117
|
+
activity.serviceUrl!,
|
|
118
|
+
null!,
|
|
119
|
+
headers
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let connectorClient
|
|
124
|
+
const tokenProvider = this.connectionManager.getTokenProviderFromActivity(identity, activity)
|
|
125
|
+
if (activity.isAgenticRequest()) {
|
|
126
|
+
logger.debug('Activity is from an agentic source, using special scope', activity.recipient)
|
|
127
|
+
const agenticInstanceId = activity.getAgenticInstanceId()
|
|
128
|
+
const agenticUserId = activity.getAgenticUser()
|
|
129
|
+
|
|
130
|
+
if (activity.recipient?.role?.toLowerCase() === RoleTypes.AgenticIdentity.toLowerCase() && agenticInstanceId) {
|
|
131
|
+
// get agentic instance token
|
|
132
|
+
const token = await tokenProvider.getAgenticInstanceToken(activity.getAgenticTenantId() ?? '', agenticInstanceId)
|
|
133
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
134
|
+
activity.serviceUrl!,
|
|
135
|
+
token,
|
|
136
|
+
headers
|
|
137
|
+
)
|
|
138
|
+
} else if (activity.recipient?.role?.toLowerCase() === RoleTypes.AgenticUser.toLowerCase() && agenticInstanceId && agenticUserId) {
|
|
139
|
+
const scope = tokenProvider.connectionSettings?.scope ?? ApxProductionScope
|
|
140
|
+
const token = await tokenProvider.getAgenticUserToken(activity.getAgenticTenantId() ?? '', agenticInstanceId, agenticUserId, [scope])
|
|
141
|
+
|
|
142
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
143
|
+
activity.serviceUrl!,
|
|
144
|
+
token,
|
|
145
|
+
headers
|
|
146
|
+
)
|
|
147
|
+
} else {
|
|
148
|
+
throw new Error('Could not create connector client for agentic user')
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
// ABS tokens will not have an azp/appid so use the botframework scope.
|
|
152
|
+
// Otherwise use the appId. This will happen when communicating back to another agent.
|
|
153
|
+
const scope = identity.azp ?? identity.appid ?? 'https://api.botframework.com'
|
|
154
|
+
const token = await tokenProvider.getAccessToken(scope)
|
|
155
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
156
|
+
activity.serviceUrl!,
|
|
157
|
+
token,
|
|
158
|
+
headers
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
return connectorClient
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static createIdentity (appId: string) : JwtPayload {
|
|
165
|
+
return {
|
|
166
|
+
aud: appId
|
|
167
|
+
} as JwtPayload
|
|
168
|
+
}
|
|
169
|
+
|
|
106
170
|
/**
|
|
107
171
|
* Sets the connector client on the turn context.
|
|
108
172
|
*
|
|
@@ -110,24 +174,71 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
110
174
|
* @protected
|
|
111
175
|
*/
|
|
112
176
|
protected setConnectorClient (
|
|
113
|
-
context: TurnContext
|
|
177
|
+
context: TurnContext,
|
|
178
|
+
connectorClient?: ConnectorClient
|
|
179
|
+
) {
|
|
180
|
+
context.turnState.set(this.ConnectorClientKey, connectorClient)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Creates a user token client for a specific service URL and scope.
|
|
185
|
+
*
|
|
186
|
+
* @param serviceUrl - The URL of the service to connect to
|
|
187
|
+
* @param scope - The authentication scope to use
|
|
188
|
+
* @param headers - Optional headers to propagate in the request
|
|
189
|
+
* @returns A promise that resolves to a ConnectorClient instance
|
|
190
|
+
* @protected
|
|
191
|
+
*/
|
|
192
|
+
protected async createUserTokenClient (
|
|
193
|
+
identity: JwtPayload,
|
|
194
|
+
tokenServiceEndpoint: string = getTokenServiceEndpoint(),
|
|
195
|
+
scope: string = 'https://api.botframework.com',
|
|
196
|
+
audience: string = 'https://api.botframework.com',
|
|
197
|
+
headers?: HeaderPropagationCollection
|
|
198
|
+
): Promise<UserTokenClient> {
|
|
199
|
+
if (!identity?.aud) {
|
|
200
|
+
// anonymous
|
|
201
|
+
return UserTokenClient.createClientWithScope(
|
|
202
|
+
tokenServiceEndpoint,
|
|
203
|
+
null!,
|
|
204
|
+
scope,
|
|
205
|
+
headers
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// get the correct token provider
|
|
210
|
+
const tokenProvider = this.connectionManager.getTokenProvider(identity, tokenServiceEndpoint)
|
|
211
|
+
|
|
212
|
+
return UserTokenClient.createClientWithScope(
|
|
213
|
+
tokenServiceEndpoint,
|
|
214
|
+
tokenProvider,
|
|
215
|
+
scope,
|
|
216
|
+
headers
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Sets the user token client on the turn context.
|
|
222
|
+
*
|
|
223
|
+
* @param context - The current turn context
|
|
224
|
+
* @protected
|
|
225
|
+
*/
|
|
226
|
+
protected setUserTokenClient (
|
|
227
|
+
context: TurnContext,
|
|
228
|
+
userTokenClient?: UserTokenClient
|
|
114
229
|
) {
|
|
115
|
-
context.turnState.set(
|
|
230
|
+
context.turnState.set(this.UserTokenClientKey, userTokenClient)
|
|
116
231
|
}
|
|
117
232
|
|
|
118
233
|
/**
|
|
234
|
+
* @deprecated This function will not be supported in future versions. Create TurnContext directly.
|
|
119
235
|
* Creates a TurnContext for the given activity and logic.
|
|
120
236
|
* @param activity - The activity to process.
|
|
121
237
|
* @param logic - The logic to execute.
|
|
122
238
|
* @returns The created TurnContext.
|
|
123
239
|
*/
|
|
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)
|
|
240
|
+
createTurnContext (activity: Activity, logic: AgentHandler, identity?: JwtPayload): TurnContext {
|
|
241
|
+
return new TurnContext(this, activity, identity)
|
|
131
242
|
}
|
|
132
243
|
|
|
133
244
|
/**
|
|
@@ -154,9 +265,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
154
265
|
delete activity.id
|
|
155
266
|
let response: ResourceResponse = { id: '' }
|
|
156
267
|
|
|
157
|
-
if (activity.type === ActivityTypes.
|
|
158
|
-
await setTimeout(() => { }, typeof activity.value === 'number' ? activity.value : 1000)
|
|
159
|
-
} else if (activity.type === ActivityTypes.InvokeResponse) {
|
|
268
|
+
if (activity.type === ActivityTypes.InvokeResponse) {
|
|
160
269
|
context.turnState.set(INVOKE_RESPONSE_KEY, activity)
|
|
161
270
|
} else if (activity.type === ActivityTypes.Trace && activity.channelId !== Channels.Emulator) {
|
|
162
271
|
// no-op
|
|
@@ -165,12 +274,10 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
165
274
|
throw new Error('Invalid activity object')
|
|
166
275
|
}
|
|
167
276
|
|
|
168
|
-
this.connectorClient = await this.createConnectorClient(activity.serviceUrl, 'https://api.botframework.com')
|
|
169
|
-
|
|
170
277
|
if (activity.replyToId) {
|
|
171
|
-
response = await this.
|
|
278
|
+
response = await context.turnState.get(this.ConnectorClientKey).replyToActivity(activity.conversation.id, activity.replyToId, activity)
|
|
172
279
|
} else {
|
|
173
|
-
response = await this.
|
|
280
|
+
response = await context.turnState.get(this.ConnectorClientKey).sendToConversation(activity.conversation.id, activity)
|
|
174
281
|
}
|
|
175
282
|
}
|
|
176
283
|
|
|
@@ -184,18 +291,6 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
184
291
|
return responses
|
|
185
292
|
}
|
|
186
293
|
|
|
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
294
|
/**
|
|
200
295
|
* Processes an incoming request and sends the response.
|
|
201
296
|
* @param request - The incoming request.
|
|
@@ -236,14 +331,17 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
236
331
|
}
|
|
237
332
|
|
|
238
333
|
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
334
|
|
|
335
|
+
const context = new TurnContext(this, activity, request.user!)
|
|
242
336
|
// if Delivery Mode == ExpectReplies, we don't need a connector client.
|
|
243
337
|
if (this.resolveIfConnectorClientIsNeeded(activity)) {
|
|
244
|
-
|
|
245
|
-
this.
|
|
246
|
-
|
|
338
|
+
const connectorClient = await this.createConnectorClientWithIdentity(request.user!, activity, headers)
|
|
339
|
+
this.setConnectorClient(context, connectorClient)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (!activity.isAgenticRequest()) {
|
|
343
|
+
const userTokenClient = await this.createUserTokenClient(request.user!)
|
|
344
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
247
345
|
}
|
|
248
346
|
|
|
249
347
|
if (
|
|
@@ -254,12 +352,11 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
254
352
|
await this.runMiddleware(context, logic)
|
|
255
353
|
const invokeResponse = this.processTurnResults(context)
|
|
256
354
|
logger.debug('Activity Response (invoke/expect replies): ', invokeResponse)
|
|
257
|
-
return end(invokeResponse?.status ?? StatusCodes.OK,
|
|
355
|
+
return end(invokeResponse?.status ?? StatusCodes.OK, invokeResponse?.body, true)
|
|
258
356
|
}
|
|
259
357
|
|
|
260
358
|
await this.runMiddleware(context, logic)
|
|
261
359
|
const invokeResponse = this.processTurnResults(context)
|
|
262
|
-
|
|
263
360
|
return end(invokeResponse?.status ?? StatusCodes.OK, invokeResponse?.body)
|
|
264
361
|
}
|
|
265
362
|
|
|
@@ -301,7 +398,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
301
398
|
throw new Error('Invalid activity object')
|
|
302
399
|
}
|
|
303
400
|
|
|
304
|
-
const response = await this.
|
|
401
|
+
const response = await context.turnState.get(this.ConnectorClientKey).updateActivity(
|
|
305
402
|
activity.conversation.id,
|
|
306
403
|
activity.id,
|
|
307
404
|
activity
|
|
@@ -325,7 +422,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
325
422
|
throw new Error('Invalid conversation reference object')
|
|
326
423
|
}
|
|
327
424
|
|
|
328
|
-
await this.
|
|
425
|
+
await context.turnState.get(this.ConnectorClientKey).deleteActivity(reference.conversation.id, reference.activityId)
|
|
329
426
|
}
|
|
330
427
|
|
|
331
428
|
/**
|
|
@@ -334,25 +431,44 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
334
431
|
* @param logic - The logic to execute.
|
|
335
432
|
* @returns A promise representing the completion of the continue operation.
|
|
336
433
|
*/
|
|
337
|
-
async continueConversation (
|
|
434
|
+
async continueConversation (
|
|
435
|
+
botAppIdOrIdentity: string | JwtPayload,
|
|
436
|
+
reference: ConversationReference,
|
|
437
|
+
logic: (revocableContext: TurnContext) => Promise<void>,
|
|
438
|
+
isResponse: Boolean = false): Promise<void> {
|
|
338
439
|
if (!reference || !reference.serviceUrl || (reference.conversation == null) || !reference.conversation.id) {
|
|
339
|
-
throw new Error('Invalid conversation reference object')
|
|
440
|
+
throw new Error('continueConversation: Invalid conversation reference object')
|
|
340
441
|
}
|
|
341
442
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
443
|
+
if (!botAppIdOrIdentity) {
|
|
444
|
+
throw new TypeError('continueConversation: botAppIdOrIdentity is required')
|
|
445
|
+
}
|
|
446
|
+
const botAppId = typeof botAppIdOrIdentity === 'string' ? botAppIdOrIdentity : botAppIdOrIdentity.aud as string
|
|
447
|
+
|
|
448
|
+
// Only having the botId will only work against ABS or Agentic. Proactive to other agents will
|
|
449
|
+
// not work with just botId. Use a JwtPayload with property aud (which is botId) and appid populated.
|
|
450
|
+
const identity =
|
|
451
|
+
typeof botAppIdOrIdentity !== 'string'
|
|
452
|
+
? botAppIdOrIdentity
|
|
453
|
+
: CloudAdapter.createIdentity(botAppId)
|
|
454
|
+
|
|
455
|
+
const context = new TurnContext(this, Activity.getContinuationActivity(reference), identity)
|
|
456
|
+
const connectorClient = await this.createConnectorClientWithIdentity(identity, context.activity)
|
|
457
|
+
this.setConnectorClient(context, connectorClient)
|
|
458
|
+
|
|
459
|
+
if (!context.activity.isAgenticRequest()) {
|
|
460
|
+
const userTokenClient = await this.createUserTokenClient(identity)
|
|
461
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
347
462
|
}
|
|
463
|
+
|
|
348
464
|
await this.runMiddleware(context, logic)
|
|
349
465
|
}
|
|
350
466
|
|
|
351
467
|
/**
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
468
|
+
* Processes the turn results and returns an InvokeResponse if applicable.
|
|
469
|
+
* @param context - The TurnContext for the current turn.
|
|
470
|
+
* @returns The InvokeResponse if applicable, otherwise undefined.
|
|
471
|
+
*/
|
|
356
472
|
protected processTurnResults (context: TurnContext): InvokeResponse | undefined {
|
|
357
473
|
logger.info('<--Sending back turn results')
|
|
358
474
|
// Handle ExpectedReplies scenarios where all activities have been buffered and sent back at once in an invoke response.
|
|
@@ -437,7 +553,9 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
437
553
|
if (!conversationParameters) throw new TypeError('`conversationParameters` must be defined')
|
|
438
554
|
if (!logic) throw new TypeError('`logic` must be defined')
|
|
439
555
|
|
|
440
|
-
const
|
|
556
|
+
const identity = CloudAdapter.createIdentity(audience)
|
|
557
|
+
const restClient = await this.createConnectorClient(serviceUrl, audience, identity)
|
|
558
|
+
const userTokenClient = await this.createUserTokenClient(identity)
|
|
441
559
|
const createConversationResult = await restClient.createConversation(conversationParameters)
|
|
442
560
|
const createActivity = this.createCreateActivity(
|
|
443
561
|
createConversationResult.id,
|
|
@@ -445,17 +563,24 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
445
563
|
serviceUrl,
|
|
446
564
|
conversationParameters
|
|
447
565
|
)
|
|
448
|
-
const context = new TurnContext(this, createActivity)
|
|
566
|
+
const context = new TurnContext(this, createActivity, CloudAdapter.createIdentity(agentAppId))
|
|
567
|
+
this.setConnectorClient(context, restClient)
|
|
568
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
449
569
|
await this.runMiddleware(context, logic)
|
|
450
570
|
}
|
|
451
571
|
|
|
452
572
|
/**
|
|
573
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
453
574
|
* Uploads an attachment.
|
|
454
575
|
* @param conversationId - The conversation ID.
|
|
455
576
|
* @param attachmentData - The attachment data.
|
|
456
577
|
* @returns A promise representing the ResourceResponse for the uploaded attachment.
|
|
457
578
|
*/
|
|
458
|
-
async uploadAttachment (conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
|
|
579
|
+
async uploadAttachment (context: TurnContext, conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
|
|
580
|
+
if (context === undefined) {
|
|
581
|
+
throw new Error('context is required')
|
|
582
|
+
}
|
|
583
|
+
|
|
459
584
|
if (conversationId === undefined) {
|
|
460
585
|
throw new Error('conversationId is required')
|
|
461
586
|
}
|
|
@@ -464,29 +589,39 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
464
589
|
throw new Error('attachmentData is required')
|
|
465
590
|
}
|
|
466
591
|
|
|
467
|
-
return await this.
|
|
592
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).uploadAttachment(conversationId, attachmentData)
|
|
468
593
|
}
|
|
469
594
|
|
|
470
595
|
/**
|
|
596
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
471
597
|
* Gets attachment information.
|
|
472
598
|
* @param attachmentId - The attachment ID.
|
|
473
599
|
* @returns A promise representing the AttachmentInfo for the requested attachment.
|
|
474
600
|
*/
|
|
475
|
-
async getAttachmentInfo (attachmentId: string): Promise<AttachmentInfo> {
|
|
601
|
+
async getAttachmentInfo (context: TurnContext, attachmentId: string): Promise<AttachmentInfo> {
|
|
602
|
+
if (context === undefined) {
|
|
603
|
+
throw new Error('context is required')
|
|
604
|
+
}
|
|
605
|
+
|
|
476
606
|
if (attachmentId === undefined) {
|
|
477
607
|
throw new Error('attachmentId is required')
|
|
478
608
|
}
|
|
479
609
|
|
|
480
|
-
return await this.
|
|
610
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachmentInfo(attachmentId)
|
|
481
611
|
}
|
|
482
612
|
|
|
483
613
|
/**
|
|
614
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
484
615
|
* Gets an attachment.
|
|
485
616
|
* @param attachmentId - The attachment ID.
|
|
486
617
|
* @param viewId - The view ID.
|
|
487
618
|
* @returns A promise representing the NodeJS.ReadableStream for the requested attachment.
|
|
488
619
|
*/
|
|
489
|
-
async getAttachment (attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
|
|
620
|
+
async getAttachment (context: TurnContext, attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
|
|
621
|
+
if (context === undefined) {
|
|
622
|
+
throw new Error('context is required')
|
|
623
|
+
}
|
|
624
|
+
|
|
490
625
|
if (attachmentId === undefined) {
|
|
491
626
|
throw new Error('attachmentId is required')
|
|
492
627
|
}
|
|
@@ -495,6 +630,6 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
495
630
|
throw new Error('viewId is required')
|
|
496
631
|
}
|
|
497
632
|
|
|
498
|
-
return await this.
|
|
633
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachment(attachmentId, viewId)
|
|
499
634
|
}
|
|
500
635
|
}
|
|
@@ -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,23 +91,38 @@ 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({
|
|
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,
|
|
100
119
|
headers: headerPropagation.outgoing,
|
|
101
|
-
transformRequest: [
|
|
102
|
-
(data, headers) => {
|
|
103
|
-
return JSON.stringify(normalizeOutgoingActivity(data))
|
|
104
|
-
}]
|
|
105
120
|
})
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
if (token.length > 1) {
|
|
122
|
+
if (token && token.length > 1) {
|
|
109
123
|
axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`
|
|
110
124
|
}
|
|
125
|
+
|
|
111
126
|
return new ConnectorClient(axiosInstance)
|
|
112
127
|
}
|
|
113
128
|
|
|
@@ -147,14 +162,17 @@ export class ConnectorClient {
|
|
|
147
162
|
* @returns The conversation resource response.
|
|
148
163
|
*/
|
|
149
164
|
public async createConversation (body: ConversationParameters): Promise<ConversationResourceResponse> {
|
|
150
|
-
|
|
165
|
+
const payload = {
|
|
166
|
+
...body,
|
|
167
|
+
activity: normalizeOutgoingActivity(body.activity)
|
|
168
|
+
}
|
|
151
169
|
const config: AxiosRequestConfig = {
|
|
152
170
|
method: 'post',
|
|
153
171
|
url: '/v3/conversations',
|
|
154
172
|
headers: {
|
|
155
173
|
'Content-Type': 'application/json'
|
|
156
174
|
},
|
|
157
|
-
data:
|
|
175
|
+
data: payload
|
|
158
176
|
}
|
|
159
177
|
const response: AxiosResponse = await this._axiosInstance(config)
|
|
160
178
|
return response.data
|
|
@@ -176,19 +194,42 @@ export class ConnectorClient {
|
|
|
176
194
|
if (!conversationId || !activityId) {
|
|
177
195
|
throw new Error('conversationId and activityId are required')
|
|
178
196
|
}
|
|
197
|
+
|
|
198
|
+
const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
|
|
199
|
+
|
|
179
200
|
const config: AxiosRequestConfig = {
|
|
180
201
|
method: 'post',
|
|
181
|
-
url: `v3/conversations/${
|
|
202
|
+
url: `v3/conversations/${trimmedConversationId}/activities/${encodeURIComponent(activityId)}`,
|
|
182
203
|
headers: {
|
|
183
204
|
'Content-Type': 'application/json'
|
|
184
205
|
},
|
|
185
|
-
data: body
|
|
206
|
+
data: normalizeOutgoingActivity(body)
|
|
186
207
|
}
|
|
187
208
|
const response = await this._axiosInstance(config)
|
|
188
209
|
logger.info('Reply to conversation/activity: ', response.data.id!, activityId)
|
|
189
210
|
return response.data
|
|
190
211
|
}
|
|
191
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Trim the conversationId to a fixed length when creating the URL. This is applied only in specific API calls for agentic calls.
|
|
215
|
+
* @param conversationId The ID of the conversation to potentially truncate.
|
|
216
|
+
* @param activity The activity object used to determine if truncation is necessary.
|
|
217
|
+
* @returns The original or truncated conversationId, depending on the channel and activity role.
|
|
218
|
+
*/
|
|
219
|
+
private conditionallyTruncateConversationId (conversationId: string, activity: Activity): string {
|
|
220
|
+
if (
|
|
221
|
+
(activity.channelIdChannel === Channels.Msteams || activity.channelIdChannel === Channels.Agents) &&
|
|
222
|
+
(activity.from?.role === RoleTypes.AgenticIdentity || activity.from?.role === RoleTypes.AgenticUser)) {
|
|
223
|
+
let maxLength = 150
|
|
224
|
+
if (process.env.MAX_APX_CONVERSATION_ID_LENGTH && !isNaN(parseInt(process.env.MAX_APX_CONVERSATION_ID_LENGTH, 10))) {
|
|
225
|
+
maxLength = parseInt(process.env.MAX_APX_CONVERSATION_ID_LENGTH, 10)
|
|
226
|
+
}
|
|
227
|
+
return conversationId.length > maxLength ? conversationId.substring(0, maxLength) : conversationId
|
|
228
|
+
} else {
|
|
229
|
+
return conversationId
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
192
233
|
/**
|
|
193
234
|
* Sends an activity to a conversation.
|
|
194
235
|
* @param conversationId - The ID of the conversation.
|
|
@@ -203,13 +244,16 @@ export class ConnectorClient {
|
|
|
203
244
|
if (!conversationId) {
|
|
204
245
|
throw new Error('conversationId is required')
|
|
205
246
|
}
|
|
247
|
+
|
|
248
|
+
const trimmedConversationId: string = this.conditionallyTruncateConversationId(conversationId, body)
|
|
249
|
+
|
|
206
250
|
const config: AxiosRequestConfig = {
|
|
207
251
|
method: 'post',
|
|
208
|
-
url: `v3/conversations/${
|
|
252
|
+
url: `v3/conversations/${trimmedConversationId}/activities`,
|
|
209
253
|
headers: {
|
|
210
254
|
'Content-Type': 'application/json'
|
|
211
255
|
},
|
|
212
|
-
data: body
|
|
256
|
+
data: normalizeOutgoingActivity(body)
|
|
213
257
|
}
|
|
214
258
|
const response = await this._axiosInstance(config)
|
|
215
259
|
return response.data
|
|
@@ -236,7 +280,7 @@ export class ConnectorClient {
|
|
|
236
280
|
headers: {
|
|
237
281
|
'Content-Type': 'application/json'
|
|
238
282
|
},
|
|
239
|
-
data: body
|
|
283
|
+
data: normalizeOutgoingActivity(body)
|
|
240
284
|
}
|
|
241
285
|
const response = await this._axiosInstance(config)
|
|
242
286
|
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'
|
package/src/oauth/index.ts
CHANGED