@microsoft/agents-hosting 1.0.0 → 1.0.3-g444d99f704

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 (72) hide show
  1. package/dist/package.json +2 -2
  2. package/dist/src/activityHandler.d.ts +0 -1
  3. package/dist/src/activityHandler.js +0 -1
  4. package/dist/src/activityHandler.js.map +1 -1
  5. package/dist/src/agent-client/agentResponseHandler.d.ts +6 -6
  6. package/dist/src/agent-client/agentResponseHandler.js +6 -6
  7. package/dist/src/app/adaptiveCards/adaptiveCardsActions.d.ts +12 -4
  8. package/dist/src/app/adaptiveCards/adaptiveCardsActions.js +5 -1
  9. package/dist/src/app/adaptiveCards/adaptiveCardsActions.js.map +1 -1
  10. package/dist/src/app/agentApplication.d.ts +24 -7
  11. package/dist/src/app/agentApplication.js +24 -7
  12. package/dist/src/app/agentApplication.js.map +1 -1
  13. package/dist/src/app/appRoute.d.ts +8 -4
  14. package/dist/src/app/attachmentDownloader.d.ts +3 -1
  15. package/dist/src/app/attachmentDownloader.js +3 -1
  16. package/dist/src/app/attachmentDownloader.js.map +1 -1
  17. package/dist/src/app/authorization.d.ts +26 -18
  18. package/dist/src/app/authorization.js +26 -18
  19. package/dist/src/app/authorization.js.map +1 -1
  20. package/dist/src/app/routeRank.d.ts +10 -3
  21. package/dist/src/app/routeRank.js +10 -3
  22. package/dist/src/app/routeRank.js.map +1 -1
  23. package/dist/src/app/streaming/streamingResponse.d.ts +23 -2
  24. package/dist/src/app/streaming/streamingResponse.js +23 -2
  25. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  26. package/dist/src/app/turnState.d.ts +69 -19
  27. package/dist/src/app/turnState.js +69 -19
  28. package/dist/src/app/turnState.js.map +1 -1
  29. package/dist/src/auth/authConfiguration.d.ts +16 -9
  30. package/dist/src/auth/authConfiguration.js +11 -6
  31. package/dist/src/auth/authConfiguration.js.map +1 -1
  32. package/dist/src/auth/jwt-middleware.js +26 -18
  33. package/dist/src/auth/jwt-middleware.js.map +1 -1
  34. package/dist/src/cards/adaptiveCard.d.ts +1 -1
  35. package/dist/src/headerPropagation.d.ts +18 -6
  36. package/dist/src/state/agentState.d.ts +23 -7
  37. package/dist/src/state/agentState.js +19 -7
  38. package/dist/src/state/agentState.js.map +1 -1
  39. package/dist/src/state/agentStatePropertyAccesor.d.ts +63 -41
  40. package/dist/src/state/agentStatePropertyAccesor.js +43 -32
  41. package/dist/src/state/agentStatePropertyAccesor.js.map +1 -1
  42. package/dist/src/storage/fileStorage.d.ts +8 -6
  43. package/dist/src/storage/fileStorage.js +8 -6
  44. package/dist/src/storage/fileStorage.js.map +1 -1
  45. package/dist/src/storage/memoryStorage.d.ts +12 -7
  46. package/dist/src/storage/memoryStorage.js +12 -7
  47. package/dist/src/storage/memoryStorage.js.map +1 -1
  48. package/dist/src/storage/storage.d.ts +18 -1
  49. package/dist/src/turnContext.d.ts +31 -20
  50. package/dist/src/turnContext.js +31 -20
  51. package/dist/src/turnContext.js.map +1 -1
  52. package/package.json +2 -2
  53. package/src/activityHandler.ts +0 -1
  54. package/src/agent-client/agentResponseHandler.ts +6 -6
  55. package/src/app/adaptiveCards/adaptiveCardsActions.ts +12 -4
  56. package/src/app/agentApplication.ts +24 -7
  57. package/src/app/appRoute.ts +8 -4
  58. package/src/app/attachmentDownloader.ts +3 -1
  59. package/src/app/authorization.ts +26 -18
  60. package/src/app/routeRank.ts +10 -3
  61. package/src/app/streaming/streamingResponse.ts +23 -2
  62. package/src/app/turnState.ts +69 -19
  63. package/src/auth/authConfiguration.ts +16 -9
  64. package/src/auth/jwt-middleware.ts +24 -17
  65. package/src/cards/adaptiveCard.ts +1 -1
  66. package/src/headerPropagation.ts +18 -6
  67. package/src/state/agentState.ts +23 -7
  68. package/src/state/agentStatePropertyAccesor.ts +63 -41
  69. package/src/storage/fileStorage.ts +8 -6
  70. package/src/storage/memoryStorage.ts +12 -7
  71. package/src/storage/storage.ts +18 -1
  72. package/src/turnContext.ts +31 -20
@@ -72,25 +72,32 @@ export const authorizeJWT = (authConfig: AuthConfiguration) => {
72
72
  return async function (req: Request, res: Response, next: NextFunction) {
73
73
  let failed = false
74
74
  logger.debug('authorizing jwt')
75
- const authHeader = req.headers.authorization as string
76
- if (authHeader) {
77
- const token: string = authHeader.split(' ')[1] // Extract the token from the Bearer string
78
- try {
79
- const user = await verifyToken(token, authConfig)
80
- logger.debug('token verified for ', user)
81
- req.user = user
82
- } catch (err: Error | any) {
83
- failed = true
84
- logger.error(err)
85
- res.status(401).send({ 'jwt-auth-error': err.message })
86
- }
75
+ if (req.method !== 'POST' && req.method !== 'GET') {
76
+ failed = true
77
+ logger.warn('Method not allowed', req.method)
78
+ res.status(405).send({ 'jwt-auth-error': 'Method not allowed' })
87
79
  } else {
88
- if (!authConfig.clientId && process.env.NODE_ENV !== 'production') {
89
- logger.info('using anonymous auth')
90
- req.user = { name: 'anonymous' }
80
+ const authHeader = req.headers.authorization as string
81
+ if (authHeader) {
82
+ const token: string = authHeader.split(' ')[1] // Extract the token from the Bearer string
83
+ try {
84
+ const user = await verifyToken(token, authConfig)
85
+ logger.debug('token verified for ', user)
86
+ req.user = user
87
+ } catch (err: Error | any) {
88
+ failed = true
89
+ logger.error(err)
90
+ res.status(401).send({ 'jwt-auth-error': err.message })
91
+ }
91
92
  } else {
92
- logger.error('authorization header not found')
93
- res.status(401).send({ 'jwt-auth-error': 'authorization header not found' })
93
+ if (!authConfig.clientId && process.env.NODE_ENV !== 'production') {
94
+ logger.info('using anonymous auth')
95
+ req.user = { name: 'anonymous' }
96
+ } else {
97
+ failed = true
98
+ logger.error('authorization header not found')
99
+ res.status(401).send({ 'jwt-auth-error': 'authorization header not found' })
100
+ }
94
101
  }
95
102
  }
96
103
  if (!failed) {
@@ -11,7 +11,7 @@
11
11
  */
12
12
  export interface AdaptiveCard {
13
13
  /**
14
- * The type of the card, which must always be 'AdaptiveCard'.
14
+ * The type of the card, which must always be `AdaptiveCard`.
15
15
  */
16
16
  type: 'AdaptiveCard'
17
17
  [key: string]: any
@@ -94,36 +94,48 @@ export interface HeaderPropagationDefinition {
94
94
  export interface HeaderPropagationCollection {
95
95
  /**
96
96
  * The collection of incoming headers from the incoming request.
97
- * @remarks This collection is built based on the headers received in the request.
97
+ *
98
+ * @remarks
99
+ * This collection is built based on the headers received in the request.
98
100
  */
99
101
  incoming: Record<string, string>
100
102
  /**
101
103
  * The collection of headers that will be propagated to outgoing requests.
102
- * @remarks This collection is built based on the incoming headers and the definition provided.
104
+ *
105
+ * @remarks
106
+ * This collection is built based on the incoming headers and the definition provided.
103
107
  */
104
108
  outgoing: Record<string, string>
105
109
  /**
106
110
  * Propagates the incoming header value to the outgoing collection based on the header definition key.
107
111
  * @param headers List of header keys to propagate.
108
- * @remarks If the header does not exist in the incoming headers, it will be ignored.
112
+ *
113
+ * @remarks
114
+ * If the header does not exist in the incoming headers, it will be ignored.
109
115
  */
110
116
  propagate(headers: string[]): void
111
117
  /**
112
118
  * Adds a header definition to the outgoing collection.
113
119
  * @param headers Headers to add to the outgoing collection.
114
- * @remarks If the header already exists, it will not be added.
120
+ *
121
+ * @remarks
122
+ * If the header already exists, it will not be added.
115
123
  */
116
124
  add(headers: Record<string, string>): void
117
125
  /**
118
126
  * Concatenates a header definition to the outgoing collection.
119
127
  * @param headers Headers to concatenate to the outgoing collection.
120
- * @remarks If the header does not exist in the incoming headers, it will be ignored. Unless the header is already present in the outgoing collection.
128
+ *
129
+ * @remarks
130
+ * If the header does not exist in the incoming headers, it will be ignored. Unless the header is already present in the outgoing collection.
121
131
  */
122
132
  concat(headers: Record<string, string>): void
123
133
  /**
124
134
  * Overrides a header definition in the outgoing collection.
125
135
  * @param headers Headers to override in the outgoing collection.
126
- * @remarks If the header does not exist in the incoming headers, it will be added to the outgoing collection.
136
+ *
137
+ * @remarks
138
+ * If the header does not exist in the incoming headers, it will be added to the outgoing collection.
127
139
  */
128
140
  override(headers: Record<string, string>): void
129
141
  }
@@ -13,6 +13,8 @@ const logger = debug('agents:state')
13
13
 
14
14
  /**
15
15
  * Represents agent state that has been cached in the turn context.
16
+ *
17
+ * @remarks
16
18
  * Used internally to track state changes and avoid unnecessary storage operations.
17
19
  */
18
20
  export interface CachedAgentState {
@@ -28,6 +30,8 @@ export interface CachedAgentState {
28
30
 
29
31
  /**
30
32
  * Represents a custom key for storing state in a specific location.
33
+ *
34
+ * @remarks
31
35
  * Allows state to be persisted with channel and conversation identifiers
32
36
  * independent of the current context.
33
37
  */
@@ -44,7 +48,8 @@ export interface CustomKey {
44
48
  }
45
49
 
46
50
  /**
47
- * @summary Manages the state of an Agent across turns in a conversation.
51
+ * Manages the state of an Agent across turns in a conversation.
52
+ *
48
53
  * @remarks
49
54
  * AgentState provides functionality to persist and retrieve state data using
50
55
  * a storage provider. It handles caching state in the turn context for performance,
@@ -64,10 +69,12 @@ export class AgentState {
64
69
 
65
70
  /**
66
71
  * Creates a property accessor for the specified property.
67
- * Property accessors provide typed access to properties within the state object.
68
72
  *
69
73
  * @param name The name of the property to access
70
74
  * @returns A property accessor for the specified property
75
+ *
76
+ * @remarks
77
+ * Property accessors provide typed access to properties within the state object.
71
78
  */
72
79
  createProperty<T = any>(name: string): AgentStatePropertyAccessor<T> {
73
80
  const prop: AgentStatePropertyAccessor<T> = new AgentStatePropertyAccessor<T>(this, name)
@@ -76,12 +83,14 @@ export class AgentState {
76
83
 
77
84
  /**
78
85
  * 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
86
  *
81
87
  * @param context The turn context to load state into
82
88
  * @param force If true, forces a reload from storage even if state is cached
83
89
  * @param customKey Optional custom storage key to use instead of the default
84
90
  * @returns A promise that resolves to the loaded state object
91
+ *
92
+ * @remarks
93
+ * If state is already cached in the turn context and force is not set, the cached version will be used.
85
94
  */
86
95
  public async load (context: TurnContext, force = false, customKey?: CustomKey): Promise<any> {
87
96
  const cached: CachedAgentState = context.turnState.get(this.stateKey)
@@ -103,12 +112,14 @@ export class AgentState {
103
112
 
104
113
  /**
105
114
  * 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
115
  *
108
116
  * @param context The turn context containing the state to save
109
117
  * @param force If true, forces a save to storage even if no changes are detected
110
118
  * @param customKey Optional custom storage key to use instead of the default
111
119
  * @returns A promise that resolves when the save operation is complete
120
+ *
121
+ * @remarks
122
+ * Change detection uses a hash of the state object to determine if saving is necessary.
112
123
  */
113
124
  public async saveChanges (context: TurnContext, force = false, customKey?: CustomKey): Promise<void> {
114
125
  let cached: CachedAgentState = context.turnState.get(this.stateKey)
@@ -151,11 +162,14 @@ export class AgentState {
151
162
 
152
163
  /**
153
164
  * 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
165
  *
157
166
  * @param context The turn context containing the state to clear
158
167
  * @returns A promise that resolves when the clear operation is complete
168
+ *
169
+ * @remarks
170
+ * This does not remove the state from storage, it only clears the in-memory representation.
171
+ * Call saveChanges() after this to persist the empty state to storage.
172
+ *
159
173
  */
160
174
  public async clear (context: TurnContext): Promise<void> {
161
175
  const emptyObjectToForceSave = { state: {}, hash: '' }
@@ -193,10 +207,12 @@ export class AgentState {
193
207
 
194
208
  /**
195
209
  * Calculates a hash for the specified state object to detect changes.
196
- * The eTag property is excluded from the hash calculation.
197
210
  *
198
211
  * @param item The state object to calculate the hash for
199
212
  * @returns A string hash representing the state
213
+ *
214
+ * @remarks
215
+ * The eTag property is excluded from the hash calculation.
200
216
  * @private
201
217
  */
202
218
  private readonly calculateChangeHash = (item: StoreItem): string => {
@@ -9,29 +9,36 @@ import { AgentState, CustomKey } from './agentState'
9
9
  /**
10
10
  * Interface for accessing a property in state storage with type safety.
11
11
  *
12
- * The interface defines standard methods for working with persisted state properties,
12
+ * @typeParam T The type of the property being accessed
13
+ *
14
+ * @remarks
15
+ * This interface defines standard methods for working with persisted state properties,
13
16
  * allowing property access with strong typing to reduce errors when working with
14
17
  * complex state objects.
15
18
  *
16
- * @typeParam T The type of the property being accessed
17
19
  */
18
20
  export interface StatePropertyAccessor<T = any> {
19
21
  /**
20
22
  * Deletes the persisted property from its backing storage object.
21
23
  *
24
+ * @param context Context for the current turn of conversation with the user.
25
+ *
22
26
  * @remarks
23
27
  * The properties backing storage object SHOULD be loaded into memory on first access.
24
28
  *
25
- * ```JavaScript
29
+ * @example
30
+ * ```javascript
26
31
  * await myProperty.delete(context);
27
32
  * ```
28
- * @param context Context for the current turn of conversation with the user.
33
+ *
29
34
  */
30
35
  delete(context: TurnContext): Promise<void>;
31
36
 
32
37
  /**
33
38
  * Reads a persisted property from its backing storage object.
34
39
  *
40
+ * @param context Context for the current turn of conversation with the user.
41
+ *
35
42
  * @remarks
36
43
  * The properties backing storage object SHOULD be loaded into memory on first access.
37
44
  *
@@ -39,10 +46,11 @@ export interface StatePropertyAccessor<T = any> {
39
46
  * specified, a clone of the `defaultValue` SHOULD be copied to the storage object. If a
40
47
  * `defaultValue` has not been specified then a value of `undefined` SHOULD be returned.
41
48
  *
42
- * ```JavaScript
49
+ * @example
50
+ * ```javascript
43
51
  * const value = await myProperty.get(context, { count: 0 });
44
52
  * ```
45
- * @param context Context for the current turn of conversation with the user.
53
+ *
46
54
  */
47
55
  get(context: TurnContext): Promise<T | undefined>;
48
56
 
@@ -57,26 +65,31 @@ export interface StatePropertyAccessor<T = any> {
57
65
  /**
58
66
  * Assigns a new value to the properties backing storage object.
59
67
  *
68
+ * @param context Context for the current turn of conversation with the user.
69
+ * @param value Value to assign.
70
+ *
60
71
  * @remarks
61
72
  * The properties backing storage object SHOULD be loaded into memory on first access.
62
73
  *
63
74
  * Depending on the state systems implementation, an additional step may be required to
64
75
  * persist the actual changes to disk.
65
76
  *
66
- * ```JavaScript
77
+ * @example
78
+ * ```javascript
67
79
  * await myProperty.set(context, value);
68
80
  * ```
69
- * @param context Context for the current turn of conversation with the user.
70
- * @param value Value to assign.
81
+ *
71
82
  */
72
83
  set(context: TurnContext, value: T): Promise<void>;
73
84
  }
74
85
 
75
86
  /**
76
- * @summary Provides typed access to an Agent state property with automatic state loading and persistence management.
87
+ * Provides typed access to an Agent state property with automatic state loading and persistence management.
88
+ *
89
+ * @typeParam T The type of the property being accessed. Can be any serializable type.
77
90
  *
78
91
  * @remarks
79
- * AgentStatePropertyAccessor simplifies working with persisted state by abstracting
92
+ * `AgentStatePropertyAccessor` simplifies working with persisted state by abstracting
80
93
  * the complexity of loading state from storage and manipulating specific properties.
81
94
  * It provides a type-safe interface for state management with automatic handling of:
82
95
  *
@@ -88,6 +101,11 @@ export interface StatePropertyAccessor<T = any> {
88
101
  *
89
102
  * ### Key Features
90
103
  *
104
+ * Key features of `AgentStatePropertyAccessor` include:
105
+ * - [Type Safety](#type-safety)
106
+ * - [Automatic Default Value Handling](#automatic-default-value-handling)
107
+ * - [Explicit Persistence Control](#explicit-persistence-control)
108
+ *
91
109
  * #### Type Safety
92
110
  * The accessor provides compile-time type checking when using TypeScript:
93
111
  * ```typescript
@@ -178,8 +196,6 @@ export interface StatePropertyAccessor<T = any> {
178
196
  * - **Persistence**: Always call `state.saveChanges(context)` to persist changes to storage.
179
197
  * - **Deep Cloning**: Default values are deep cloned using JSON serialization, which may not work with complex objects containing functions or circular references.
180
198
  *
181
- * @typeParam T The type of the property being accessed. Can be any serializable type.
182
- *
183
199
  * @see {@link AgentState.createProperty} for creating property accessors
184
200
  * @see {@link StatePropertyAccessor} for the interface definition
185
201
  */
@@ -187,13 +203,13 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
187
203
  /**
188
204
  * Creates a new instance of AgentStatePropertyAccessor.
189
205
  *
206
+ * @param state The agent state object that manages the backing storage for this property
207
+ * @param name The unique name of the property within the state object. This name is used as the key in the state storage.
208
+ *
190
209
  * @remarks
191
210
  * This constructor is typically not called directly. Instead, use {@link AgentState.createProperty}
192
211
  * to create property accessors, which ensures proper integration with the state management system.
193
212
  *
194
- * @param state The agent state object that manages the backing storage for this property
195
- * @param name The unique name of the property within the state object. This name is used as the key in the state storage.
196
- *
197
213
  * @example
198
214
  * ```typescript
199
215
  * // Recommended way - use AgentState.createProperty
@@ -202,11 +218,18 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
202
218
  * // Direct construction (not recommended)
203
219
  * const accessor = new AgentStatePropertyAccessor<UserProfile>(userState, "userProfile");
204
220
  * ```
221
+ *
205
222
  */
206
223
  constructor (protected readonly state: AgentState, public readonly name: string) { }
207
224
 
208
225
  /**
209
- * @summary Deletes the property from the state storage.
226
+ * Deletes the property from the state storage.
227
+ *
228
+ * @param context The turn context for the current conversation turn
229
+ * @param customKey Optional custom key for accessing state in a specific storage location.
230
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
231
+ * @returns A promise that resolves when the delete operation is complete
232
+ *
210
233
  * @remarks
211
234
  * This operation removes the property from the in-memory state object but does not
212
235
  * automatically persist the change to the underlying storage. You must call
@@ -216,13 +239,7 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
216
239
  * - The deletion only affects the in-memory state until `saveChanges()` is called
217
240
  * - After deletion, subsequent `get()` calls will return `undefined` (or the default value if provided)
218
241
  *
219
- * @param context The turn context for the current conversation turn
220
- * @param customKey Optional custom key for accessing state in a specific storage location.
221
- * Useful for multi-tenant scenarios or when state needs to be partitioned.
222
- *
223
- * @returns A promise that resolves when the delete operation is complete
224
- *
225
- * @example
242
+ * @example Basic usage
226
243
  * ```typescript
227
244
  * const userSettings = userState.createProperty<UserSettings>("settings");
228
245
  *
@@ -242,6 +259,7 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
242
259
  * await userSettings.delete(context, tenantKey);
243
260
  * await userState.saveChanges(context);
244
261
  * ```
262
+ *
245
263
  */
246
264
  async delete (context: TurnContext, customKey?: CustomKey): Promise<void> {
247
265
  const obj: any = await this.state.load(context, false, customKey)
@@ -251,7 +269,16 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
251
269
  }
252
270
 
253
271
  /**
254
- * @summary Retrieves the value of the property from state storage.
272
+ * Retrieves the value of the property from state storage.
273
+ *
274
+ * @param context The turn context for the current conversation turn
275
+ * @param defaultValue Optional default value to use if the property doesn't exist.
276
+ * When provided, this value is deep cloned and stored in state.
277
+ * @param customKey Optional custom key for accessing state in a specific storage location.
278
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
279
+ *
280
+ * @returns A promise that resolves to the property value, the cloned default value, or `undefined`
281
+ *
255
282
  * @remarks
256
283
  * This method provides intelligent default value handling:
257
284
  * - If the property exists, its value is returned
@@ -268,14 +295,6 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
268
295
  * **Performance**: The first access loads state from storage; subsequent accesses use
269
296
  * the in-memory cached version until the context is disposed.
270
297
  *
271
- * @param context The turn context for the current conversation turn
272
- * @param defaultValue Optional default value to use if the property doesn't exist.
273
- * When provided, this value is deep cloned and stored in state.
274
- * @param customKey Optional custom key for accessing state in a specific storage location.
275
- * Useful for multi-tenant scenarios or when state needs to be partitioned.
276
- *
277
- * @returns A promise that resolves to the property value, the cloned default value, or `undefined`
278
- *
279
298
  * @example Basic usage
280
299
  * ```typescript
281
300
  * const counterProperty = userState.createProperty<number>("counter");
@@ -314,6 +333,7 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
314
333
  * const tenantKey = { key: `tenant_${tenantId}` };
315
334
  * const tenantData = await dataProperty.get(context, defaultData, tenantKey);
316
335
  * ```
336
+ *
317
337
  */
318
338
  async get (context: TurnContext, defaultValue?: T, customKey?: CustomKey): Promise<T> {
319
339
  const obj: any = await this.state.load(context, false, customKey)
@@ -329,7 +349,15 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
329
349
  }
330
350
 
331
351
  /**
332
- * @summary Sets the value of the property in state storage.
352
+ * Sets the value of the property in state storage.
353
+ *
354
+ * @param context The turn context for the current conversation turn
355
+ * @param value The value to assign to the property. Can be any serializable value.
356
+ * @param customKey Optional custom key for accessing state in a specific storage location.
357
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
358
+ *
359
+ * @returns A promise that resolves when the set operation is complete
360
+ *
333
361
  * @remarks
334
362
  * This operation updates the property in the in-memory state object but does not
335
363
  * automatically persist the change to the underlying storage. You must call
@@ -346,13 +374,6 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
346
374
  * **Type Safety**: When using TypeScript, the value must match the property's
347
375
  * declared type parameter.
348
376
  *
349
- * @param context The turn context for the current conversation turn
350
- * @param value The value to assign to the property. Can be any serializable value.
351
- * @param customKey Optional custom key for accessing state in a specific storage location.
352
- * Useful for multi-tenant scenarios or when state needs to be partitioned.
353
- *
354
- * @returns A promise that resolves when the set operation is complete
355
- *
356
377
  * @example Basic usage
357
378
  * ```typescript
358
379
  * const counterProperty = userState.createProperty<number>("counter");
@@ -394,6 +415,7 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
394
415
  * await dataProperty.set(context, updatedData, tenantKey);
395
416
  * await userState.saveChanges(context);
396
417
  * ```
418
+ *
397
419
  */
398
420
  async set (context: TurnContext, value: T, customKey?: CustomKey): Promise<void> {
399
421
  const obj: any = await this.state.load(context, false, customKey)
@@ -8,7 +8,7 @@ import fs from 'fs'
8
8
  import { Storage, StoreItem } from './storage'
9
9
 
10
10
  /**
11
- * @summary A file-based storage implementation that persists data to the local filesystem.
11
+ * A file-based storage implementation that persists data to the local filesystem.
12
12
  *
13
13
  * @remarks
14
14
  * FileStorage stores all data in a single JSON file named 'state.json' within a specified folder.
@@ -47,7 +47,6 @@ import { Storage, StoreItem } from './storage'
47
47
  * await storage.delete(['conversation456']);
48
48
  * ```
49
49
  *
50
-
51
50
  */
52
51
  export class FileStorage implements Storage {
53
52
  private _folder: string
@@ -57,6 +56,7 @@ export class FileStorage implements Storage {
57
56
  * Creates a new FileStorage instance that stores data in the specified folder.
58
57
  *
59
58
  * @param folder The absolute or relative path to the folder where the state.json file will be stored
59
+ * @throws May throw filesystem errors if the folder cannot be created or accessed
60
60
  *
61
61
  * @remarks
62
62
  * The constructor performs the following initialization steps:
@@ -64,7 +64,6 @@ export class FileStorage implements Storage {
64
64
  * 2. Creates an empty state.json file if it doesn't exist
65
65
  * 3. Loads existing data from state.json into memory for fast access
66
66
  *
67
- * @throws May throw filesystem errors if the folder cannot be created or accessed
68
67
  */
69
68
  constructor (folder: string) {
70
69
  this._folder = folder
@@ -83,13 +82,13 @@ export class FileStorage implements Storage {
83
82
  *
84
83
  * @param keys Array of keys to read from storage
85
84
  * @returns Promise resolving to an object containing the requested items (keys that don't exist are omitted)
86
- *
87
85
  * @throws ReferenceError if keys array is empty or undefined
88
86
  *
89
87
  * @remarks
90
88
  * This method reads from the in-memory cache that was loaded during construction,
91
89
  * making it very fast but potentially returning stale data if the file was
92
90
  * modified by external processes.
91
+ *
93
92
  */
94
93
  read (keys: string[]) : Promise<StoreItem> {
95
94
  return new Promise((resolve, reject) => {
@@ -119,8 +118,10 @@ export class FileStorage implements Storage {
119
118
  * to the state.json file. The file is written with pretty-printing (2-space indentation)
120
119
  * for better readability during development and debugging.
121
120
  *
122
- * Note: This implementation does not support eTag-based optimistic concurrency control.
123
- * Any eTag values in the changes object are ignored.
121
+ * > [!NOTE]
122
+ * > This implementation does not support eTag-based optimistic concurrency control.
123
+ * > Any eTag values in the changes object are ignored.
124
+ *
124
125
  */
125
126
  write (changes: StoreItem) : Promise<void> {
126
127
  const keys = Object.keys(changes)
@@ -143,6 +144,7 @@ export class FileStorage implements Storage {
143
144
  * This method removes the specified keys from both the in-memory cache
144
145
  * and writes the updated state to the state.json file. Keys that don't
145
146
  * exist in storage are silently ignored.
147
+ *
146
148
  */
147
149
  delete (keys: string[]) : Promise<void> {
148
150
  return new Promise((resolve, reject) => {
@@ -39,10 +39,12 @@ export class MemoryStorage implements Storage {
39
39
  /**
40
40
  * Gets a single shared instance of the MemoryStorage class.
41
41
  *
42
+ * @returns The singleton instance of MemoryStorage
43
+ *
44
+ * @remarks
42
45
  * Using this method ensures that the same storage instance is used across
43
46
  * the application, allowing for shared state without passing references.
44
47
  *
45
- * @returns The singleton instance of MemoryStorage
46
48
  */
47
49
  static getSingleInstance (): MemoryStorage {
48
50
  if (!MemoryStorage.instance) {
@@ -78,14 +80,15 @@ export class MemoryStorage implements Storage {
78
80
  /**
79
81
  * Writes storage items to memory.
80
82
  *
83
+ * @param changes The items to write, indexed by key
84
+ * @returns A promise that resolves when the write operation is complete
85
+ * @throws Will throw an error if changes are not provided or if there's an eTag conflict
86
+ *
87
+ * @remarks
81
88
  * This method supports optimistic concurrency control through eTags.
82
89
  * If an item has an eTag, it will only be updated if the existing item
83
90
  * has the same eTag. If an item has an eTag of '*' or no eTag, it will
84
91
  * always be written regardless of the current state.
85
- *
86
- * @param changes The items to write, indexed by key
87
- * @returns A promise that resolves when the write operation is complete
88
- * @throws Will throw an error if changes are not provided or if there's an eTag conflict
89
92
  */
90
93
  async write (changes: StoreItem): Promise<void> {
91
94
  if (!changes || changes.length === 0) {
@@ -124,13 +127,15 @@ export class MemoryStorage implements Storage {
124
127
  /**
125
128
  * Saves an item to memory with a new eTag.
126
129
  *
130
+ * @param key The key of the item to save
131
+ * @param item The item to save
132
+ *
133
+ * @remarks
127
134
  * This private method handles the details of:
128
135
  * - Creating a clone of the item to prevent modification of the original
129
136
  * - Generating a new eTag for optimistic concurrency control
130
137
  * - Converting the item to a JSON string for storage
131
138
  *
132
- * @param key The key of the item to save
133
- * @param item The item to save
134
139
  * @private
135
140
  */
136
141
  private saveItem (key: string, item: unknown): void {
@@ -7,41 +7,58 @@ import { TurnContext } from '../turnContext'
7
7
 
8
8
  /**
9
9
  * Represents an item to be stored in a storage provider.
10
+ *
11
+ * @remarks
10
12
  * Each item can contain arbitrary data along with an optional eTag for optimistic concurrency control.
11
13
  */
12
14
  export interface StoreItem {
13
15
  /**
14
16
  * Optional eTag used for optimistic concurrency control.
17
+ *
18
+ * @remarks
15
19
  * When set to '*', it indicates that the write should proceed regardless of existing data.
16
20
  * When comparing eTags, exact string matching is used to determine if data has changed.
21
+ *
17
22
  */
18
23
  eTag?: string;
19
24
 
20
25
  /**
21
26
  * Additional properties can be stored in the item.
27
+ *
28
+ * @remarks
22
29
  * Each storage provider may have specific requirements or limitations on property names and values.
30
+ *
23
31
  */
24
32
  [key: string]: any;
25
33
  }
26
34
 
27
35
  /**
28
36
  * Represents a collection of store items indexed by key.
37
+ *
38
+ * @remarks
29
39
  * Used as the return type for storage read operations.
40
+ *
30
41
  */
31
42
  export interface StoreItems {
32
43
  /**
33
44
  * Keys are the storage item identifiers, and values are the stored items.
45
+ *
46
+ * @remarks
34
47
  * If a requested key is not found during a read operation, it will not appear in this collection.
48
+ *
35
49
  */
36
50
  [key: string]: any;
37
51
  }
38
52
 
39
53
  /**
40
54
  * A factory function to generate storage keys based on the conversation context.
41
- * Allows different storage strategies based on the conversation state.
42
55
  *
43
56
  * @param context The TurnContext for the current turn of conversation
44
57
  * @returns A string key for storage that uniquely identifies where to store the data
58
+ *
59
+ * @remarks
60
+ * Allows different storage strategies based on the conversation state.
61
+ *
45
62
  */
46
63
  export type StorageKeyFactory = (context: TurnContext) => string | Promise<string>
47
64