@microsoft/agents-hosting 1.9.0-beta.3.gb2d23c1c44 → 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.
Files changed (150) hide show
  1. package/README.md +182 -4
  2. package/dist/package.json +3 -3
  3. package/dist/src/app/agentApplication.d.ts +4 -3
  4. package/dist/src/app/agentApplication.js +24 -21
  5. package/dist/src/app/agentApplication.js.map +1 -1
  6. package/dist/src/app/agentApplicationBuilder.d.ts +9 -2
  7. package/dist/src/app/agentApplicationBuilder.js +9 -0
  8. package/dist/src/app/agentApplicationBuilder.js.map +1 -1
  9. package/dist/src/app/agentApplicationOptions.d.ts +16 -4
  10. package/dist/src/app/auth/authorization.d.ts +54 -0
  11. package/dist/src/app/auth/authorization.js +63 -2
  12. package/dist/src/app/auth/authorization.js.map +1 -1
  13. package/dist/src/app/auth/authorizationManager.d.ts +0 -8
  14. package/dist/src/app/auth/authorizationManager.js +104 -178
  15. package/dist/src/app/auth/authorizationManager.js.map +1 -1
  16. package/dist/src/app/auth/handlerStorage.d.ts +5 -3
  17. package/dist/src/app/auth/handlerStorage.js +36 -10
  18. package/dist/src/app/auth/handlerStorage.js.map +1 -1
  19. package/dist/src/app/auth/types.d.ts +2 -2
  20. package/dist/src/app/index.d.ts +1 -0
  21. package/dist/src/app/proactive/proactive.js +10 -6
  22. package/dist/src/app/proactive/proactive.js.map +1 -1
  23. package/dist/src/app/proactive/proactiveOptions.d.ts +2 -2
  24. package/dist/src/app/rateLimit.d.ts +315 -0
  25. package/dist/src/app/rateLimit.js +333 -0
  26. package/dist/src/app/rateLimit.js.map +1 -0
  27. package/dist/src/app/turnState.d.ts +6 -3
  28. package/dist/src/app/turnState.js +43 -4
  29. package/dist/src/app/turnState.js.map +1 -1
  30. package/dist/src/auth/authConfiguration.d.ts +10 -3
  31. package/dist/src/auth/authConfiguration.js +292 -259
  32. package/dist/src/auth/authConfiguration.js.map +1 -1
  33. package/dist/src/auth/delegatedTokenCredential.d.ts +29 -0
  34. package/dist/src/auth/delegatedTokenCredential.js +49 -0
  35. package/dist/src/auth/delegatedTokenCredential.js.map +1 -0
  36. package/dist/src/auth/msal/msalTokenCredential.js +1 -1
  37. package/dist/src/auth/msal/msalTokenCredential.js.map +1 -1
  38. package/dist/src/auth/settings.d.ts +8 -70
  39. package/dist/src/auth/settings.js +5 -67
  40. package/dist/src/auth/settings.js.map +1 -1
  41. package/dist/src/cloudAdapter.d.ts +5 -0
  42. package/dist/src/cloudAdapter.js +13 -103
  43. package/dist/src/cloudAdapter.js.map +1 -1
  44. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.d.ts +23 -0
  45. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js +183 -0
  46. package/dist/src/configuration/botFrameworkEnvironmentCompatibility.js.map +1 -0
  47. package/dist/src/configuration/configuration.d.ts +83 -0
  48. package/dist/src/configuration/configuration.js +836 -0
  49. package/dist/src/configuration/configuration.js.map +1 -0
  50. package/dist/src/configuration/configurationSource.d.ts +57 -0
  51. package/dist/src/configuration/configurationSource.js +7 -0
  52. package/dist/src/configuration/configurationSource.js.map +1 -0
  53. package/dist/src/configuration/environmentConfiguration.d.ts +14 -0
  54. package/dist/src/configuration/environmentConfiguration.js +271 -0
  55. package/dist/src/configuration/environmentConfiguration.js.map +1 -0
  56. package/dist/src/configuration/index.d.ts +7 -0
  57. package/dist/src/configuration/index.js +14 -0
  58. package/dist/src/configuration/index.js.map +1 -0
  59. package/dist/src/configuration/jsonFileConfigurationSource.d.ts +15 -0
  60. package/dist/src/configuration/jsonFileConfigurationSource.js +58 -0
  61. package/dist/src/configuration/jsonFileConfigurationSource.js.map +1 -0
  62. package/dist/src/createCloudAdapter.d.ts +30 -5
  63. package/dist/src/createCloudAdapter.js +17 -10
  64. package/dist/src/createCloudAdapter.js.map +1 -1
  65. package/dist/src/errorHelper.js +124 -5
  66. package/dist/src/errorHelper.js.map +1 -1
  67. package/dist/src/index.d.ts +1 -0
  68. package/dist/src/index.js +1 -0
  69. package/dist/src/index.js.map +1 -1
  70. package/dist/src/observability/traces.d.ts +6 -4
  71. package/dist/src/observability/traces.js +10 -9
  72. package/dist/src/observability/traces.js.map +1 -1
  73. package/dist/src/outboundHostValidator.d.ts +4 -1
  74. package/dist/src/outboundHostValidator.js +25 -48
  75. package/dist/src/outboundHostValidator.js.map +1 -1
  76. package/dist/src/state/agentState.d.ts +8 -3
  77. package/dist/src/state/agentState.js +26 -8
  78. package/dist/src/state/agentState.js.map +1 -1
  79. package/dist/src/state/conversationState.d.ts +2 -2
  80. package/dist/src/state/conversationState.js.map +1 -1
  81. package/dist/src/state/userState.d.ts +2 -2
  82. package/dist/src/state/userState.js.map +1 -1
  83. package/dist/src/statusCodes.d.ts +5 -0
  84. package/dist/src/statusCodes.js +5 -0
  85. package/dist/src/statusCodes.js.map +1 -1
  86. package/dist/src/storage/fileStorage.d.ts +83 -68
  87. package/dist/src/storage/fileStorage.js +279 -105
  88. package/dist/src/storage/fileStorage.js.map +1 -1
  89. package/dist/src/storage/index.d.ts +1 -0
  90. package/dist/src/storage/index.js +1 -0
  91. package/dist/src/storage/index.js.map +1 -1
  92. package/dist/src/storage/memoryStorage.d.ts +85 -60
  93. package/dist/src/storage/memoryStorage.js +244 -87
  94. package/dist/src/storage/memoryStorage.js.map +1 -1
  95. package/dist/src/storage/storage.d.ts +100 -2
  96. package/dist/src/storage/storage.js +25 -0
  97. package/dist/src/storage/storage.js.map +1 -1
  98. package/dist/src/storage/storageCompatibility.d.ts +17 -0
  99. package/dist/src/storage/storageCompatibility.js +157 -0
  100. package/dist/src/storage/storageCompatibility.js.map +1 -0
  101. package/dist/src/storage/storageExpiry.d.ts +6 -0
  102. package/dist/src/storage/storageExpiry.js +20 -0
  103. package/dist/src/storage/storageExpiry.js.map +1 -0
  104. package/dist/src/utils/env.d.ts +43 -0
  105. package/dist/src/utils/env.js +42 -6
  106. package/dist/src/utils/env.js.map +1 -1
  107. package/dist/src/utils.d.ts +1 -0
  108. package/dist/src/utils.js +10 -1
  109. package/dist/src/utils.js.map +1 -1
  110. package/package.json +3 -3
  111. package/src/app/agentApplication.ts +27 -14
  112. package/src/app/agentApplicationBuilder.ts +13 -2
  113. package/src/app/agentApplicationOptions.ts +18 -4
  114. package/src/app/auth/authorization.ts +67 -2
  115. package/src/app/auth/authorizationManager.ts +126 -204
  116. package/src/app/auth/handlerStorage.ts +51 -7
  117. package/src/app/auth/types.ts +2 -2
  118. package/src/app/index.ts +7 -0
  119. package/src/app/proactive/proactive.ts +19 -9
  120. package/src/app/proactive/proactiveOptions.ts +2 -2
  121. package/src/app/rateLimit.ts +659 -0
  122. package/src/app/turnState.ts +50 -7
  123. package/src/auth/authConfiguration.ts +415 -260
  124. package/src/auth/delegatedTokenCredential.ts +49 -0
  125. package/src/auth/msal/msalTokenCredential.ts +1 -1
  126. package/src/auth/settings.ts +5 -82
  127. package/src/cloudAdapter.ts +38 -113
  128. package/src/configuration/botFrameworkEnvironmentCompatibility.ts +245 -0
  129. package/src/configuration/configuration.ts +1076 -0
  130. package/src/configuration/configurationSource.ts +76 -0
  131. package/src/configuration/environmentConfiguration.ts +377 -0
  132. package/src/configuration/index.ts +19 -0
  133. package/src/configuration/jsonFileConfigurationSource.ts +74 -0
  134. package/src/createCloudAdapter.ts +52 -9
  135. package/src/errorHelper.ts +151 -5
  136. package/src/index.ts +1 -0
  137. package/src/observability/traces.ts +8 -7
  138. package/src/outboundHostValidator.ts +37 -44
  139. package/src/state/agentState.ts +39 -13
  140. package/src/state/conversationState.ts +2 -2
  141. package/src/state/userState.ts +2 -2
  142. package/src/statusCodes.ts +6 -0
  143. package/src/storage/fileStorage.ts +299 -106
  144. package/src/storage/index.ts +1 -0
  145. package/src/storage/memoryStorage.ts +268 -85
  146. package/src/storage/storage.ts +114 -2
  147. package/src/storage/storageCompatibility.ts +185 -0
  148. package/src/storage/storageExpiry.ts +21 -0
  149. package/src/utils/env.ts +63 -0
  150. package/src/utils.ts +10 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ExceptionHelper } from '@microsoft/agents-activity'
7
+ import { Errors } from '../errorHelper'
8
+ import {
9
+ Storage,
10
+ StorageDeleteOptions,
11
+ StorageDeleteResults,
12
+ StorageOperationStatus,
13
+ StorageProvider,
14
+ StorageReadResults,
15
+ StorageV2,
16
+ StorageWriteMode,
17
+ StorageWriteOptions,
18
+ StorageWriteResults,
19
+ } from './storage'
20
+
21
+ /** Returns true when a storage implementation declares the V2 contract. */
22
+ export function isStorageV2 (storage: StorageProvider): storage is StorageV2 {
23
+ return storage instanceof StorageV2
24
+ }
25
+
26
+ /** Converts a supported storage implementation to the V2 contract. */
27
+ export function asStorageV2 (storage: StorageProvider): StorageV2 {
28
+ return isStorageV2(storage) ? storage : new StorageToStorageV2Adapter(storage)
29
+ }
30
+
31
+ /** Returns a successful V2 read value, maps not-found to undefined, and rejects invalid results. */
32
+ export function getStorageReadValue<T extends object> (results: StorageReadResults<T> | null | undefined, key: string): T | undefined {
33
+ const result = results?.[key]
34
+ if (result?.status === StorageOperationStatus.NotFound) return undefined
35
+ if (result?.status === StorageOperationStatus.Succeeded) return result.value
36
+ throwStorageResultError('read', key, result?.status)
37
+ }
38
+
39
+ /** Adapts the legacy storage contract to version 2 where its semantics allow it. */
40
+ class StorageToStorageV2Adapter extends StorageV2 {
41
+ constructor (private readonly storage: Storage) {
42
+ super()
43
+ }
44
+
45
+ async read<T extends object = Record<string, unknown>> (keys: string[]): Promise<StorageReadResults<T>> {
46
+ validateKeys(keys)
47
+ if (keys.length === 0) return {}
48
+
49
+ const items = await this.storage.read(keys)
50
+ return Object.fromEntries(keys.map(key => {
51
+ const value = items[key]
52
+ return [key, Object.prototype.hasOwnProperty.call(items, key)
53
+ ? { key, status: StorageOperationStatus.Succeeded, value: value as T, version: value?.eTag as string | undefined }
54
+ : { key, status: StorageOperationStatus.NotFound }]
55
+ }))
56
+ }
57
+
58
+ async write<T extends object = Record<string, unknown>> (changes: Record<string, T>, options?: StorageWriteOptions): Promise<StorageWriteResults> {
59
+ validateChanges(changes)
60
+ if (options?.mode !== undefined && options.mode !== StorageWriteMode.Upsert) {
61
+ throwUnsupportedOption('mode')
62
+ }
63
+ if (options?.ttl !== undefined) {
64
+ throwUnsupportedOption('ttl')
65
+ }
66
+ validateExpectedVersion(options?.expectedVersion)
67
+ if (Object.keys(changes).length === 0) return {}
68
+ const legacyChanges = Object.fromEntries(Object.entries(changes).map(([key, value]) => [
69
+ key,
70
+ options?.expectedVersion === undefined
71
+ ? removeLegacyETag(value)
72
+ : { ...removeLegacyETag(value), eTag: options.expectedVersion },
73
+ ]))
74
+ await this.storage.write(legacyChanges)
75
+ return Object.fromEntries(Object.keys(changes).map(key => [key, { key, status: StorageOperationStatus.Succeeded }]))
76
+ }
77
+
78
+ async delete (keys: string[], options?: StorageDeleteOptions): Promise<StorageDeleteResults> {
79
+ validateDeleteKeys(keys)
80
+ validateExpectedVersion(options?.expectedVersion)
81
+ if (options?.expectedVersion !== undefined) {
82
+ throwUnsupportedOption('expectedVersion')
83
+ }
84
+ if (keys.length === 0) return {}
85
+
86
+ await this.storage.delete(keys)
87
+ return Object.fromEntries(keys.map(key => [key, { key, status: StorageOperationStatus.Succeeded }]))
88
+ }
89
+ }
90
+
91
+ function validateKeys (keys: string[]): void {
92
+ if (!Array.isArray(keys)) {
93
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageReadKeysRequired)
94
+ }
95
+ if (keys.some(key => typeof key !== 'string' || key.trim() === '')) {
96
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageV2KeyRequired)
97
+ }
98
+ }
99
+
100
+ function validateDeleteKeys (keys: string[]): void {
101
+ if (!Array.isArray(keys)) {
102
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageDeleteKeysRequired)
103
+ }
104
+ if (keys.some(key => typeof key !== 'string' || key.trim() === '')) {
105
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageV2KeyRequired)
106
+ }
107
+ }
108
+
109
+ function validateChanges (changes: Record<string, unknown>): void {
110
+ if (changes === null || typeof changes !== 'object' || Array.isArray(changes)) {
111
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageWriteChangesRequired)
112
+ }
113
+ if (Object.keys(changes).some(key => key.trim() === '')) {
114
+ throw ExceptionHelper.generateException(ReferenceError, Errors.StorageV2KeyRequired)
115
+ }
116
+ }
117
+
118
+ function removeLegacyETag<T> (value: T): T {
119
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) return value
120
+ const { eTag: _eTag, ...withoutETag } = value as Record<string, unknown>
121
+ return withoutETag as T
122
+ }
123
+
124
+ function validateExpectedVersion (expectedVersion: string | undefined): void {
125
+ if (expectedVersion === '') {
126
+ throw ExceptionHelper.generateException(RangeError, Errors.StorageV2ExpectedVersionEmpty)
127
+ }
128
+ }
129
+
130
+ function throwUnsupportedOption (option: string): never {
131
+ throw ExceptionHelper.generateException(Error, Errors.StorageV2UnsupportedOption, undefined, { option })
132
+ }
133
+
134
+ /** Throws when a V2 write did not succeed for every requested key. */
135
+ export function assertStorageWriteSucceeded (results: StorageWriteResults | null | undefined, keys: string[]): void {
136
+ assertStorageResults('write', results, keys, new Set([StorageOperationStatus.Succeeded]))
137
+ }
138
+
139
+ /** Throws the state-specific concurrency error when a state write does not succeed. */
140
+ export function assertAgentStateWriteSucceeded (
141
+ results: StorageWriteResults | null | undefined,
142
+ key: string,
143
+ name: string
144
+ ): void {
145
+ const status = results?.[key]?.status
146
+ if (status !== StorageOperationStatus.Succeeded) {
147
+ throw ExceptionHelper.generateException(Error, Errors.AgentStateWriteConflict, undefined, {
148
+ name,
149
+ key,
150
+ status: status ?? 'missing',
151
+ })
152
+ }
153
+ }
154
+
155
+ /** Throws when a V2 delete did not complete with idempotent V1 semantics. */
156
+ export function assertStorageDeleteSucceeded (results: StorageDeleteResults | null | undefined, keys: string[]): void {
157
+ assertStorageResults(
158
+ 'delete',
159
+ results,
160
+ keys,
161
+ new Set([StorageOperationStatus.Succeeded, StorageOperationStatus.NotFound])
162
+ )
163
+ }
164
+
165
+ function assertStorageResults (
166
+ operation: 'write' | 'delete',
167
+ results: StorageWriteResults | StorageDeleteResults | null | undefined,
168
+ keys: string[],
169
+ acceptedStatuses: ReadonlySet<StorageOperationStatus>
170
+ ): void {
171
+ for (const key of keys) {
172
+ const status = results?.[key]?.status
173
+ if (status === undefined || !acceptedStatuses.has(status)) {
174
+ throwStorageResultError(operation, key, status)
175
+ }
176
+ }
177
+ }
178
+
179
+ function throwStorageResultError (operation: 'read' | 'write' | 'delete', key: string, status?: StorageOperationStatus): never {
180
+ throw ExceptionHelper.generateException(Error, Errors.StorageV2OperationFailed, undefined, {
181
+ operation,
182
+ key,
183
+ status: status ?? 'missing',
184
+ })
185
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { StorageWriteOptions } from './storage'
7
+ import { ExceptionHelper } from '@microsoft/agents-activity'
8
+ import { Errors } from '../errorHelper'
9
+
10
+ export function getStorageWriteExpiry (options?: StorageWriteOptions): number | undefined {
11
+ const ttl = options?.ttl
12
+ if (ttl === undefined) {
13
+ return undefined
14
+ }
15
+
16
+ if (!Number.isFinite(ttl) || ttl <= 0) {
17
+ throw ExceptionHelper.generateException(RangeError, Errors.InvalidStorageTtl)
18
+ }
19
+
20
+ return Date.now() + ttl * 1000
21
+ }
package/src/utils/env.ts CHANGED
@@ -10,6 +10,69 @@
10
10
  * normalize behavior across the package without growing the public API.
11
11
  */
12
12
 
13
+ export interface LoadEnv {
14
+ [upperKey: string]: { key: string, value: any }
15
+ }
16
+
17
+ type ParserSettings<K extends string> = {
18
+ [key in K]: (value: string) => { key?: string, value?: any } | undefined
19
+ }
20
+
21
+ /**
22
+ * Indexes non-empty environment values case-insensitively while preserving
23
+ * their original key spelling.
24
+ */
25
+ export function loadEnvSettings (
26
+ callback: (key: string, value: string) => void,
27
+ environment: NodeJS.ProcessEnv = process.env
28
+ ): LoadEnv {
29
+ const env: LoadEnv = {}
30
+ for (const [envKey, envValue] of Object.entries(environment)) {
31
+ if (!envValue?.trim()) {
32
+ continue
33
+ }
34
+
35
+ env[envKey.toUpperCase()] = { key: envKey, value: envValue }
36
+ callback(envKey, envValue)
37
+ }
38
+
39
+ return env
40
+ }
41
+
42
+ /**
43
+ * Creates a case-insensitive parser for a fixed set of environment keys.
44
+ */
45
+ export function envParser<K extends string> (
46
+ settings: ParserSettings<K> & ThisType<ParserSettings<K>>
47
+ ) {
48
+ const keys = Object.keys(settings) as K[]
49
+ const upperKeys = keys.reduce((acc, key) => {
50
+ acc[key.toUpperCase()] = key
51
+ return acc
52
+ }, {} as Record<string, K>)
53
+
54
+ return {
55
+ keys,
56
+ parse (key: K, value: string) {
57
+ const match = upperKeys[key.toUpperCase()]
58
+ if (!match) {
59
+ return {}
60
+ }
61
+
62
+ const result = settings[match](value)
63
+ return { key: result?.key ?? match, value: result?.value }
64
+ }
65
+ }
66
+ }
67
+
68
+ export const envParserUtils = {
69
+ bypass: (value: string) => ({ value }),
70
+ redirect: <Parser extends ReturnType<typeof envParser>>(
71
+ parser: Parser,
72
+ key: Parameters<Parser['parse']>[0]
73
+ ) => (value: string) => parser.parse(key, value)
74
+ }
75
+
13
76
  /**
14
77
  * Parses an environment-variable string into a boolean.
15
78
  *
package/src/utils.ts CHANGED
@@ -12,3 +12,13 @@ export const prune = <T extends Record<string, any>>(obj: T) => {
12
12
  const entries = Object.entries(obj).filter(([, value]) => value !== undefined)
13
13
  return Object.fromEntries(entries) as T
14
14
  }
15
+
16
+ export const mergeDefined = <T extends Record<string, any>>(
17
+ ...layers: readonly (Partial<T> | undefined)[]
18
+ ): T => {
19
+ const result: Partial<T> = {}
20
+ for (const layer of layers) {
21
+ if (layer) Object.assign(result, prune(layer))
22
+ }
23
+ return result as T
24
+ }