@microsoft/agents-hosting 1.9.0-beta.8.gf58e66b2ee → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +182 -4
- package/dist/package.json +3 -3
- package/dist/src/app/agentApplication.d.ts +4 -3
- package/dist/src/app/agentApplication.js +24 -21
- package/dist/src/app/agentApplication.js.map +1 -1
- package/dist/src/app/agentApplicationBuilder.d.ts +9 -2
- package/dist/src/app/agentApplicationBuilder.js +9 -0
- package/dist/src/app/agentApplicationBuilder.js.map +1 -1
- package/dist/src/app/agentApplicationOptions.d.ts +16 -4
- package/dist/src/app/auth/authorizationManager.d.ts +0 -8
- package/dist/src/app/auth/authorizationManager.js +104 -178
- package/dist/src/app/auth/authorizationManager.js.map +1 -1
- package/dist/src/app/auth/handlerStorage.d.ts +5 -3
- package/dist/src/app/auth/handlerStorage.js +36 -10
- package/dist/src/app/auth/handlerStorage.js.map +1 -1
- package/dist/src/app/auth/types.d.ts +2 -2
- package/dist/src/app/index.d.ts +1 -0
- package/dist/src/app/proactive/proactive.js +10 -6
- package/dist/src/app/proactive/proactive.js.map +1 -1
- package/dist/src/app/proactive/proactiveOptions.d.ts +2 -2
- package/dist/src/app/rateLimit.d.ts +315 -0
- package/dist/src/app/rateLimit.js +333 -0
- package/dist/src/app/rateLimit.js.map +1 -0
- package/dist/src/app/turnState.d.ts +6 -3
- package/dist/src/app/turnState.js +43 -4
- package/dist/src/app/turnState.js.map +1 -1
- package/dist/src/auth/authConfiguration.d.ts +10 -3
- package/dist/src/auth/authConfiguration.js +292 -259
- package/dist/src/auth/authConfiguration.js.map +1 -1
- package/dist/src/auth/settings.d.ts +8 -70
- package/dist/src/auth/settings.js +5 -67
- package/dist/src/auth/settings.js.map +1 -1
- package/dist/src/cloudAdapter.d.ts +5 -0
- package/dist/src/cloudAdapter.js +13 -103
- package/dist/src/cloudAdapter.js.map +1 -1
- package/dist/src/configuration/botFrameworkEnvironmentCompatibility.d.ts +23 -0
- package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js +183 -0
- package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js.map +1 -0
- package/dist/src/configuration/configuration.d.ts +83 -0
- package/dist/src/configuration/configuration.js +836 -0
- package/dist/src/configuration/configuration.js.map +1 -0
- package/dist/src/configuration/configurationSource.d.ts +57 -0
- package/dist/src/configuration/configurationSource.js +7 -0
- package/dist/src/configuration/configurationSource.js.map +1 -0
- package/dist/src/configuration/environmentConfiguration.d.ts +14 -0
- package/dist/src/configuration/environmentConfiguration.js +271 -0
- package/dist/src/configuration/environmentConfiguration.js.map +1 -0
- package/dist/src/configuration/index.d.ts +7 -0
- package/dist/src/configuration/index.js +14 -0
- package/dist/src/configuration/index.js.map +1 -0
- package/dist/src/configuration/jsonFileConfigurationSource.d.ts +15 -0
- package/dist/src/configuration/jsonFileConfigurationSource.js +58 -0
- package/dist/src/configuration/jsonFileConfigurationSource.js.map +1 -0
- package/dist/src/createCloudAdapter.d.ts +30 -5
- package/dist/src/createCloudAdapter.js +17 -10
- package/dist/src/createCloudAdapter.js.map +1 -1
- package/dist/src/errorHelper.js +117 -5
- package/dist/src/errorHelper.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/observability/traces.d.ts +6 -4
- package/dist/src/observability/traces.js +10 -9
- package/dist/src/observability/traces.js.map +1 -1
- package/dist/src/outboundHostValidator.d.ts +4 -1
- package/dist/src/outboundHostValidator.js +25 -48
- package/dist/src/outboundHostValidator.js.map +1 -1
- package/dist/src/state/agentState.d.ts +8 -3
- package/dist/src/state/agentState.js +26 -8
- package/dist/src/state/agentState.js.map +1 -1
- package/dist/src/state/conversationState.d.ts +2 -2
- package/dist/src/state/conversationState.js.map +1 -1
- package/dist/src/state/userState.d.ts +2 -2
- package/dist/src/state/userState.js.map +1 -1
- package/dist/src/statusCodes.d.ts +5 -0
- package/dist/src/statusCodes.js +5 -0
- package/dist/src/statusCodes.js.map +1 -1
- package/dist/src/storage/fileStorage.d.ts +83 -68
- package/dist/src/storage/fileStorage.js +279 -105
- package/dist/src/storage/fileStorage.js.map +1 -1
- package/dist/src/storage/index.d.ts +1 -0
- package/dist/src/storage/index.js +1 -0
- package/dist/src/storage/index.js.map +1 -1
- package/dist/src/storage/memoryStorage.d.ts +85 -60
- package/dist/src/storage/memoryStorage.js +244 -87
- package/dist/src/storage/memoryStorage.js.map +1 -1
- package/dist/src/storage/storage.d.ts +100 -2
- package/dist/src/storage/storage.js +25 -0
- package/dist/src/storage/storage.js.map +1 -1
- package/dist/src/storage/storageCompatibility.d.ts +17 -0
- package/dist/src/storage/storageCompatibility.js +157 -0
- package/dist/src/storage/storageCompatibility.js.map +1 -0
- package/dist/src/storage/storageExpiry.d.ts +6 -0
- package/dist/src/storage/storageExpiry.js +20 -0
- package/dist/src/storage/storageExpiry.js.map +1 -0
- package/dist/src/utils/env.d.ts +43 -0
- package/dist/src/utils/env.js +42 -6
- package/dist/src/utils/env.js.map +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/utils.js +10 -1
- package/dist/src/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/app/agentApplication.ts +27 -14
- package/src/app/agentApplicationBuilder.ts +13 -2
- package/src/app/agentApplicationOptions.ts +18 -4
- package/src/app/auth/authorizationManager.ts +126 -204
- package/src/app/auth/handlerStorage.ts +51 -7
- package/src/app/auth/types.ts +2 -2
- package/src/app/index.ts +7 -0
- package/src/app/proactive/proactive.ts +19 -9
- package/src/app/proactive/proactiveOptions.ts +2 -2
- package/src/app/rateLimit.ts +659 -0
- package/src/app/turnState.ts +50 -7
- package/src/auth/authConfiguration.ts +415 -260
- package/src/auth/settings.ts +5 -82
- package/src/cloudAdapter.ts +38 -113
- package/src/configuration/botFrameworkEnvironmentCompatibility.ts +245 -0
- package/src/configuration/configuration.ts +1076 -0
- package/src/configuration/configurationSource.ts +76 -0
- package/src/configuration/environmentConfiguration.ts +377 -0
- package/src/configuration/index.ts +19 -0
- package/src/configuration/jsonFileConfigurationSource.ts +74 -0
- package/src/createCloudAdapter.ts +52 -9
- package/src/errorHelper.ts +143 -5
- package/src/index.ts +1 -0
- package/src/observability/traces.ts +8 -7
- package/src/outboundHostValidator.ts +37 -44
- package/src/state/agentState.ts +39 -13
- package/src/state/conversationState.ts +2 -2
- package/src/state/userState.ts +2 -2
- package/src/statusCodes.ts +6 -0
- package/src/storage/fileStorage.ts +299 -106
- package/src/storage/index.ts +1 -0
- package/src/storage/memoryStorage.ts +268 -85
- package/src/storage/storage.ts +114 -2
- package/src/storage/storageCompatibility.ts +185 -0
- package/src/storage/storageExpiry.ts +21 -0
- package/src/utils/env.ts +63 -0
- package/src/utils.ts +10 -0
package/src/errorHelper.ts
CHANGED
|
@@ -448,6 +448,14 @@ export const Errors: { [key: string]: AgentErrorDefinition } = {
|
|
|
448
448
|
description: 'MSAL returned an unparsable response body'
|
|
449
449
|
},
|
|
450
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Error thrown when a security-sensitive boolean configuration value is invalid.
|
|
453
|
+
*/
|
|
454
|
+
InvalidBooleanConfigurationValue: {
|
|
455
|
+
code: -120394,
|
|
456
|
+
description: 'Configuration source "{sourceName}" returned an invalid boolean for "{path}". Expected one of true/false/1/0.'
|
|
457
|
+
},
|
|
458
|
+
|
|
451
459
|
FailedToAcquireTokenUsingCertificate: {
|
|
452
460
|
code: -120395,
|
|
453
461
|
description: 'Failed to acquire token using certificate'
|
|
@@ -578,11 +586,11 @@ export const Errors: { [key: string]: AgentErrorDefinition } = {
|
|
|
578
586
|
},
|
|
579
587
|
|
|
580
588
|
/**
|
|
581
|
-
* Error thrown when authorization
|
|
589
|
+
* Error thrown when no authorization handlers were resolved.
|
|
582
590
|
*/
|
|
583
591
|
AuthorizationOptionNotAvailable: {
|
|
584
592
|
code: -120530,
|
|
585
|
-
description: 'The Application.authorization property is unavailable because no authorization
|
|
593
|
+
description: 'The Application.authorization property is unavailable because no authorization handlers were resolved.'
|
|
586
594
|
},
|
|
587
595
|
|
|
588
596
|
/**
|
|
@@ -790,14 +798,60 @@ export const Errors: { [key: string]: AgentErrorDefinition } = {
|
|
|
790
798
|
description: 'Changes are required when writing.'
|
|
791
799
|
},
|
|
792
800
|
|
|
793
|
-
/**
|
|
794
|
-
|
|
795
|
-
|
|
801
|
+
/** Error thrown when a V2 storage key is empty or whitespace. */
|
|
802
|
+
StorageV2KeyRequired: {
|
|
803
|
+
code: -120703,
|
|
804
|
+
description: 'Storage V2 keys must be non-empty strings.'
|
|
805
|
+
},
|
|
806
|
+
|
|
807
|
+
/** Error thrown when the legacy storage adapter cannot honor a V2 option. */
|
|
808
|
+
StorageV2UnsupportedOption: {
|
|
809
|
+
code: -120704,
|
|
810
|
+
description: 'The legacy storage adapter does not support the V2 storage option "{option}".'
|
|
811
|
+
},
|
|
812
|
+
|
|
813
|
+
/** Error thrown when an empty V2 storage version token is provided. */
|
|
814
|
+
StorageV2ExpectedVersionEmpty: {
|
|
815
|
+
code: -120706,
|
|
816
|
+
description: 'Storage V2 expectedVersion cannot be empty.'
|
|
817
|
+
},
|
|
818
|
+
|
|
819
|
+
/** Error thrown when a V2 storage operation returns a failed or missing result. */
|
|
820
|
+
StorageV2OperationFailed: {
|
|
821
|
+
code: -120707,
|
|
822
|
+
description: 'Storage V2 {operation} failed for key "{key}" with status "{status}".'
|
|
823
|
+
},
|
|
824
|
+
|
|
825
|
+
/** Error thrown when a V2 value is not a non-array object. */
|
|
826
|
+
StorageV2ValueRequired: {
|
|
827
|
+
code: -120708,
|
|
828
|
+
description: 'Storage V2 values must be non-null, non-array objects.'
|
|
829
|
+
},
|
|
830
|
+
|
|
831
|
+
/** Error thrown when keys are required for storage delete operations. */
|
|
832
|
+
StorageDeleteKeysRequired: {
|
|
833
|
+
code: -120709,
|
|
834
|
+
description: 'Keys are required when deleting.'
|
|
835
|
+
},
|
|
836
|
+
|
|
837
|
+
/** Error thrown when storage option is not available in app options. */
|
|
796
838
|
StorageOptionNotAvailable: {
|
|
797
839
|
code: -120710,
|
|
798
840
|
description: "The 'storage' option is not available in the app options. Ensure that the app is properly configured.",
|
|
799
841
|
},
|
|
800
842
|
|
|
843
|
+
/** Error thrown when a V2 write mode is not supported. */
|
|
844
|
+
StorageV2WriteModeUnsupported: {
|
|
845
|
+
code: -120711,
|
|
846
|
+
description: 'Storage V2 write mode "{mode}" is not supported.'
|
|
847
|
+
},
|
|
848
|
+
|
|
849
|
+
/** Error thrown when another turn saved state after this turn loaded it. */
|
|
850
|
+
AgentStateWriteConflict: {
|
|
851
|
+
code: -120712,
|
|
852
|
+
description: "AgentState '{name}' could not save key '{key}' because another turn updated the state first (status: {status}). This turn's state changes were not saved."
|
|
853
|
+
},
|
|
854
|
+
|
|
801
855
|
/**
|
|
802
856
|
* Error thrown when state is not loaded.
|
|
803
857
|
*/
|
|
@@ -1043,6 +1097,90 @@ export const Errors: { [key: string]: AgentErrorDefinition } = {
|
|
|
1043
1097
|
description: 'The Entra Agent ID sidecar returned an unsupported authorization scheme `{scheme}`. Only the Bearer scheme is supported'
|
|
1044
1098
|
},
|
|
1045
1099
|
|
|
1100
|
+
// ============================================================================
|
|
1101
|
+
// Configuration Source Errors (-120812 to -120827)
|
|
1102
|
+
// ============================================================================
|
|
1103
|
+
|
|
1104
|
+
ConfigurationAlreadyConsumed: {
|
|
1105
|
+
code: -120812,
|
|
1106
|
+
description: 'Configuration sources must be preloaded before the first configuration consumer is created.'
|
|
1107
|
+
},
|
|
1108
|
+
|
|
1109
|
+
ConfigurationSourceNameRequired: {
|
|
1110
|
+
code: -120813,
|
|
1111
|
+
description: 'Configuration source name must be a non-empty string.'
|
|
1112
|
+
},
|
|
1113
|
+
|
|
1114
|
+
DuplicateConfigurationSource: {
|
|
1115
|
+
code: -120814,
|
|
1116
|
+
description: 'Configuration source name `{sourceName}` is registered more than once.'
|
|
1117
|
+
},
|
|
1118
|
+
|
|
1119
|
+
ConfigurationSourceLoadFailed: {
|
|
1120
|
+
code: -120815,
|
|
1121
|
+
description: 'Configuration source `{sourceName}` failed to load.'
|
|
1122
|
+
},
|
|
1123
|
+
|
|
1124
|
+
InvalidConfigurationPath: {
|
|
1125
|
+
code: -120816,
|
|
1126
|
+
description: 'Configuration source `{sourceName}` returned unsupported canonical path `{path}`.'
|
|
1127
|
+
},
|
|
1128
|
+
|
|
1129
|
+
InvalidConfigurationValue: {
|
|
1130
|
+
code: -120817,
|
|
1131
|
+
description: 'Configuration source `{sourceName}` returned an invalid value for canonical path `{path}`.'
|
|
1132
|
+
},
|
|
1133
|
+
|
|
1134
|
+
ConfigurationPreloadInProgress: {
|
|
1135
|
+
code: -120818,
|
|
1136
|
+
description: 'Another configuration preload is already in progress.'
|
|
1137
|
+
},
|
|
1138
|
+
|
|
1139
|
+
InvalidConnectionMapEntry: {
|
|
1140
|
+
code: -120819,
|
|
1141
|
+
description: 'Connection map entry at index {index} must define both serviceUrl and connection.'
|
|
1142
|
+
},
|
|
1143
|
+
|
|
1144
|
+
ConfigurationAlreadyPreloaded: {
|
|
1145
|
+
code: -120820,
|
|
1146
|
+
description: 'Configuration sources have already been preloaded for this process.'
|
|
1147
|
+
},
|
|
1148
|
+
|
|
1149
|
+
UnsupportedRuntimeConfigurationField: {
|
|
1150
|
+
code: -120821,
|
|
1151
|
+
description: 'Configuration source `{sourceName}` returned field `{path}`, which is not supported by the JavaScript SDK.'
|
|
1152
|
+
},
|
|
1153
|
+
|
|
1154
|
+
InvalidConfigurationSourceResult: {
|
|
1155
|
+
code: -120822,
|
|
1156
|
+
description: 'Configuration source `{sourceName}` returned an invalid source result.'
|
|
1157
|
+
},
|
|
1158
|
+
|
|
1159
|
+
InvalidConfigurationContext: {
|
|
1160
|
+
code: -120823,
|
|
1161
|
+
description: 'The configuration context is invalid. Create contexts with createConfigurationContext().'
|
|
1162
|
+
},
|
|
1163
|
+
|
|
1164
|
+
InvalidConfigurationSourceMode: {
|
|
1165
|
+
code: -120824,
|
|
1166
|
+
description: 'Configuration source `{sourceName}` uses unsupported mode `{mode}`. Use `fallback`, `overrideEnvironment`, or `enforce`.'
|
|
1167
|
+
},
|
|
1168
|
+
|
|
1169
|
+
JsonConfigurationFileReadFailed: {
|
|
1170
|
+
code: -120825,
|
|
1171
|
+
description: 'JSON configuration file `{filePath}` could not be read.'
|
|
1172
|
+
},
|
|
1173
|
+
|
|
1174
|
+
InvalidJsonConfigurationFile: {
|
|
1175
|
+
code: -120826,
|
|
1176
|
+
description: 'JSON configuration file `{filePath}` does not contain valid JSON.'
|
|
1177
|
+
},
|
|
1178
|
+
|
|
1179
|
+
JsonConfigurationDocumentRequired: {
|
|
1180
|
+
code: -120827,
|
|
1181
|
+
description: 'JSON configuration file `{filePath}` must contain an object at the document root.'
|
|
1182
|
+
},
|
|
1183
|
+
|
|
1046
1184
|
// ============================================================================
|
|
1047
1185
|
// Application Configuration Errors (-120850 to -120902)
|
|
1048
1186
|
// ============================================================================
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { authorizeJWT, buildJwksUri, clearJwksClients } from './auth/jwt-middlew
|
|
|
8
8
|
|
|
9
9
|
export * from './app'
|
|
10
10
|
export * from './cards'
|
|
11
|
+
export * from './configuration'
|
|
11
12
|
export * from './connector-client'
|
|
12
13
|
export { Errors as HostingErrors } from './errorHelper'
|
|
13
14
|
export * from './invoke'
|
|
@@ -5,7 +5,8 @@ import { SpanNames, trace } from '@microsoft/agents-telemetry'
|
|
|
5
5
|
import { HostingMetrics } from './metrics'
|
|
6
6
|
import { Activity, ConversationReference } from '@microsoft/agents-activity'
|
|
7
7
|
import { HandlerStorage } from '../app/auth/handlerStorage'
|
|
8
|
-
import type {
|
|
8
|
+
import type { StorageProvider } from '../storage'
|
|
9
|
+
import { asStorageV2 } from '../storage/storageCompatibility'
|
|
9
10
|
|
|
10
11
|
export const AgentApplicationTraceDefinitions = {
|
|
11
12
|
run: trace.define({
|
|
@@ -279,8 +280,8 @@ export const ProactiveTraceDefinitions = {
|
|
|
279
280
|
conversationId: '',
|
|
280
281
|
},
|
|
281
282
|
actions: ({ span }) => ({
|
|
282
|
-
async link (storage:
|
|
283
|
-
const item = (await storage.read([key]))?.[key] ?? {}
|
|
283
|
+
async link (storage: StorageProvider, key: string) {
|
|
284
|
+
const item = ((await asStorageV2(storage).read([key]))?.[key]?.value ?? {}) as { __link?: unknown }
|
|
284
285
|
return link(span, item)
|
|
285
286
|
}
|
|
286
287
|
}),
|
|
@@ -333,8 +334,8 @@ export const ProactiveTraceDefinitions = {
|
|
|
333
334
|
activityType: '',
|
|
334
335
|
},
|
|
335
336
|
actions: ({ span }) => ({
|
|
336
|
-
async link (storage:
|
|
337
|
-
const item = (await storage.read([key]))?.[key] ?? {}
|
|
337
|
+
async link (storage: StorageProvider, key: string) {
|
|
338
|
+
const item = ((await asStorageV2(storage).read([key]))?.[key]?.value ?? {}) as { __link?: unknown }
|
|
338
339
|
link(span, item)
|
|
339
340
|
}
|
|
340
341
|
}),
|
|
@@ -367,8 +368,8 @@ export const ProactiveTraceDefinitions = {
|
|
|
367
368
|
hasAutoSignIn: false,
|
|
368
369
|
},
|
|
369
370
|
actions: ({ span }) => ({
|
|
370
|
-
async link (storage:
|
|
371
|
-
const item = (await storage.read([key]))?.[key] ?? {}
|
|
371
|
+
async link (storage: StorageProvider, key: string) {
|
|
372
|
+
const item = ((await asStorageV2(storage).read([key]))?.[key]?.value ?? {}) as { __link?: unknown }
|
|
372
373
|
link(span, item)
|
|
373
374
|
}
|
|
374
375
|
}),
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ConfigurationContext,
|
|
8
|
+
getConfigurationSnapshot
|
|
9
|
+
} from './configuration/configuration'
|
|
10
|
+
import { loadModernEnvironmentConfiguration } from './configuration/environmentConfiguration'
|
|
11
|
+
import { mergeDefined } from './utils'
|
|
7
12
|
|
|
8
13
|
/** Hosts used by Microsoft channel callbacks and hosted attachments. */
|
|
9
14
|
const DEFAULT_MICROSOFT_HOSTS = Object.freeze([
|
|
@@ -17,11 +22,11 @@ const DEFAULT_MICROSOFT_HOSTS = Object.freeze([
|
|
|
17
22
|
'blob.core.windows.net'
|
|
18
23
|
])
|
|
19
24
|
|
|
20
|
-
const OUTBOUND_HOST_VALIDATOR_ENV_PREFIX = 'OutboundHostValidator__'
|
|
21
|
-
const OUTBOUND_HOST_VALIDATOR_ENV_PREFIX_UPPER = OUTBOUND_HOST_VALIDATOR_ENV_PREFIX.toUpperCase()
|
|
22
|
-
|
|
23
25
|
/** Configuration for the shared outbound-host allowlist. */
|
|
24
26
|
export interface OutboundHostValidatorOptions {
|
|
27
|
+
/** Optional host-scoped external configuration. */
|
|
28
|
+
configurationContext?: ConfigurationContext
|
|
29
|
+
|
|
25
30
|
/** Enables allowlist enforcement. Defaults to `false`. */
|
|
26
31
|
enabled?: boolean
|
|
27
32
|
|
|
@@ -56,14 +61,17 @@ export class OutboundHostValidator implements OutboundUrlPolicy {
|
|
|
56
61
|
private readonly suffixes: ReadonlySet<string>
|
|
57
62
|
|
|
58
63
|
public constructor (options: OutboundHostValidatorOptions = {}) {
|
|
59
|
-
|
|
64
|
+
const resolved = options.configurationContext
|
|
65
|
+
? resolveOutboundHostValidatorOptions(options)
|
|
66
|
+
: options
|
|
67
|
+
this.enabled = resolved.enabled ?? false
|
|
60
68
|
|
|
61
69
|
const suffixes = new Set<string>()
|
|
62
|
-
if (
|
|
70
|
+
if (resolved.includeDefaultMicrosoftHosts ?? true) {
|
|
63
71
|
for (const host of DEFAULT_MICROSOFT_HOSTS) suffixes.add(host)
|
|
64
72
|
}
|
|
65
73
|
|
|
66
|
-
for (const host of
|
|
74
|
+
for (const host of resolved.hosts ?? []) {
|
|
67
75
|
const normalized = normalizeConfiguredHost(host)
|
|
68
76
|
if (normalized) suffixes.add(normalized)
|
|
69
77
|
}
|
|
@@ -93,47 +101,32 @@ export class OutboundHostValidator implements OutboundUrlPolicy {
|
|
|
93
101
|
* indexed values such as `Hosts__0`, `Hosts__1`, and so on.
|
|
94
102
|
*/
|
|
95
103
|
export function loadOutboundHostValidatorOptionsFromEnv (): OutboundHostValidatorOptions {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const hosts: string[] = []
|
|
99
|
-
|
|
100
|
-
for (const [envKey, rawValue] of Object.entries(process.env)) {
|
|
101
|
-
const upperKey = envKey.toUpperCase()
|
|
102
|
-
if (!upperKey.startsWith(OUTBOUND_HOST_VALIDATOR_ENV_PREFIX_UPPER)) continue
|
|
103
|
-
|
|
104
|
-
const property = envKey.substring(OUTBOUND_HOST_VALIDATOR_ENV_PREFIX.length)
|
|
105
|
-
const upperProperty = property.toUpperCase()
|
|
106
|
-
|
|
107
|
-
if (upperProperty === 'ENABLED') {
|
|
108
|
-
const value = parseBooleanEnv(rawValue)
|
|
109
|
-
if (value !== undefined) result.enabled = value
|
|
110
|
-
} else if (upperProperty === 'INCLUDEDEFAULTMICROSOFTHOSTS') {
|
|
111
|
-
const value = parseBooleanEnv(rawValue)
|
|
112
|
-
if (value !== undefined) result.includeDefaultMicrosoftHosts = value
|
|
113
|
-
} else if (upperProperty === 'HOSTS' && rawValue) {
|
|
114
|
-
hosts.push(...rawValue.split(',').map(host => host.trim()).filter(Boolean))
|
|
115
|
-
} else {
|
|
116
|
-
const match = /^HOSTS__(\d+)$/i.exec(property)
|
|
117
|
-
if (match && rawValue?.trim()) indexedHosts.set(Number(match[1]), rawValue.trim())
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
for (const [, host] of [...indexedHosts.entries()].sort(([left], [right]) => left - right)) {
|
|
122
|
-
hosts.push(host)
|
|
123
|
-
}
|
|
124
|
-
if (hosts.length > 0) result.hosts = hosts
|
|
104
|
+
return { ...loadModernEnvironmentConfiguration().outboundHostValidator }
|
|
105
|
+
}
|
|
125
106
|
|
|
126
|
-
|
|
107
|
+
/** Creates a validator using the shared configuration precedence. */
|
|
108
|
+
export function createOutboundHostValidator (options: OutboundHostValidatorOptions = {}): OutboundHostValidator {
|
|
109
|
+
return new OutboundHostValidator(resolveOutboundHostValidatorOptions(options))
|
|
127
110
|
}
|
|
128
111
|
|
|
129
|
-
|
|
130
|
-
|
|
112
|
+
function resolveOutboundHostValidatorOptions (
|
|
113
|
+
options: OutboundHostValidatorOptions
|
|
114
|
+
): OutboundHostValidatorOptions {
|
|
115
|
+
const external = getConfigurationSnapshot(options.configurationContext)
|
|
131
116
|
const fromEnv = loadOutboundHostValidatorOptionsFromEnv()
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
117
|
+
const direct: OutboundHostValidatorOptions = {}
|
|
118
|
+
if (options.enabled !== undefined) direct.enabled = options.enabled
|
|
119
|
+
if (options.includeDefaultMicrosoftHosts !== undefined) {
|
|
120
|
+
direct.includeDefaultMicrosoftHosts = options.includeDefaultMicrosoftHosts
|
|
121
|
+
}
|
|
122
|
+
if (options.hosts !== undefined) direct.hosts = options.hosts
|
|
123
|
+
return mergeDefined<OutboundHostValidatorOptions>(
|
|
124
|
+
external.fallback.outboundHostValidator,
|
|
125
|
+
fromEnv,
|
|
126
|
+
external.overrideEnvironment.outboundHostValidator,
|
|
127
|
+
direct,
|
|
128
|
+
external.enforce.outboundHostValidator
|
|
129
|
+
)
|
|
137
130
|
}
|
|
138
131
|
|
|
139
132
|
function getUrlHost (input: string | URL | null | undefined): string | undefined {
|
package/src/state/agentState.ts
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { StorageKeyFactory, StorageOperationStatus, StorageProvider, StorageV2, StorageWriteMode, StoreItem } from '../storage/storage'
|
|
7
|
+
import {
|
|
8
|
+
asStorageV2,
|
|
9
|
+
assertAgentStateWriteSucceeded,
|
|
10
|
+
assertStorageDeleteSucceeded,
|
|
11
|
+
getStorageReadValue,
|
|
12
|
+
isStorageV2,
|
|
13
|
+
} from '../storage/storageCompatibility'
|
|
7
14
|
import { TurnContext } from '../turnContext'
|
|
8
15
|
import { createHash } from 'node:crypto'
|
|
9
16
|
import { AgentStatePropertyAccessor } from './agentStatePropertyAccesor'
|
|
@@ -26,6 +33,10 @@ export interface CachedAgentState {
|
|
|
26
33
|
* Hash of the state used to detect changes
|
|
27
34
|
*/
|
|
28
35
|
hash: string;
|
|
36
|
+
/** Version returned when the state was loaded, used to reject stale V2 writes. */
|
|
37
|
+
version?: string;
|
|
38
|
+
/** Whether the state was not found when it was loaded. */
|
|
39
|
+
isNew?: boolean;
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
/**
|
|
@@ -62,13 +73,17 @@ export interface CustomKey {
|
|
|
62
73
|
export class AgentState {
|
|
63
74
|
private readonly stateKey = Symbol('state')
|
|
64
75
|
|
|
76
|
+
private get internalStorage (): StorageV2 {
|
|
77
|
+
return asStorageV2(this.storage)
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
/**
|
|
66
81
|
* Creates a new instance of AgentState.
|
|
67
82
|
*
|
|
68
83
|
* @param storage The storage provider used to persist state between turns
|
|
69
84
|
* @param storageKey A factory function that generates keys for storing state data
|
|
70
85
|
*/
|
|
71
|
-
constructor (protected storage:
|
|
86
|
+
constructor (protected storage: StorageProvider, protected storageKey: StorageKeyFactory) {}
|
|
72
87
|
|
|
73
88
|
/**
|
|
74
89
|
* Creates a property accessor for the specified property.
|
|
@@ -101,11 +116,15 @@ export class AgentState {
|
|
|
101
116
|
if (force || !cached || !cached.state) {
|
|
102
117
|
const key: string = await this.getStorageOrCustomKey(customKey, context)
|
|
103
118
|
logger.info(`Reading storage with key ${key}`)
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
const state: any = storedItem[key] || {}
|
|
119
|
+
const storedItems = await this.internalStorage.read<Record<string, any>>([key])
|
|
120
|
+
const state: any = getStorageReadValue(storedItems, key) ?? {}
|
|
107
121
|
const hash: string = this.calculateChangeHash(state)
|
|
108
|
-
context.turnState.set(this.stateKey, {
|
|
122
|
+
context.turnState.set(this.stateKey, {
|
|
123
|
+
state,
|
|
124
|
+
hash,
|
|
125
|
+
version: storedItems[key]?.version,
|
|
126
|
+
isNew: storedItems[key]?.status === StorageOperationStatus.NotFound,
|
|
127
|
+
})
|
|
109
128
|
|
|
110
129
|
return state
|
|
111
130
|
}
|
|
@@ -130,15 +149,21 @@ export class AgentState {
|
|
|
130
149
|
if (!cached) {
|
|
131
150
|
cached = { state: {}, hash: '' }
|
|
132
151
|
}
|
|
133
|
-
cached.state.eTag = '*'
|
|
134
|
-
const changes: StoreItem = {} as StoreItem
|
|
135
|
-
|
|
136
152
|
const key: string = await this.getStorageOrCustomKey(customKey, context)
|
|
137
153
|
|
|
138
|
-
changes[key] = cached.state
|
|
139
|
-
|
|
140
154
|
logger.info(`Writing storage with key ${key}`)
|
|
141
|
-
await this.
|
|
155
|
+
const results = await this.internalStorage.write(
|
|
156
|
+
{ [key]: cached.state },
|
|
157
|
+
cached.version !== undefined
|
|
158
|
+
? { expectedVersion: cached.version }
|
|
159
|
+
: cached.isNew && isStorageV2(this.storage)
|
|
160
|
+
? { mode: StorageWriteMode.CreateOnly }
|
|
161
|
+
: undefined
|
|
162
|
+
)
|
|
163
|
+
assertAgentStateWriteSucceeded(results, key, this.constructor.name)
|
|
164
|
+
const result = results[key]
|
|
165
|
+
cached.version = result.version
|
|
166
|
+
cached.isNew = false
|
|
142
167
|
cached.hash = this.calculateChangeHash(cached.state)
|
|
143
168
|
context.turnState.set(this.stateKey, cached)
|
|
144
169
|
}
|
|
@@ -195,7 +220,8 @@ export class AgentState {
|
|
|
195
220
|
}
|
|
196
221
|
const key = await this.getStorageOrCustomKey(customKey, context)
|
|
197
222
|
logger.info(`Deleting storage with key ${key}`)
|
|
198
|
-
await this.
|
|
223
|
+
const results = await this.internalStorage.delete([key])
|
|
224
|
+
assertStorageDeleteSucceeded(results, [key])
|
|
199
225
|
}
|
|
200
226
|
|
|
201
227
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { AgentState } from './agentState'
|
|
7
|
-
import {
|
|
7
|
+
import { StorageProvider } from '../storage/storage'
|
|
8
8
|
import { TurnContext } from '../turnContext'
|
|
9
9
|
import { Activity, ExceptionHelper } from '@microsoft/agents-activity'
|
|
10
10
|
import { Errors } from '../errorHelper'
|
|
@@ -17,7 +17,7 @@ export class ConversationState extends AgentState {
|
|
|
17
17
|
* Creates a new instance of ConversationState.
|
|
18
18
|
* @param storage The storage provider.
|
|
19
19
|
*/
|
|
20
|
-
constructor (storage:
|
|
20
|
+
constructor (storage: StorageProvider, private readonly namespace: string = '') {
|
|
21
21
|
super(storage, (context: TurnContext) => {
|
|
22
22
|
const key: string = this.getStorageKey(context)
|
|
23
23
|
|
package/src/state/userState.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { AgentState } from './agentState'
|
|
7
|
-
import {
|
|
7
|
+
import { StorageProvider } from '../storage/storage'
|
|
8
8
|
import { TurnContext } from '../turnContext'
|
|
9
9
|
import { Activity, ExceptionHelper } from '@microsoft/agents-activity'
|
|
10
10
|
import { Errors } from '../errorHelper'
|
|
@@ -17,7 +17,7 @@ export class UserState extends AgentState {
|
|
|
17
17
|
* Creates a new instance of UserState.
|
|
18
18
|
* @param storage The storage provider.
|
|
19
19
|
*/
|
|
20
|
-
constructor (storage:
|
|
20
|
+
constructor (storage: StorageProvider, private readonly namespace: string = '') {
|
|
21
21
|
super(storage, (context: TurnContext) => {
|
|
22
22
|
const key: string = this.getStorageKey(context)
|
|
23
23
|
|
package/src/statusCodes.ts
CHANGED
|
@@ -78,6 +78,12 @@ export enum StatusCodes {
|
|
|
78
78
|
*/
|
|
79
79
|
UPGRADE_REQUIRED = 426,
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* The user has sent too many requests in a given amount of time.
|
|
83
|
+
* Used when rate limiting or throttling prevents a turn from being processed.
|
|
84
|
+
*/
|
|
85
|
+
TOO_MANY_REQUESTS = 429,
|
|
86
|
+
|
|
81
87
|
/**
|
|
82
88
|
* The server encountered an unexpected condition that prevented it from fulfilling the request.
|
|
83
89
|
* Generic error message when an unexpected agent hosting error occurs
|