@microsoft/agents-hosting 0.2.10-g3ac88ff25e → 0.3.5
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/README.md +17 -1
- package/dist/src/activityHandler.d.ts +304 -46
- package/dist/src/activityHandler.js +298 -45
- package/dist/src/activityHandler.js.map +1 -1
- package/dist/src/agent-client/agentClient.d.ts +50 -0
- package/dist/src/agent-client/agentClient.js +28 -0
- package/dist/src/agent-client/agentClient.js.map +1 -1
- package/dist/src/app/agentApplication.d.ts +272 -7
- package/dist/src/app/agentApplication.js +278 -12
- package/dist/src/app/agentApplication.js.map +1 -1
- package/dist/src/app/agentApplicationBuilder.d.ts +34 -3
- package/dist/src/app/agentApplicationBuilder.js +38 -6
- package/dist/src/app/agentApplicationBuilder.js.map +1 -1
- package/dist/src/app/agentApplicationOptions.d.ts +26 -2
- package/dist/src/app/appMemory.d.ts +34 -0
- package/dist/src/app/{memory.js → appMemory.js} +1 -1
- package/dist/src/app/appMemory.js.map +1 -0
- package/dist/src/app/appRoute.d.ts +6 -0
- package/dist/src/app/attachmentDownloader.d.ts +18 -0
- package/dist/src/app/attachmentDownloader.js +18 -0
- package/dist/src/app/attachmentDownloader.js.map +1 -1
- package/dist/src/app/conversationUpdateEvents.d.ts +6 -0
- package/dist/src/app/index.d.ts +4 -1
- package/dist/src/app/index.js +4 -1
- package/dist/src/app/index.js.map +1 -1
- package/dist/src/app/inputFileDownloader.d.ts +22 -0
- package/dist/src/app/oauth/authorization.d.ts +87 -0
- package/dist/src/app/oauth/authorization.js +135 -0
- package/dist/src/app/oauth/authorization.js.map +1 -0
- package/dist/src/app/routeHandler.d.ts +8 -0
- package/dist/src/app/routeSelector.d.ts +9 -0
- package/dist/src/app/turnEvents.d.ts +6 -0
- package/dist/src/app/turnState.d.ts +152 -2
- package/dist/src/app/turnState.js +125 -0
- package/dist/src/app/turnState.js.map +1 -1
- package/dist/src/app/turnStateEntry.d.ts +32 -0
- package/dist/src/app/turnStateEntry.js +32 -0
- package/dist/src/app/turnStateEntry.js.map +1 -1
- package/dist/src/auth/authConfiguration.d.ts +24 -0
- package/dist/src/auth/authConfiguration.js.map +1 -1
- package/dist/src/auth/request.d.ts +12 -0
- package/dist/src/baseAdapter.d.ts +17 -0
- package/dist/src/baseAdapter.js +17 -0
- package/dist/src/baseAdapter.js.map +1 -1
- package/dist/src/cards/cardFactory.d.ts +3 -0
- package/dist/src/cards/cardFactory.js +3 -0
- package/dist/src/cards/cardFactory.js.map +1 -1
- package/dist/src/cards/index.d.ts +1 -0
- package/dist/src/cards/index.js +1 -0
- package/dist/src/cards/index.js.map +1 -1
- package/dist/src/cards/o365ConnectorCardActionBase.d.ts +8 -0
- package/dist/src/cloudAdapter.d.ts +25 -3
- package/dist/src/cloudAdapter.js +25 -3
- package/dist/src/cloudAdapter.js.map +1 -1
- package/dist/src/getProductInfo.d.ts +6 -0
- package/dist/src/getProductInfo.js +6 -0
- package/dist/src/getProductInfo.js.map +1 -1
- package/dist/src/logger.d.ts +34 -2
- package/dist/src/logger.js +35 -0
- package/dist/src/logger.js.map +1 -1
- package/dist/src/oauth/oAuthFlow.d.ts +32 -3
- package/dist/src/oauth/oAuthFlow.js +38 -14
- package/dist/src/oauth/oAuthFlow.js.map +1 -1
- package/dist/src/oauth/userTokenClient.d.ts +2 -2
- package/dist/src/oauth/userTokenClient.js +3 -3
- package/dist/src/oauth/userTokenClient.js.map +1 -1
- package/dist/src/state/agentState.d.ts +79 -27
- package/dist/src/state/agentState.js +58 -27
- package/dist/src/state/agentState.js.map +1 -1
- package/dist/src/state/agentStatePropertyAccesor.d.ts +67 -11
- package/dist/src/state/agentStatePropertyAccesor.js +58 -11
- package/dist/src/state/agentStatePropertyAccesor.js.map +1 -1
- package/dist/src/statusCodes.d.ts +39 -0
- package/dist/src/statusCodes.js +39 -0
- package/dist/src/statusCodes.js.map +1 -1
- package/dist/src/storage/memoryStorage.d.ts +48 -14
- package/dist/src/storage/memoryStorage.js +48 -14
- package/dist/src/storage/memoryStorage.js.map +1 -1
- package/dist/src/storage/storage.d.ts +43 -13
- package/dist/src/tokenResponseEventName.d.ts +3 -0
- package/dist/src/tokenResponseEventName.js +3 -0
- package/dist/src/tokenResponseEventName.js.map +1 -1
- package/dist/src/turnContext.d.ts +142 -56
- package/dist/src/turnContext.js +123 -53
- package/dist/src/turnContext.js.map +1 -1
- package/package.json +6 -6
- package/src/activityHandler.ts +304 -46
- package/src/agent-client/agentClient.ts +55 -5
- package/src/app/agentApplication.ts +283 -15
- package/src/app/agentApplicationBuilder.ts +39 -7
- package/src/app/agentApplicationOptions.ts +33 -2
- package/src/app/appMemory.ts +38 -0
- package/src/app/appRoute.ts +7 -0
- package/src/app/attachmentDownloader.ts +18 -0
- package/src/app/conversationUpdateEvents.ts +6 -0
- package/src/app/index.ts +4 -1
- package/src/app/inputFileDownloader.ts +24 -0
- package/src/app/oauth/authorization.ts +162 -0
- package/src/app/routeHandler.ts +8 -0
- package/src/app/routeSelector.ts +9 -0
- package/src/app/turnEvents.ts +6 -0
- package/src/app/turnState.ts +153 -3
- package/src/app/turnStateEntry.ts +32 -0
- package/src/auth/authConfiguration.ts +32 -1
- package/src/auth/request.ts +15 -0
- package/src/baseAdapter.ts +18 -0
- package/src/cards/cardFactory.ts +3 -0
- package/src/cards/index.ts +1 -0
- package/src/cards/o365ConnectorCardActionBase.ts +8 -0
- package/src/cloudAdapter.ts +28 -3
- package/src/getProductInfo.ts +7 -0
- package/src/logger.ts +34 -1
- package/src/oauth/oAuthFlow.ts +59 -18
- package/src/oauth/userTokenClient.ts +4 -4
- package/src/state/agentState.ts +81 -29
- package/src/state/agentStatePropertyAccesor.ts +67 -11
- package/src/statusCodes.ts +51 -0
- package/src/storage/memoryStorage.ts +48 -14
- package/src/storage/storage.ts +51 -18
- package/src/tokenResponseEventName.ts +3 -0
- package/src/turnContext.ts +142 -56
- package/dist/src/app/memory.d.ts +0 -10
- package/dist/src/app/memory.js.map +0 -1
- package/dist/src/app/oauth/userIdentity.d.ts +0 -43
- package/dist/src/app/oauth/userIdentity.js +0 -54
- package/dist/src/app/oauth/userIdentity.js.map +0 -1
- package/src/app/memory.ts +0 -14
- package/src/app/oauth/userIdentity.ts +0 -78
package/src/auth/request.ts
CHANGED
|
@@ -13,8 +13,23 @@ export interface Request<
|
|
|
13
13
|
Body extends Record<string, unknown> = Record<string, unknown>,
|
|
14
14
|
Headers extends Record<string, string[] | string | undefined> = Record<string, string[] | string | undefined>
|
|
15
15
|
> {
|
|
16
|
+
/**
|
|
17
|
+
* The body of the HTTP request, containing parsed data.
|
|
18
|
+
*/
|
|
16
19
|
body?: Body
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The headers of the HTTP request, represented as key-value pairs.
|
|
23
|
+
*/
|
|
17
24
|
headers: Headers
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The HTTP method of the request (e.g., GET, POST, PUT, DELETE).
|
|
28
|
+
*/
|
|
18
29
|
method?: string
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The user information extracted from a JWT payload, if available.
|
|
33
|
+
*/
|
|
19
34
|
user?: JwtPayload
|
|
20
35
|
}
|
package/src/baseAdapter.ts
CHANGED
|
@@ -20,6 +20,9 @@ const logger = debug('agents:base-adapter')
|
|
|
20
20
|
* Base class for all adapters, providing middleware and error handling capabilities.
|
|
21
21
|
*/
|
|
22
22
|
export abstract class BaseAdapter {
|
|
23
|
+
/**
|
|
24
|
+
* The middleware set used to process the pipeline of middleware handlers.
|
|
25
|
+
*/
|
|
23
26
|
protected middleware: MiddlewareSet = new MiddlewareSet()
|
|
24
27
|
|
|
25
28
|
private turnError: (context: TurnContext, error: Error) => Promise<void> = async (context: TurnContext, error: Error) => {
|
|
@@ -42,7 +45,14 @@ export abstract class BaseAdapter {
|
|
|
42
45
|
readonly ConnectorClientKey = Symbol('ConnectorClient')
|
|
43
46
|
readonly OAuthScopeKey = Symbol('OAuthScope')
|
|
44
47
|
|
|
48
|
+
/**
|
|
49
|
+
* The authentication provider used for token management.
|
|
50
|
+
*/
|
|
45
51
|
authProvider: AuthProvider = new MsalTokenProvider()
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The authentication configuration for the adapter.
|
|
55
|
+
*/
|
|
46
56
|
authConfig: AuthConfiguration = { issuers: [] }
|
|
47
57
|
|
|
48
58
|
/**
|
|
@@ -103,10 +113,18 @@ export abstract class BaseAdapter {
|
|
|
103
113
|
*/
|
|
104
114
|
abstract getAttachment (attachmentId: string, viewId: string): Promise<NodeJS.ReadableStream>
|
|
105
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Gets the error handler for the adapter.
|
|
118
|
+
* @returns The current error handler function.
|
|
119
|
+
*/
|
|
106
120
|
get onTurnError (): (context: TurnContext, error: Error) => Promise<void> {
|
|
107
121
|
return this.turnError
|
|
108
122
|
}
|
|
109
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Sets the error handler for the adapter.
|
|
126
|
+
* @param value - The error handler function to set.
|
|
127
|
+
*/
|
|
110
128
|
set onTurnError (value: (context: TurnContext, error: Error) => Promise<void>) {
|
|
111
129
|
this.turnError = value
|
|
112
130
|
}
|
package/src/cards/cardFactory.ts
CHANGED
|
@@ -21,6 +21,9 @@ import { SigninCard } from './signinCard'
|
|
|
21
21
|
* Factory class for creating various types of cards.
|
|
22
22
|
*/
|
|
23
23
|
export class CardFactory {
|
|
24
|
+
/**
|
|
25
|
+
* The content types supported by the card factory.
|
|
26
|
+
*/
|
|
24
27
|
static contentTypes: any = {
|
|
25
28
|
adaptiveCard: 'application/vnd.microsoft.card.adaptive',
|
|
26
29
|
animationCard: 'application/vnd.microsoft.card.animation',
|
package/src/cards/index.ts
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Defines the possible types of actions in an O365 connector card.
|
|
8
|
+
*
|
|
9
|
+
* - `ViewAction`: Represents an action to view content.
|
|
10
|
+
* - `OpenUri`: Represents an action to open a URI.
|
|
11
|
+
* - `HttpPOST`: Represents an action to make an HTTP POST request.
|
|
12
|
+
* - `ActionCard`: Represents an action that opens a card with additional actions or inputs.
|
|
13
|
+
*/
|
|
6
14
|
export type O365ConnectorCardActionType = 'ViewAction' | 'OpenUri' | 'HttpPOST' | 'ActionCard'
|
|
7
15
|
|
|
8
16
|
/**
|
package/src/cloudAdapter.ts
CHANGED
|
@@ -25,15 +25,23 @@ import { normalizeIncomingActivity } from './activityWireCompat'
|
|
|
25
25
|
const logger = debug('agents:cloud-adapter')
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Adapter for handling agent interactions.
|
|
28
|
+
* Adapter for handling agent interactions with various channels through cloud-based services.
|
|
29
|
+
*
|
|
30
|
+
* CloudAdapter processes incoming HTTP requests from Microsoft Bot Framework channels,
|
|
31
|
+
* authenticates them, and generates outgoing responses. It manages the communication
|
|
32
|
+
* flow between agents and users across different channels, handling activities, attachments,
|
|
33
|
+
* and conversation continuations.
|
|
29
34
|
*/
|
|
30
35
|
export class CloudAdapter extends BaseAdapter {
|
|
36
|
+
/**
|
|
37
|
+
* Client for connecting to the Bot Framework Connector service
|
|
38
|
+
*/
|
|
31
39
|
public connectorClient!: ConnectorClient
|
|
32
40
|
|
|
33
41
|
/**
|
|
34
42
|
* Creates an instance of CloudAdapter.
|
|
35
|
-
* @param authConfig - The authentication configuration
|
|
36
|
-
* @param authProvider -
|
|
43
|
+
* @param authConfig - The authentication configuration for securing communications
|
|
44
|
+
* @param authProvider - Optional custom authentication provider. If not specified, a default MsalTokenProvider will be used
|
|
37
45
|
*/
|
|
38
46
|
constructor (authConfig: AuthConfiguration, authProvider?: AuthProvider) {
|
|
39
47
|
super()
|
|
@@ -47,6 +55,14 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Creates a connector client for a specific service URL and scope.
|
|
60
|
+
*
|
|
61
|
+
* @param serviceUrl - The URL of the service to connect to
|
|
62
|
+
* @param scope - The authentication scope to use
|
|
63
|
+
* @returns A promise that resolves to a ConnectorClient instance
|
|
64
|
+
* @protected
|
|
65
|
+
*/
|
|
50
66
|
protected async createConnectorClient (
|
|
51
67
|
serviceUrl: string,
|
|
52
68
|
scope: string
|
|
@@ -59,6 +75,12 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
59
75
|
)
|
|
60
76
|
}
|
|
61
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Sets the connector client on the turn context.
|
|
80
|
+
*
|
|
81
|
+
* @param context - The current turn context
|
|
82
|
+
* @protected
|
|
83
|
+
*/
|
|
62
84
|
protected setConnectorClient (
|
|
63
85
|
context: TurnContext
|
|
64
86
|
) {
|
|
@@ -164,6 +186,9 @@ export class CloudAdapter extends BaseAdapter {
|
|
|
164
186
|
}
|
|
165
187
|
res.end()
|
|
166
188
|
}
|
|
189
|
+
if (!request.body) {
|
|
190
|
+
throw new TypeError('`request.body` parameter required, make sure express.json() is used as middleware')
|
|
191
|
+
}
|
|
167
192
|
const incoming = normalizeIncomingActivity(request.body!)
|
|
168
193
|
const activity = Activity.fromObject(incoming)
|
|
169
194
|
logger.info(`--> Processing incoming activity, type:${activity.type} channel:${activity.channelId}`)
|
package/src/getProductInfo.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import pjson from '@microsoft/agents-hosting/package.json'
|
|
2
2
|
import os from 'os'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generates a string containing information about the SDK version and runtime environment.
|
|
6
|
+
* This is used for telemetry and User-Agent headers in HTTP requests.
|
|
7
|
+
*
|
|
8
|
+
* @returns A formatted string containing the SDK version, Node.js version, and OS details
|
|
9
|
+
*/
|
|
3
10
|
export const getProductInfo = () : string => `agents-sdk-js/${pjson.version} nodejs/${process.version} ${os.platform()}-${os.arch()}/${os.release()}`
|
package/src/logger.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import createDebug, { Debugger } from 'debug'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Logger class that provides colored logging functionality using the debug package.
|
|
5
|
+
* Supports different log levels: info, warn, error, and debug.
|
|
6
|
+
*/
|
|
7
|
+
export class Logger {
|
|
4
8
|
private loggers: { [level: string]: Debugger } = {}
|
|
5
9
|
private readonly levelColors: { [level: string]: string } = {
|
|
6
10
|
info: '2', // Green
|
|
@@ -9,6 +13,10 @@ class Logger {
|
|
|
9
13
|
debug: '4' // Blue
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new Logger instance with the specified namespace.
|
|
18
|
+
* @param namespace The namespace to use for the logger
|
|
19
|
+
*/
|
|
12
20
|
constructor (namespace: string = '') {
|
|
13
21
|
this.initializeLoggers(namespace)
|
|
14
22
|
}
|
|
@@ -21,23 +29,48 @@ class Logger {
|
|
|
21
29
|
}
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Logs an informational message.
|
|
34
|
+
* @param message The message to log
|
|
35
|
+
* @param args Additional arguments to include in the log
|
|
36
|
+
*/
|
|
24
37
|
info (message: string, ...args: any[]) {
|
|
25
38
|
this.loggers.info(message, ...args)
|
|
26
39
|
}
|
|
27
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Logs a warning message.
|
|
43
|
+
* @param message The message to log
|
|
44
|
+
* @param args Additional arguments to include in the log
|
|
45
|
+
*/
|
|
28
46
|
warn (message: string, ...args: any[]) {
|
|
29
47
|
this.loggers.warn(message, ...args)
|
|
30
48
|
}
|
|
31
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Logs an error message.
|
|
52
|
+
* @param message The message to log
|
|
53
|
+
* @param args Additional arguments to include in the log
|
|
54
|
+
*/
|
|
32
55
|
error (message: string, ...args: any[]) {
|
|
33
56
|
this.loggers.error(message, ...args)
|
|
34
57
|
}
|
|
35
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Logs a debug message.
|
|
61
|
+
* @param message The message to log
|
|
62
|
+
* @param args Additional arguments to include in the log
|
|
63
|
+
*/
|
|
36
64
|
debug (message: string, ...args: any[]) {
|
|
37
65
|
this.loggers.debug(message, ...args)
|
|
38
66
|
}
|
|
39
67
|
}
|
|
40
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new Logger instance with the specified namespace.
|
|
71
|
+
* @param namespace The namespace to use for the logger
|
|
72
|
+
* @returns A new Logger instance
|
|
73
|
+
*/
|
|
41
74
|
export function debug (namespace: string): Logger {
|
|
42
75
|
return new Logger(namespace)
|
|
43
76
|
}
|
package/src/oauth/oAuthFlow.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
3
|
import { debug } from './../logger'
|
|
4
|
-
import {
|
|
4
|
+
import { ActivityTypes, Attachment } from '@microsoft/agents-activity'
|
|
5
5
|
import {
|
|
6
6
|
CardFactory,
|
|
7
7
|
AgentStatePropertyAccessor,
|
|
8
8
|
UserState,
|
|
9
9
|
TurnContext,
|
|
10
10
|
MessageFactory,
|
|
11
|
-
SigningResource,
|
|
12
11
|
TokenExchangeRequest,
|
|
13
12
|
UserTokenClient
|
|
14
13
|
} from '../'
|
|
@@ -25,28 +24,72 @@ interface TokenVerifyState {
|
|
|
25
24
|
state: string
|
|
26
25
|
}
|
|
27
26
|
/**
|
|
28
|
-
* Manages the OAuth flow
|
|
27
|
+
* Manages the OAuth flow
|
|
29
28
|
*/
|
|
30
29
|
export class OAuthFlow {
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* The user token client used for managing user tokens.
|
|
32
|
+
*/
|
|
33
|
+
userTokenClient: UserTokenClient
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The current state of the OAuth flow.
|
|
37
|
+
*/
|
|
32
38
|
state: FlowState | null
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The accessor for managing the flow state in user state.
|
|
42
|
+
*/
|
|
33
43
|
flowStateAccessor: AgentStatePropertyAccessor<FlowState | null>
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The ID of the token exchange request, used to deduplicate requests.
|
|
47
|
+
*/
|
|
34
48
|
tokenExchangeId: string | null = null
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The name of the OAuth connection.
|
|
52
|
+
*/
|
|
35
53
|
absOauthConnectionName: string
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The title of the OAuth card.
|
|
57
|
+
*/
|
|
58
|
+
cardTitle: string = 'Sign in'
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The text of the OAuth card.
|
|
62
|
+
*/
|
|
63
|
+
cardText: string = 'login'
|
|
64
|
+
|
|
36
65
|
/**
|
|
37
66
|
* Creates a new instance of OAuthFlow.
|
|
38
67
|
* @param userState The user state.
|
|
39
68
|
*/
|
|
40
|
-
constructor (userState: UserState, absOauthConnectionName: string, tokenClient?: UserTokenClient) {
|
|
41
|
-
this.state =
|
|
69
|
+
constructor (userState: UserState, absOauthConnectionName: string, tokenClient?: UserTokenClient, cardTitle?: string, cardText?: string) {
|
|
70
|
+
this.state = new FlowState()
|
|
42
71
|
this.flowStateAccessor = userState.createProperty('flowState')
|
|
43
72
|
this.absOauthConnectionName = absOauthConnectionName
|
|
44
|
-
this.userTokenClient = tokenClient
|
|
73
|
+
this.userTokenClient = tokenClient ?? null!
|
|
74
|
+
this.cardTitle = cardTitle ?? this.cardTitle
|
|
75
|
+
this.cardText = cardText ?? this.cardText
|
|
45
76
|
}
|
|
46
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Retrieves the user token from the user token service.
|
|
80
|
+
* @param context The turn context containing the activity information.
|
|
81
|
+
* @returns A promise that resolves to the user token response.
|
|
82
|
+
* @throws Will throw an error if the channelId or from properties are not set in the activity.
|
|
83
|
+
*/
|
|
47
84
|
public async getUserToken (context: TurnContext): Promise<TokenResponse> {
|
|
48
85
|
await this.initializeTokenClient(context)
|
|
49
|
-
|
|
86
|
+
logger.info('Get token from user token service')
|
|
87
|
+
const activity = context.activity
|
|
88
|
+
if (activity.channelId && activity.from && activity.from.id) {
|
|
89
|
+
return await this.userTokenClient.getUserToken(this.absOauthConnectionName, activity.channelId, activity.from.id)
|
|
90
|
+
} else {
|
|
91
|
+
throw new Error('UserTokenService requires channelId and from to be set')
|
|
92
|
+
}
|
|
50
93
|
}
|
|
51
94
|
|
|
52
95
|
/**
|
|
@@ -55,16 +98,14 @@ export class OAuthFlow {
|
|
|
55
98
|
* @returns A promise that resolves to the user token.
|
|
56
99
|
*/
|
|
57
100
|
public async beginFlow (context: TurnContext): Promise<TokenResponse> {
|
|
58
|
-
logger.info('Starting OAuth flow')
|
|
59
101
|
this.state = await this.getUserState(context)
|
|
60
|
-
|
|
61
|
-
const authConfig = context.adapter.authConfig
|
|
62
102
|
if (this.absOauthConnectionName === '') {
|
|
63
|
-
throw new Error('connectionName is not set
|
|
103
|
+
throw new Error('connectionName is not set')
|
|
64
104
|
}
|
|
105
|
+
logger.info('Starting OAuth flow for connectionName:', this.absOauthConnectionName)
|
|
65
106
|
await this.initializeTokenClient(context)
|
|
66
107
|
|
|
67
|
-
const tokenResponse = await this.userTokenClient
|
|
108
|
+
const tokenResponse = await this.userTokenClient.getUserToken(this.absOauthConnectionName, context.activity.channelId!, context.activity.from?.id!)
|
|
68
109
|
if (tokenResponse?.status === TokenRequestStatus.Success) {
|
|
69
110
|
this.state.flowStarted = false
|
|
70
111
|
this.state.flowExpires = 0
|
|
@@ -73,10 +114,10 @@ export class OAuthFlow {
|
|
|
73
114
|
return tokenResponse
|
|
74
115
|
}
|
|
75
116
|
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
await context.sendActivity(
|
|
117
|
+
const authConfig = context.adapter.authConfig
|
|
118
|
+
const signingResource = await this.userTokenClient.getSignInResource(authConfig.clientId!, this.absOauthConnectionName, context.activity.getConversationReference(), context.activity.relatesTo)
|
|
119
|
+
const oCard: Attachment = CardFactory.oauthCard(this.absOauthConnectionName, this.cardTitle, this.cardText, signingResource)
|
|
120
|
+
await context.sendActivity(MessageFactory.attachment(oCard))
|
|
80
121
|
this.state.flowStarted = true
|
|
81
122
|
this.state.flowExpires = Date.now() + 30000
|
|
82
123
|
await this.flowStateAccessor.set(context, this.state)
|
|
@@ -166,7 +207,7 @@ export class OAuthFlow {
|
|
|
166
207
|
}
|
|
167
208
|
|
|
168
209
|
private async initializeTokenClient (context: TurnContext) {
|
|
169
|
-
if (this.userTokenClient === undefined) {
|
|
210
|
+
if (this.userTokenClient === undefined || this.userTokenClient === null) {
|
|
170
211
|
const scope = 'https://api.botframework.com'
|
|
171
212
|
const accessToken = await context.adapter.authProvider.getAccessToken(context.adapter.authConfig, scope)
|
|
172
213
|
this.userTokenClient = new UserTokenClient(accessToken)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import axios, { AxiosInstance } from 'axios'
|
|
5
5
|
import { SigningResource } from './signingResource'
|
|
6
|
-
import {
|
|
6
|
+
import { ConversationReference } from '@microsoft/agents-activity'
|
|
7
7
|
import { debug } from '../logger'
|
|
8
8
|
import { TokenExchangeRequest } from './tokenExchangeRequest'
|
|
9
9
|
import { normalizeTokenExchangeState } from '../activityWireCompat'
|
|
@@ -86,12 +86,12 @@ export class UserTokenClient {
|
|
|
86
86
|
* @param activity The activity.
|
|
87
87
|
* @returns A promise that resolves to the signing resource.
|
|
88
88
|
*/
|
|
89
|
-
async getSignInResource (appId: string, cnxName: string,
|
|
89
|
+
async getSignInResource (appId: string, cnxName: string, conversationReference: ConversationReference, relatesTo?: ConversationReference) : Promise<SigningResource> {
|
|
90
90
|
try {
|
|
91
91
|
const tokenExchangeState = {
|
|
92
92
|
connectionName: cnxName,
|
|
93
|
-
conversation:
|
|
94
|
-
relatesTo
|
|
93
|
+
conversation: conversationReference,
|
|
94
|
+
relatesTo,
|
|
95
95
|
msAppId: appId
|
|
96
96
|
}
|
|
97
97
|
const tokenExchangeStateNormalized = normalizeTokenExchangeState(tokenExchangeState)
|
package/src/state/agentState.ts
CHANGED
|
@@ -11,34 +11,63 @@ import { debug } from '../logger'
|
|
|
11
11
|
|
|
12
12
|
const logger = debug('agents:state')
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Represents agent state that has been cached in the turn context.
|
|
16
|
+
* Used internally to track state changes and avoid unnecessary storage operations.
|
|
17
|
+
*/
|
|
14
18
|
export interface CachedAgentState {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The state object containing all properties and their values
|
|
21
|
+
*/
|
|
22
|
+
state: { [id: string]: any };
|
|
23
|
+
/**
|
|
24
|
+
* Hash of the state used to detect changes
|
|
25
|
+
*/
|
|
26
|
+
hash: string;
|
|
17
27
|
}
|
|
18
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Represents a custom key for storing state in a specific location.
|
|
31
|
+
* Allows state to be persisted with channel and conversation identifiers
|
|
32
|
+
* independent of the current context.
|
|
33
|
+
*/
|
|
19
34
|
export interface CustomKey {
|
|
35
|
+
/**
|
|
36
|
+
* The ID of the channel where the state should be stored
|
|
37
|
+
*/
|
|
20
38
|
channelId: string;
|
|
39
|
+
/**
|
|
40
|
+
* The ID of the conversation where the state should be stored
|
|
41
|
+
*/
|
|
21
42
|
conversationId: string;
|
|
22
43
|
// TODO: namespace needs to be added
|
|
23
44
|
}
|
|
24
45
|
|
|
25
46
|
/**
|
|
26
|
-
* Manages the state of an Agent.
|
|
47
|
+
* Manages the state of an Agent across turns in a conversation.
|
|
48
|
+
*
|
|
49
|
+
* AgentState provides functionality to persist and retrieve state data using
|
|
50
|
+
* a storage provider. It handles caching state in the turn context for performance,
|
|
51
|
+
* calculating change hashes to detect modifications, and managing property accessors
|
|
52
|
+
* for typed access to state properties.
|
|
27
53
|
*/
|
|
28
54
|
export class AgentState {
|
|
29
55
|
private readonly stateKey = Symbol('state')
|
|
30
56
|
|
|
31
57
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
58
|
+
* Creates a new instance of AgentState.
|
|
59
|
+
*
|
|
60
|
+
* @param storage The storage provider used to persist state between turns
|
|
61
|
+
* @param storageKey A factory function that generates keys for storing state data
|
|
62
|
+
*/
|
|
36
63
|
constructor (protected storage: Storage, protected storageKey: StorageKeyFactory) { }
|
|
37
64
|
|
|
38
65
|
/**
|
|
39
66
|
* Creates a property accessor for the specified property.
|
|
40
|
-
*
|
|
41
|
-
*
|
|
67
|
+
* Property accessors provide typed access to properties within the state object.
|
|
68
|
+
*
|
|
69
|
+
* @param name The name of the property to access
|
|
70
|
+
* @returns A property accessor for the specified property
|
|
42
71
|
*/
|
|
43
72
|
createProperty<T = any>(name: string): AgentStatePropertyAccessor<T> {
|
|
44
73
|
const prop: AgentStatePropertyAccessor<T> = new AgentStatePropertyAccessor<T>(this, name)
|
|
@@ -46,10 +75,13 @@ export class AgentState {
|
|
|
46
75
|
}
|
|
47
76
|
|
|
48
77
|
/**
|
|
49
|
-
* Loads the state from storage.
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* @
|
|
78
|
+
* Loads the state from storage into the turn context.
|
|
79
|
+
* If state is already cached in the turn context and force is not set, the cached version will be used.
|
|
80
|
+
*
|
|
81
|
+
* @param context The turn context to load state into
|
|
82
|
+
* @param force If true, forces a reload from storage even if state is cached
|
|
83
|
+
* @param customKey Optional custom storage key to use instead of the default
|
|
84
|
+
* @returns A promise that resolves to the loaded state object
|
|
53
85
|
*/
|
|
54
86
|
public async load (context: TurnContext, force = false, customKey?: CustomKey): Promise<any> {
|
|
55
87
|
const cached: CachedAgentState = context.turnState.get(this.stateKey)
|
|
@@ -70,10 +102,13 @@ export class AgentState {
|
|
|
70
102
|
}
|
|
71
103
|
|
|
72
104
|
/**
|
|
73
|
-
* Saves the state to storage.
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* @
|
|
105
|
+
* Saves the state to storage if it has changed since it was loaded.
|
|
106
|
+
* Change detection uses a hash of the state object to determine if saving is necessary.
|
|
107
|
+
*
|
|
108
|
+
* @param context The turn context containing the state to save
|
|
109
|
+
* @param force If true, forces a save to storage even if no changes are detected
|
|
110
|
+
* @param customKey Optional custom storage key to use instead of the default
|
|
111
|
+
* @returns A promise that resolves when the save operation is complete
|
|
77
112
|
*/
|
|
78
113
|
public async saveChanges (context: TurnContext, force = false, customKey?: CustomKey): Promise<void> {
|
|
79
114
|
let cached: CachedAgentState = context.turnState.get(this.stateKey)
|
|
@@ -95,6 +130,14 @@ export class AgentState {
|
|
|
95
130
|
}
|
|
96
131
|
}
|
|
97
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Determines whether to use a custom key or generate one from the context.
|
|
135
|
+
*
|
|
136
|
+
* @param customKey Optional custom key with channel and conversation IDs
|
|
137
|
+
* @param context The turn context used to generate a key if no custom key is provided
|
|
138
|
+
* @returns The storage key to use
|
|
139
|
+
* @private
|
|
140
|
+
*/
|
|
98
141
|
private async getStorageOrCustomKey (customKey: CustomKey | undefined, context: TurnContext) {
|
|
99
142
|
let key: string | undefined
|
|
100
143
|
if (customKey && customKey.channelId && customKey.conversationId) {
|
|
@@ -107,9 +150,12 @@ export class AgentState {
|
|
|
107
150
|
}
|
|
108
151
|
|
|
109
152
|
/**
|
|
110
|
-
* Clears the state
|
|
111
|
-
*
|
|
112
|
-
*
|
|
153
|
+
* Clears the state by setting it to an empty object in the turn context.
|
|
154
|
+
* Note: This does not remove the state from storage, it only clears the in-memory representation.
|
|
155
|
+
* Call saveChanges() after this to persist the empty state to storage.
|
|
156
|
+
*
|
|
157
|
+
* @param context The turn context containing the state to clear
|
|
158
|
+
* @returns A promise that resolves when the clear operation is complete
|
|
113
159
|
*/
|
|
114
160
|
public async clear (context: TurnContext): Promise<void> {
|
|
115
161
|
const emptyObjectToForceSave = { state: {}, hash: '' }
|
|
@@ -118,9 +164,11 @@ export class AgentState {
|
|
|
118
164
|
}
|
|
119
165
|
|
|
120
166
|
/**
|
|
121
|
-
* Deletes the state from storage.
|
|
122
|
-
*
|
|
123
|
-
* @
|
|
167
|
+
* Deletes the state from both the turn context and storage.
|
|
168
|
+
*
|
|
169
|
+
* @param context The turn context containing the state to delete
|
|
170
|
+
* @param customKey Optional custom storage key to use instead of the default
|
|
171
|
+
* @returns A promise that resolves when the delete operation is complete
|
|
124
172
|
*/
|
|
125
173
|
public async delete (context: TurnContext, customKey?: CustomKey): Promise<void> {
|
|
126
174
|
if (context.turnState.has(this.stateKey)) {
|
|
@@ -132,9 +180,10 @@ export class AgentState {
|
|
|
132
180
|
}
|
|
133
181
|
|
|
134
182
|
/**
|
|
135
|
-
* Gets the state from the turn context.
|
|
136
|
-
*
|
|
137
|
-
* @
|
|
183
|
+
* Gets the state from the turn context without loading it from storage.
|
|
184
|
+
*
|
|
185
|
+
* @param context The turn context containing the state to get
|
|
186
|
+
* @returns The state object, or undefined if no state is found in the turn context
|
|
138
187
|
*/
|
|
139
188
|
public get (context: TurnContext): any | undefined {
|
|
140
189
|
const cached: CachedAgentState = context.turnState.get(this.stateKey)
|
|
@@ -143,9 +192,12 @@ export class AgentState {
|
|
|
143
192
|
}
|
|
144
193
|
|
|
145
194
|
/**
|
|
146
|
-
* Calculates
|
|
147
|
-
*
|
|
148
|
-
*
|
|
195
|
+
* Calculates a hash for the specified state object to detect changes.
|
|
196
|
+
* The eTag property is excluded from the hash calculation.
|
|
197
|
+
*
|
|
198
|
+
* @param item The state object to calculate the hash for
|
|
199
|
+
* @returns A string hash representing the state
|
|
200
|
+
* @private
|
|
149
201
|
*/
|
|
150
202
|
private readonly calculateChangeHash = (item: StoreItem): string => {
|
|
151
203
|
const { eTag, ...rest } = item
|