@microsoft/agents-hosting 1.1.0-alpha.8.g2362542eea → 1.1.0-alpha.85
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 +222 -0
- package/dist/src/app/auth/handlers/azureBotAuthorization.js +428 -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 +40 -2
- package/dist/src/auth/authConfiguration.js +209 -55
- 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 +23 -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 +24 -0
- package/dist/src/auth/msalTokenProvider.js +143 -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/cloudAdapter.d.ts +40 -23
- package/dist/src/cloudAdapter.js +141 -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/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 +182 -0
- package/src/app/auth/handlers/azureBotAuthorization.ts +599 -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 +239 -53
- package/src/auth/authConstants.ts +11 -0
- package/src/auth/authProvider.ts +31 -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 +185 -9
- package/src/baseAdapter.ts +10 -29
- package/src/cloudAdapter.ts +205 -71
- 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/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,79 @@ 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
|
+
|
|
128
|
+
if (activity.recipient?.role === RoleTypes.AgenticIdentity && activity.getAgenticInstanceId()) {
|
|
129
|
+
// get agentic instance token
|
|
130
|
+
const token = await tokenProvider.getAgenticInstanceToken(activity.getAgenticInstanceId() ?? '')
|
|
131
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
132
|
+
activity.serviceUrl!,
|
|
133
|
+
token,
|
|
134
|
+
headers
|
|
135
|
+
)
|
|
136
|
+
} else if (activity.recipient?.role === RoleTypes.AgenticUser && activity.getAgenticInstanceId() && activity.getAgenticUser()) {
|
|
137
|
+
const scope = tokenProvider.connectionSettings?.scope ?? ApxProductionScope
|
|
138
|
+
const token = await tokenProvider.getAgenticUserToken(activity.getAgenticInstanceId() ?? '', activity.getAgenticUser() ?? '', [scope])
|
|
139
|
+
|
|
140
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
141
|
+
activity.serviceUrl!,
|
|
142
|
+
token,
|
|
143
|
+
headers
|
|
144
|
+
)
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error('Could not create connector client for agentic user')
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
// ABS tokens will not have an azp/appid so use the botframework scope.
|
|
150
|
+
// Otherwise use the appId. This will happen when communicating back to another agent.
|
|
151
|
+
const scope = identity.azp ?? identity.appid ?? 'https://api.botframework.com'
|
|
152
|
+
const token = await tokenProvider.getAccessToken(scope)
|
|
153
|
+
connectorClient = ConnectorClient.createClientWithToken(
|
|
154
|
+
activity.serviceUrl!,
|
|
155
|
+
token,
|
|
156
|
+
headers
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return connectorClient
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
static createIdentity (appId: string) : JwtPayload {
|
|
164
|
+
return {
|
|
165
|
+
aud: appId
|
|
166
|
+
} as JwtPayload
|
|
167
|
+
}
|
|
168
|
+
|
|
106
169
|
/**
|
|
107
170
|
* Sets the connector client on the turn context.
|
|
108
171
|
*
|
|
@@ -110,24 +173,71 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
110
173
|
* @protected
|
|
111
174
|
*/
|
|
112
175
|
protected setConnectorClient (
|
|
113
|
-
context: TurnContext
|
|
176
|
+
context: TurnContext,
|
|
177
|
+
connectorClient?: ConnectorClient
|
|
178
|
+
) {
|
|
179
|
+
context.turnState.set(this.ConnectorClientKey, connectorClient)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Creates a user token client for a specific service URL and scope.
|
|
184
|
+
*
|
|
185
|
+
* @param serviceUrl - The URL of the service to connect to
|
|
186
|
+
* @param scope - The authentication scope to use
|
|
187
|
+
* @param headers - Optional headers to propagate in the request
|
|
188
|
+
* @returns A promise that resolves to a ConnectorClient instance
|
|
189
|
+
* @protected
|
|
190
|
+
*/
|
|
191
|
+
protected async createUserTokenClient (
|
|
192
|
+
identity: JwtPayload,
|
|
193
|
+
tokenServiceEndpoint: string = getTokenServiceEndpoint(),
|
|
194
|
+
scope: string = 'https://api.botframework.com',
|
|
195
|
+
audience: string = 'https://api.botframework.com',
|
|
196
|
+
headers?: HeaderPropagationCollection
|
|
197
|
+
): Promise<UserTokenClient> {
|
|
198
|
+
if (!identity?.aud) {
|
|
199
|
+
// anonymous
|
|
200
|
+
return UserTokenClient.createClientWithScope(
|
|
201
|
+
tokenServiceEndpoint,
|
|
202
|
+
null!,
|
|
203
|
+
scope,
|
|
204
|
+
headers
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// get the correct token provider
|
|
209
|
+
const tokenProvider = this.connectionManager.getTokenProvider(identity, tokenServiceEndpoint)
|
|
210
|
+
|
|
211
|
+
return UserTokenClient.createClientWithScope(
|
|
212
|
+
tokenServiceEndpoint,
|
|
213
|
+
tokenProvider,
|
|
214
|
+
scope,
|
|
215
|
+
headers
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Sets the user token client on the turn context.
|
|
221
|
+
*
|
|
222
|
+
* @param context - The current turn context
|
|
223
|
+
* @protected
|
|
224
|
+
*/
|
|
225
|
+
protected setUserTokenClient (
|
|
226
|
+
context: TurnContext,
|
|
227
|
+
userTokenClient?: UserTokenClient
|
|
114
228
|
) {
|
|
115
|
-
context.turnState.set(
|
|
229
|
+
context.turnState.set(this.UserTokenClientKey, userTokenClient)
|
|
116
230
|
}
|
|
117
231
|
|
|
118
232
|
/**
|
|
233
|
+
* @deprecated This function will not be supported in future versions. Create TurnContext directly.
|
|
119
234
|
* Creates a TurnContext for the given activity and logic.
|
|
120
235
|
* @param activity - The activity to process.
|
|
121
236
|
* @param logic - The logic to execute.
|
|
122
237
|
* @returns The created TurnContext.
|
|
123
238
|
*/
|
|
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)
|
|
239
|
+
createTurnContext (activity: Activity, logic: AgentHandler, identity?: JwtPayload): TurnContext {
|
|
240
|
+
return new TurnContext(this, activity, identity)
|
|
131
241
|
}
|
|
132
242
|
|
|
133
243
|
/**
|
|
@@ -154,9 +264,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
154
264
|
delete activity.id
|
|
155
265
|
let response: ResourceResponse = { id: '' }
|
|
156
266
|
|
|
157
|
-
if (activity.type === ActivityTypes.
|
|
158
|
-
await setTimeout(() => { }, typeof activity.value === 'number' ? activity.value : 1000)
|
|
159
|
-
} else if (activity.type === ActivityTypes.InvokeResponse) {
|
|
267
|
+
if (activity.type === ActivityTypes.InvokeResponse) {
|
|
160
268
|
context.turnState.set(INVOKE_RESPONSE_KEY, activity)
|
|
161
269
|
} else if (activity.type === ActivityTypes.Trace && activity.channelId !== Channels.Emulator) {
|
|
162
270
|
// no-op
|
|
@@ -165,12 +273,10 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
165
273
|
throw new Error('Invalid activity object')
|
|
166
274
|
}
|
|
167
275
|
|
|
168
|
-
this.connectorClient = await this.createConnectorClient(activity.serviceUrl, 'https://api.botframework.com')
|
|
169
|
-
|
|
170
276
|
if (activity.replyToId) {
|
|
171
|
-
response = await this.
|
|
277
|
+
response = await context.turnState.get(this.ConnectorClientKey).replyToActivity(activity.conversation.id, activity.replyToId, activity)
|
|
172
278
|
} else {
|
|
173
|
-
response = await this.
|
|
279
|
+
response = await context.turnState.get(this.ConnectorClientKey).sendToConversation(activity.conversation.id, activity)
|
|
174
280
|
}
|
|
175
281
|
}
|
|
176
282
|
|
|
@@ -184,18 +290,6 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
184
290
|
return responses
|
|
185
291
|
}
|
|
186
292
|
|
|
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
293
|
/**
|
|
200
294
|
* Processes an incoming request and sends the response.
|
|
201
295
|
* @param request - The incoming request.
|
|
@@ -236,14 +330,17 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
236
330
|
}
|
|
237
331
|
|
|
238
332
|
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
333
|
|
|
334
|
+
const context = new TurnContext(this, activity, request.user!)
|
|
242
335
|
// if Delivery Mode == ExpectReplies, we don't need a connector client.
|
|
243
336
|
if (this.resolveIfConnectorClientIsNeeded(activity)) {
|
|
244
|
-
|
|
245
|
-
this.
|
|
246
|
-
|
|
337
|
+
const connectorClient = await this.createConnectorClientWithIdentity(request.user!, activity, headers)
|
|
338
|
+
this.setConnectorClient(context, connectorClient)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!activity.isAgenticRequest()) {
|
|
342
|
+
const userTokenClient = await this.createUserTokenClient(request.user!)
|
|
343
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
247
344
|
}
|
|
248
345
|
|
|
249
346
|
if (
|
|
@@ -259,7 +356,6 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
259
356
|
|
|
260
357
|
await this.runMiddleware(context, logic)
|
|
261
358
|
const invokeResponse = this.processTurnResults(context)
|
|
262
|
-
|
|
263
359
|
return end(invokeResponse?.status ?? StatusCodes.OK, invokeResponse?.body)
|
|
264
360
|
}
|
|
265
361
|
|
|
@@ -301,7 +397,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
301
397
|
throw new Error('Invalid activity object')
|
|
302
398
|
}
|
|
303
399
|
|
|
304
|
-
const response = await this.
|
|
400
|
+
const response = await context.turnState.get(this.ConnectorClientKey).updateActivity(
|
|
305
401
|
activity.conversation.id,
|
|
306
402
|
activity.id,
|
|
307
403
|
activity
|
|
@@ -325,7 +421,7 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
325
421
|
throw new Error('Invalid conversation reference object')
|
|
326
422
|
}
|
|
327
423
|
|
|
328
|
-
await this.
|
|
424
|
+
await context.turnState.get(this.ConnectorClientKey).deleteActivity(reference.conversation.id, reference.activityId)
|
|
329
425
|
}
|
|
330
426
|
|
|
331
427
|
/**
|
|
@@ -334,25 +430,44 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
334
430
|
* @param logic - The logic to execute.
|
|
335
431
|
* @returns A promise representing the completion of the continue operation.
|
|
336
432
|
*/
|
|
337
|
-
async continueConversation (
|
|
433
|
+
async continueConversation (
|
|
434
|
+
botAppIdOrIdentity: string | JwtPayload,
|
|
435
|
+
reference: ConversationReference,
|
|
436
|
+
logic: (revocableContext: TurnContext) => Promise<void>,
|
|
437
|
+
isResponse: Boolean = false): Promise<void> {
|
|
338
438
|
if (!reference || !reference.serviceUrl || (reference.conversation == null) || !reference.conversation.id) {
|
|
339
|
-
throw new Error('Invalid conversation reference object')
|
|
439
|
+
throw new Error('continueConversation: Invalid conversation reference object')
|
|
340
440
|
}
|
|
341
441
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
442
|
+
if (!botAppIdOrIdentity) {
|
|
443
|
+
throw new TypeError('continueConversation: botAppIdOrIdentity is required')
|
|
444
|
+
}
|
|
445
|
+
const botAppId = typeof botAppIdOrIdentity === 'string' ? botAppIdOrIdentity : botAppIdOrIdentity.aud as string
|
|
446
|
+
|
|
447
|
+
// Only having the botId will only work against ABS or Agentic. Proactive to other agents will
|
|
448
|
+
// not work with just botId. Use a JwtPayload with property aud (which is botId) and appid populated.
|
|
449
|
+
const identity =
|
|
450
|
+
typeof botAppIdOrIdentity !== 'string'
|
|
451
|
+
? botAppIdOrIdentity
|
|
452
|
+
: CloudAdapter.createIdentity(botAppId)
|
|
453
|
+
|
|
454
|
+
const context = new TurnContext(this, Activity.getContinuationActivity(reference), identity)
|
|
455
|
+
const connectorClient = await this.createConnectorClientWithIdentity(identity, context.activity)
|
|
456
|
+
this.setConnectorClient(context, connectorClient)
|
|
457
|
+
|
|
458
|
+
if (!context.activity.isAgenticRequest()) {
|
|
459
|
+
const userTokenClient = await this.createUserTokenClient(identity)
|
|
460
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
347
461
|
}
|
|
462
|
+
|
|
348
463
|
await this.runMiddleware(context, logic)
|
|
349
464
|
}
|
|
350
465
|
|
|
351
466
|
/**
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
467
|
+
* Processes the turn results and returns an InvokeResponse if applicable.
|
|
468
|
+
* @param context - The TurnContext for the current turn.
|
|
469
|
+
* @returns The InvokeResponse if applicable, otherwise undefined.
|
|
470
|
+
*/
|
|
356
471
|
protected processTurnResults (context: TurnContext): InvokeResponse | undefined {
|
|
357
472
|
logger.info('<--Sending back turn results')
|
|
358
473
|
// Handle ExpectedReplies scenarios where all activities have been buffered and sent back at once in an invoke response.
|
|
@@ -437,7 +552,9 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
437
552
|
if (!conversationParameters) throw new TypeError('`conversationParameters` must be defined')
|
|
438
553
|
if (!logic) throw new TypeError('`logic` must be defined')
|
|
439
554
|
|
|
440
|
-
const
|
|
555
|
+
const identity = CloudAdapter.createIdentity(audience)
|
|
556
|
+
const restClient = await this.createConnectorClient(serviceUrl, audience, identity)
|
|
557
|
+
const userTokenClient = await this.createUserTokenClient(identity)
|
|
441
558
|
const createConversationResult = await restClient.createConversation(conversationParameters)
|
|
442
559
|
const createActivity = this.createCreateActivity(
|
|
443
560
|
createConversationResult.id,
|
|
@@ -445,17 +562,24 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
445
562
|
serviceUrl,
|
|
446
563
|
conversationParameters
|
|
447
564
|
)
|
|
448
|
-
const context = new TurnContext(this, createActivity)
|
|
565
|
+
const context = new TurnContext(this, createActivity, CloudAdapter.createIdentity(agentAppId))
|
|
566
|
+
this.setConnectorClient(context, restClient)
|
|
567
|
+
this.setUserTokenClient(context, userTokenClient)
|
|
449
568
|
await this.runMiddleware(context, logic)
|
|
450
569
|
}
|
|
451
570
|
|
|
452
571
|
/**
|
|
572
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
453
573
|
* Uploads an attachment.
|
|
454
574
|
* @param conversationId - The conversation ID.
|
|
455
575
|
* @param attachmentData - The attachment data.
|
|
456
576
|
* @returns A promise representing the ResourceResponse for the uploaded attachment.
|
|
457
577
|
*/
|
|
458
|
-
async uploadAttachment (conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
|
|
578
|
+
async uploadAttachment (context: TurnContext, conversationId: string, attachmentData: AttachmentData): Promise<ResourceResponse> {
|
|
579
|
+
if (context === undefined) {
|
|
580
|
+
throw new Error('context is required')
|
|
581
|
+
}
|
|
582
|
+
|
|
459
583
|
if (conversationId === undefined) {
|
|
460
584
|
throw new Error('conversationId is required')
|
|
461
585
|
}
|
|
@@ -464,29 +588,39 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
464
588
|
throw new Error('attachmentData is required')
|
|
465
589
|
}
|
|
466
590
|
|
|
467
|
-
return await this.
|
|
591
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).uploadAttachment(conversationId, attachmentData)
|
|
468
592
|
}
|
|
469
593
|
|
|
470
594
|
/**
|
|
595
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
471
596
|
* Gets attachment information.
|
|
472
597
|
* @param attachmentId - The attachment ID.
|
|
473
598
|
* @returns A promise representing the AttachmentInfo for the requested attachment.
|
|
474
599
|
*/
|
|
475
|
-
async getAttachmentInfo (attachmentId: string): Promise<AttachmentInfo> {
|
|
600
|
+
async getAttachmentInfo (context: TurnContext, attachmentId: string): Promise<AttachmentInfo> {
|
|
601
|
+
if (context === undefined) {
|
|
602
|
+
throw new Error('context is required')
|
|
603
|
+
}
|
|
604
|
+
|
|
476
605
|
if (attachmentId === undefined) {
|
|
477
606
|
throw new Error('attachmentId is required')
|
|
478
607
|
}
|
|
479
608
|
|
|
480
|
-
return await this.
|
|
609
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachmentInfo(attachmentId)
|
|
481
610
|
}
|
|
482
611
|
|
|
483
612
|
/**
|
|
613
|
+
* @deprecated This function will not be supported in future versions. Use TurnContext.turnState.get<ConnectorClient>(CloudAdapter.ConnectorClientKey).
|
|
484
614
|
* Gets an attachment.
|
|
485
615
|
* @param attachmentId - The attachment ID.
|
|
486
616
|
* @param viewId - The view ID.
|
|
487
617
|
* @returns A promise representing the NodeJS.ReadableStream for the requested attachment.
|
|
488
618
|
*/
|
|
489
|
-
async getAttachment (attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
|
|
619
|
+
async getAttachment (context: TurnContext, attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream> {
|
|
620
|
+
if (context === undefined) {
|
|
621
|
+
throw new Error('context is required')
|
|
622
|
+
}
|
|
623
|
+
|
|
490
624
|
if (attachmentId === undefined) {
|
|
491
625
|
throw new Error('attachmentId is required')
|
|
492
626
|
}
|
|
@@ -495,6 +629,6 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
495
629
|
throw new Error('viewId is required')
|
|
496
630
|
}
|
|
497
631
|
|
|
498
|
-
return await this.
|
|
632
|
+
return await context.turnState.get<ConnectorClient>(this.ConnectorClientKey).getAttachment(attachmentId, viewId)
|
|
499
633
|
}
|
|
500
634
|
}
|
|
@@ -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