@microsoft/agents-hosting 0.6.1 → 0.6.11

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 (142) hide show
  1. package/dist/src/activityHandler.d.ts +29 -5
  2. package/dist/src/activityHandler.js +30 -6
  3. package/dist/src/activityHandler.js.map +1 -1
  4. package/dist/src/agent-client/agentClient.js +1 -1
  5. package/dist/src/agent-client/agentClient.js.map +1 -1
  6. package/dist/src/agent-client/agentResponseHandler.d.ts +34 -0
  7. package/dist/src/agent-client/agentResponseHandler.js +35 -1
  8. package/dist/src/agent-client/agentResponseHandler.js.map +1 -1
  9. package/dist/src/app/adaptiveCards/adaptiveCardsActions.d.ts +23 -2
  10. package/dist/src/app/adaptiveCards/adaptiveCardsActions.js.map +1 -1
  11. package/dist/src/app/adaptiveCards/adaptiveCardsSearchParams.d.ts +1 -1
  12. package/dist/src/app/agentApplication.d.ts +46 -34
  13. package/dist/src/app/agentApplication.js +64 -40
  14. package/dist/src/app/agentApplication.js.map +1 -1
  15. package/dist/src/app/agentApplicationOptions.d.ts +74 -13
  16. package/dist/src/app/appRoute.d.ts +56 -2
  17. package/dist/src/app/attachmentDownloader.d.ts +1 -0
  18. package/dist/src/app/attachmentDownloader.js +2 -1
  19. package/dist/src/app/attachmentDownloader.js.map +1 -1
  20. package/dist/src/app/authorization.d.ts +1 -1
  21. package/dist/src/app/authorization.js +1 -1
  22. package/dist/src/app/authorization.js.map +1 -1
  23. package/dist/src/app/extensions.d.ts +37 -1
  24. package/dist/src/app/extensions.js +38 -2
  25. package/dist/src/app/extensions.js.map +1 -1
  26. package/dist/src/app/index.d.ts +2 -0
  27. package/dist/src/app/index.js +2 -0
  28. package/dist/src/app/index.js.map +1 -1
  29. package/dist/src/app/routeList.d.ts +13 -0
  30. package/dist/src/app/routeList.js +30 -0
  31. package/dist/src/app/routeList.js.map +1 -0
  32. package/dist/src/app/routeRank.d.ts +51 -0
  33. package/dist/src/app/routeRank.js +56 -0
  34. package/dist/src/app/routeRank.js.map +1 -0
  35. package/dist/src/app/streaming/streamingResponse.js +29 -41
  36. package/dist/src/app/streaming/streamingResponse.js.map +1 -1
  37. package/dist/src/app/turnState.d.ts +2 -0
  38. package/dist/src/app/turnState.js +3 -1
  39. package/dist/src/app/turnState.js.map +1 -1
  40. package/dist/src/auth/authConfiguration.d.ts +4 -0
  41. package/dist/src/auth/authConfiguration.js +4 -0
  42. package/dist/src/auth/authConfiguration.js.map +1 -1
  43. package/dist/src/auth/authProvider.d.ts +1 -1
  44. package/dist/src/auth/jwt-middleware.js +1 -1
  45. package/dist/src/auth/jwt-middleware.js.map +1 -1
  46. package/dist/src/auth/msalTokenCredential.d.ts +14 -0
  47. package/dist/src/auth/msalTokenCredential.js +14 -0
  48. package/dist/src/auth/msalTokenCredential.js.map +1 -1
  49. package/dist/src/auth/msalTokenProvider.js +4 -2
  50. package/dist/src/auth/msalTokenProvider.js.map +1 -1
  51. package/dist/src/baseAdapter.d.ts +22 -1
  52. package/dist/src/baseAdapter.js +23 -2
  53. package/dist/src/baseAdapter.js.map +1 -1
  54. package/dist/src/cards/adaptiveCard.d.ts +2 -0
  55. package/dist/src/cards/animationCard.d.ts +1 -1
  56. package/dist/src/cards/audioCard.d.ts +1 -1
  57. package/dist/src/cards/cardImage.d.ts +1 -1
  58. package/dist/src/cards/fact.d.ts +1 -1
  59. package/dist/src/cards/heroCard.d.ts +1 -1
  60. package/dist/src/cards/o365ConnectorCardSection.d.ts +5 -0
  61. package/dist/src/cloudAdapter.d.ts +11 -0
  62. package/dist/src/cloudAdapter.js +33 -4
  63. package/dist/src/cloudAdapter.js.map +1 -1
  64. package/dist/src/connector-client/connectorClient.js +1 -1
  65. package/dist/src/connector-client/connectorClient.js.map +1 -1
  66. package/dist/src/index.d.ts +0 -2
  67. package/dist/src/index.js +0 -2
  68. package/dist/src/index.js.map +1 -1
  69. package/dist/src/middlewareSet.js +1 -1
  70. package/dist/src/middlewareSet.js.map +1 -1
  71. package/dist/src/oauth/oAuthFlow.js +1 -1
  72. package/dist/src/oauth/oAuthFlow.js.map +1 -1
  73. package/dist/src/oauth/userTokenClient.js +1 -1
  74. package/dist/src/oauth/userTokenClient.js.map +1 -1
  75. package/dist/src/state/agentState.js +1 -1
  76. package/dist/src/state/agentState.js.map +1 -1
  77. package/dist/src/state/agentStatePropertyAccesor.d.ts +269 -38
  78. package/dist/src/state/agentStatePropertyAccesor.js +269 -38
  79. package/dist/src/state/agentStatePropertyAccesor.js.map +1 -1
  80. package/dist/src/statusCodes.d.ts +30 -0
  81. package/dist/src/statusCodes.js +30 -0
  82. package/dist/src/statusCodes.js.map +1 -1
  83. package/dist/src/storage/fileStorage.d.ts +97 -0
  84. package/dist/src/storage/fileStorage.js +97 -0
  85. package/dist/src/storage/fileStorage.js.map +1 -1
  86. package/dist/src/storage/memoryStorage.d.ts +2 -1
  87. package/dist/src/storage/memoryStorage.js +3 -2
  88. package/dist/src/storage/memoryStorage.js.map +1 -1
  89. package/dist/src/storage/storage.d.ts +1 -0
  90. package/dist/src/transcript/transcriptLoggerMiddleware.js +1 -1
  91. package/dist/src/transcript/transcriptLoggerMiddleware.js.map +1 -1
  92. package/dist/src/turnContext.d.ts +1 -0
  93. package/dist/src/turnContext.js +1 -0
  94. package/dist/src/turnContext.js.map +1 -1
  95. package/package.json +4 -5
  96. package/src/activityHandler.ts +30 -6
  97. package/src/agent-client/agentClient.ts +1 -1
  98. package/src/agent-client/agentResponseHandler.ts +35 -1
  99. package/src/app/adaptiveCards/adaptiveCardsActions.ts +23 -2
  100. package/src/app/adaptiveCards/adaptiveCardsSearchParams.ts +1 -1
  101. package/src/app/agentApplication.ts +70 -41
  102. package/src/app/agentApplicationOptions.ts +75 -13
  103. package/src/app/appRoute.ts +57 -2
  104. package/src/app/attachmentDownloader.ts +2 -1
  105. package/src/app/authorization.ts +2 -2
  106. package/src/app/extensions.ts +45 -2
  107. package/src/app/index.ts +2 -0
  108. package/src/app/routeList.ts +37 -0
  109. package/src/app/routeRank.ts +54 -0
  110. package/src/app/streaming/streamingResponse.ts +22 -69
  111. package/src/app/turnState.ts +3 -1
  112. package/src/auth/authConfiguration.ts +4 -0
  113. package/src/auth/authProvider.ts +1 -1
  114. package/src/auth/jwt-middleware.ts +1 -1
  115. package/src/auth/msalTokenCredential.ts +15 -0
  116. package/src/auth/msalTokenProvider.ts +4 -2
  117. package/src/baseAdapter.ts +25 -2
  118. package/src/cards/adaptiveCard.ts +2 -0
  119. package/src/cards/animationCard.ts +1 -1
  120. package/src/cards/audioCard.ts +1 -1
  121. package/src/cards/cardImage.ts +1 -1
  122. package/src/cards/fact.ts +1 -1
  123. package/src/cards/heroCard.ts +1 -1
  124. package/src/cards/o365ConnectorCardSection.ts +5 -0
  125. package/src/cloudAdapter.ts +36 -4
  126. package/src/connector-client/connectorClient.ts +1 -1
  127. package/src/index.ts +0 -2
  128. package/src/middlewareSet.ts +1 -1
  129. package/src/oauth/oAuthFlow.ts +1 -1
  130. package/src/oauth/userTokenClient.ts +1 -1
  131. package/src/state/agentState.ts +1 -1
  132. package/src/state/agentStatePropertyAccesor.ts +269 -38
  133. package/src/statusCodes.ts +30 -0
  134. package/src/storage/fileStorage.ts +99 -0
  135. package/src/storage/memoryStorage.ts +3 -2
  136. package/src/storage/storage.ts +1 -0
  137. package/src/transcript/transcriptLoggerMiddleware.ts +1 -1
  138. package/src/turnContext.ts +1 -0
  139. package/dist/src/logger.d.ts +0 -44
  140. package/dist/src/logger.js +0 -77
  141. package/dist/src/logger.js.map +0 -1
  142. package/src/logger.ts +0 -76
@@ -3,7 +3,7 @@
3
3
 
4
4
  import axios, { AxiosInstance } from 'axios'
5
5
  import { ConversationReference } from '@microsoft/agents-activity'
6
- import { debug } from '../logger'
6
+ import { debug } from '@microsoft/agents-activity/src/logger'
7
7
  import { normalizeTokenExchangeState } from '../activityWireCompat'
8
8
  import { AadResourceUrls, SignInResource, TokenExchangeRequest, TokenOrSinginResourceResponse, TokenResponse, TokenStatus } from './userTokenClient.types'
9
9
  import { getProductInfo } from '../getProductInfo'
@@ -7,7 +7,7 @@ import { Storage, StorageKeyFactory, StoreItem } from '../storage/storage'
7
7
  import { TurnContext } from '../turnContext'
8
8
  import { createHash } from 'node:crypto'
9
9
  import { AgentStatePropertyAccessor } from './agentStatePropertyAccesor'
10
- import { debug } from '../logger'
10
+ import { debug } from '@microsoft/agents-activity/src/logger'
11
11
 
12
12
  const logger = debug('agents:state')
13
13
 
@@ -73,56 +73,176 @@ export interface StatePropertyAccessor<T = any> {
73
73
  }
74
74
 
75
75
  /**
76
- * Provides typed access to an Agent state property with automatic state loading.
76
+ * Provides typed access to an Agent state property with automatic state loading and persistence management.
77
77
  *
78
- * The AgentStatePropertyAccessor simplifies working with state by abstracting
79
- * the details of loading state from storage and manipulating specific properties.
80
- * It automatically handles:
78
+ * @remarks
79
+ * AgentStatePropertyAccessor simplifies working with persisted state by abstracting
80
+ * the complexity of loading state from storage and manipulating specific properties.
81
+ * It provides a type-safe interface for state management with automatic handling of:
81
82
  *
82
- * - Loading state when needed
83
- * - Deep cloning of default values to prevent reference issues
84
- * - Type checking for properties (when using TypeScript)
85
- * - Ensuring properties exist before access
83
+ * - **Lazy Loading**: State is loaded from storage only when first accessed
84
+ * - **Type Safety**: Full TypeScript support with generic type parameters
85
+ * - **Default Values**: Automatic deep cloning of default values to prevent reference issues
86
+ * - **Memory Management**: Efficient in-memory caching with explicit persistence control
87
+ * - **Custom Keys**: Support for custom storage keys for advanced scenarios
86
88
  *
87
- * Property accessors are created through the {@link AgentState.createProperty} method:
89
+ * ## Key Features
88
90
  *
91
+ * ### Type Safety
92
+ * The accessor provides compile-time type checking when using TypeScript:
89
93
  * ```typescript
90
- * // Create a property accessor for a user profile
94
+ * interface UserProfile {
95
+ * name: string;
96
+ * preferences: { theme: string; language: string };
97
+ * }
91
98
  * const userProfile = userState.createProperty<UserProfile>("userProfile");
99
+ * ```
100
+ *
101
+ * ### Automatic Default Value Handling
102
+ * When a property doesn't exist, default values are automatically cloned and stored:
103
+ * ```typescript
104
+ * // If userProfile doesn't exist, the default will be cloned and saved
105
+ * const profile = await userProfile.get(context, {
106
+ * name: "Anonymous",
107
+ * preferences: { theme: "light", language: "en" }
108
+ * });
109
+ * ```
110
+ *
111
+ * ### Explicit Persistence Control
112
+ * Changes are kept in memory until explicitly persisted:
113
+ * ```typescript
114
+ * // Modify the state
115
+ * const counter = await counterProperty.get(context, 0);
116
+ * await counterProperty.set(context, counter + 1);
117
+ *
118
+ * // Changes are only in memory at this point
119
+ * // Persist to storage
120
+ * await userState.saveChanges(context);
121
+ * ```
92
122
  *
93
- * // Get the profile with a default if not exists
94
- * const profile = await userProfile.get(context, { name: "", preferences: {} });
123
+ * ## Usage Examples
95
124
  *
96
- * // Update a value
125
+ * ### Basic Usage
126
+ * ```typescript
127
+ * // Create a property accessor
128
+ * const userProfile = userState.createProperty<UserProfile>("userProfile");
129
+ *
130
+ * // Get with default value
131
+ * const profile = await userProfile.get(context, {
132
+ * name: "",
133
+ * preferences: { theme: "light", language: "en" }
134
+ * });
135
+ *
136
+ * // Modify the profile
97
137
  * profile.preferences.theme = "dark";
98
138
  *
99
- * // Save the change
139
+ * // Save the changes
100
140
  * await userProfile.set(context, profile);
141
+ * await userState.saveChanges(context); // Persist to storage
142
+ * ```
143
+ *
144
+ * ### Working with Primitive Types
145
+ * ```typescript
146
+ * const counterProperty = userState.createProperty<number>("counter");
101
147
  *
102
- * // Later, call userState.saveChanges(context) to persist to storage
148
+ * // Increment counter
149
+ * const currentCount = await counterProperty.get(context, 0);
150
+ * await counterProperty.set(context, currentCount + 1);
151
+ * await userState.saveChanges(context);
103
152
  * ```
104
153
  *
105
- * @typeParam T The type of the property being accessed
154
+ * ### Conditional Logic
155
+ * ```typescript
156
+ * const settingsProperty = userState.createProperty<Settings>("settings");
157
+ *
158
+ * // Check if property exists
159
+ * const settings = await settingsProperty.get(context);
160
+ * if (settings === undefined) {
161
+ * // Property doesn't exist, initialize with defaults
162
+ * await settingsProperty.set(context, getDefaultSettings());
163
+ * }
164
+ * ```
165
+ *
166
+ * ### Custom Storage Keys
167
+ * ```typescript
168
+ * // Store state with a custom key for multi-tenant scenarios
169
+ * const customKey = { key: `tenant_${tenantId}` };
170
+ * const tenantData = await dataProperty.get(context, defaultData, customKey);
171
+ * await dataProperty.set(context, updatedData, customKey);
172
+ * ```
173
+ *
174
+ * ## Important Notes
175
+ *
176
+ * - **Thread Safety**: This class is not thread-safe. Ensure proper synchronization in concurrent scenarios.
177
+ * - **Memory Usage**: State objects are kept in memory until the context is disposed.
178
+ * - **Persistence**: Always call `state.saveChanges(context)` to persist changes to storage.
179
+ * - **Deep Cloning**: Default values are deep cloned using JSON serialization, which may not work with complex objects containing functions or circular references.
180
+ *
181
+ * @typeParam T The type of the property being accessed. Can be any serializable type.
182
+ *
183
+ * @see {@link AgentState.createProperty} for creating property accessors
184
+ * @see {@link StatePropertyAccessor} for the interface definition
106
185
  */
107
186
  export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccessor<T> {
108
187
  /**
109
188
  * Creates a new instance of AgentStatePropertyAccessor.
110
189
  *
111
- * @param state The agent state object that will contain this property
112
- * @param name The name of the property in the state object
190
+ * @remarks
191
+ * This constructor is typically not called directly. Instead, use {@link AgentState.createProperty}
192
+ * to create property accessors, which ensures proper integration with the state management system.
193
+ *
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
+ * @example
198
+ * ```typescript
199
+ * // Recommended way - use AgentState.createProperty
200
+ * const userProfile = userState.createProperty<UserProfile>("userProfile");
201
+ *
202
+ * // Direct construction (not recommended)
203
+ * const accessor = new AgentStatePropertyAccessor<UserProfile>(userState, "userProfile");
204
+ * ```
113
205
  */
114
206
  constructor (protected readonly state: AgentState, public readonly name: string) { }
115
207
 
116
208
  /**
117
- * Deletes the property from the state.
209
+ * Deletes the property from the state storage.
118
210
  *
119
- * This removes the property from the state object but does not automatically
120
- * persist the change to storage. Call state.saveChanges() afterwards to
121
- * persist changes.
211
+ * This operation removes the property from the in-memory state object but does not
212
+ * automatically persist the change to the underlying storage. You must call
213
+ * `state.saveChanges(context)` afterwards to persist the deletion.
214
+ *
215
+ * @remarks
216
+ * - If the property doesn't exist, this operation is a no-op
217
+ * - The deletion only affects the in-memory state until `saveChanges()` is called
218
+ * - After deletion, subsequent `get()` calls will return `undefined` (or the default value if provided)
219
+ *
220
+ * @param context The turn context for the current conversation turn
221
+ * @param customKey Optional custom key for accessing state in a specific storage location.
222
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
122
223
  *
123
- * @param context The turn context
124
- * @param customKey Optional custom key for storing the state in a specific location
125
224
  * @returns A promise that resolves when the delete operation is complete
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const userSettings = userState.createProperty<UserSettings>("settings");
229
+ *
230
+ * // Delete the user settings
231
+ * await userSettings.delete(context);
232
+ *
233
+ * // Persist the deletion to storage
234
+ * await userState.saveChanges(context);
235
+ *
236
+ * // Verify deletion
237
+ * const settings = await userSettings.get(context); // Returns undefined
238
+ * ```
239
+ *
240
+ * @example Custom key usage
241
+ * ```typescript
242
+ * const tenantKey = { key: `tenant_${tenantId}` };
243
+ * await userSettings.delete(context, tenantKey);
244
+ * await userState.saveChanges(context);
245
+ * ```
126
246
  */
127
247
  async delete (context: TurnContext, customKey?: CustomKey): Promise<void> {
128
248
  const obj: any = await this.state.load(context, false, customKey)
@@ -132,16 +252,70 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
132
252
  }
133
253
 
134
254
  /**
135
- * Gets the value of the property from the state.
255
+ * Retrieves the value of the property from state storage.
256
+ *
257
+ * This method provides intelligent default value handling:
258
+ * - If the property exists, its value is returned
259
+ * - If the property doesn't exist and a default value is provided, the default is deep cloned,
260
+ * stored in state, and returned
261
+ * - If the property doesn't exist and no default is provided, `undefined` is returned
262
+ *
263
+ * @remarks
264
+ * **Deep Cloning**: Default values are deep cloned using JSON serialization to prevent
265
+ * reference sharing issues. This means:
266
+ * - Functions, symbols, and circular references will be lost
267
+ * - Dates become strings (use Date constructor to restore)
268
+ * - Complex objects with prototypes lose their prototype chain
269
+ *
270
+ * **Performance**: The first access loads state from storage; subsequent accesses use
271
+ * the in-memory cached version until the context is disposed.
272
+ *
273
+ * @param context The turn context for the current conversation turn
274
+ * @param defaultValue Optional default value to use if the property doesn't exist.
275
+ * When provided, this value is deep cloned and stored in state.
276
+ * @param customKey Optional custom key for accessing state in a specific storage location.
277
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
136
278
  *
137
- * If the property doesn't exist and a default value is provided, a deep clone
138
- * of the default value will be stored in state and returned. This ensures that
139
- * modifications to the returned object will be properly tracked.
279
+ * @returns A promise that resolves to the property value, the cloned default value, or `undefined`
140
280
  *
141
- * @param context The turn context
142
- * @param defaultValue Optional default value to use if the property doesn't exist
143
- * @param customKey Optional custom key for storing the state in a specific location
144
- * @returns A promise that resolves to the value of the property or undefined
281
+ * @example Basic usage
282
+ * ```typescript
283
+ * const counterProperty = userState.createProperty<number>("counter");
284
+ *
285
+ * // Get with default value
286
+ * const count = await counterProperty.get(context, 0);
287
+ * console.log(count); // 0 if property doesn't exist, otherwise the stored value
288
+ * ```
289
+ *
290
+ * @example Complex object with default
291
+ * ```typescript
292
+ * interface UserProfile {
293
+ * name: string;
294
+ * preferences: { theme: string; notifications: boolean };
295
+ * }
296
+ *
297
+ * const userProfile = userState.createProperty<UserProfile>("profile");
298
+ * const profile = await userProfile.get(context, {
299
+ * name: "Anonymous",
300
+ * preferences: { theme: "light", notifications: true }
301
+ * });
302
+ * ```
303
+ *
304
+ * @example Checking for existence
305
+ * ```typescript
306
+ * const profile = await userProfile.get(context);
307
+ * if (profile === undefined) {
308
+ * console.log("Profile has not been set yet");
309
+ * } else {
310
+ * console.log(`Welcome back, ${profile.name}!`);
311
+ * }
312
+ * ```
313
+ *
314
+ * @example Custom key usage
315
+ * ```typescript
316
+ * const tenantKey = { key: `tenant_${tenantId}` };
317
+ * const tenantData = await dataProperty.get(context, defaultData, tenantKey);
318
+ * ```
145
319
  */
146
320
  async get (context: TurnContext, defaultValue?: T, customKey?: CustomKey): Promise<T> {
147
321
  const obj: any = await this.state.load(context, false, customKey)
@@ -157,15 +331,72 @@ export class AgentStatePropertyAccessor<T = any> implements StatePropertyAccesso
157
331
  }
158
332
 
159
333
  /**
160
- * Sets the value of the property in the state.
334
+ * Sets the value of the property in state storage.
161
335
  *
162
- * This updates the property in the in-memory state object but does not automatically
163
- * persist the change to storage. Call state.saveChanges() afterwards to persist changes.
336
+ * This operation updates the property in the in-memory state object but does not
337
+ * automatically persist the change to the underlying storage. You must call
338
+ * `state.saveChanges(context)` afterwards to persist the changes.
339
+ *
340
+ * @remarks
341
+ * **Memory vs Storage**: Changes are immediately reflected in memory and will be
342
+ * available to subsequent `get()` calls within the same context, but are not
343
+ * persisted to storage until `saveChanges()` is called.
344
+ *
345
+ * **Value References**: The exact value reference is stored (no cloning occurs).
346
+ * Ensure you don't modify objects after setting them unless you intend for those
347
+ * changes to be reflected in state.
348
+ *
349
+ * **Type Safety**: When using TypeScript, the value must match the property's
350
+ * declared type parameter.
351
+ *
352
+ * @param context The turn context for the current conversation turn
353
+ * @param value The value to assign to the property. Can be any serializable value.
354
+ * @param customKey Optional custom key for accessing state in a specific storage location.
355
+ * Useful for multi-tenant scenarios or when state needs to be partitioned.
164
356
  *
165
- * @param context The turn context
166
- * @param value The value to set
167
- * @param customKey Optional custom key for storing the state in a specific location
168
357
  * @returns A promise that resolves when the set operation is complete
358
+ *
359
+ * @example Basic usage
360
+ * ```typescript
361
+ * const counterProperty = userState.createProperty<number>("counter");
362
+ *
363
+ * // Set a new value
364
+ * await counterProperty.set(context, 42);
365
+ *
366
+ * // Persist to storage
367
+ * await userState.saveChanges(context);
368
+ * ```
369
+ *
370
+ * @example Complex object
371
+ * ```typescript
372
+ * const userProfile = userState.createProperty<UserProfile>("profile");
373
+ *
374
+ * const newProfile: UserProfile = {
375
+ * name: "John Doe",
376
+ * preferences: { theme: "dark", notifications: false }
377
+ * };
378
+ *
379
+ * await userProfile.set(context, newProfile);
380
+ * await userState.saveChanges(context);
381
+ * ```
382
+ *
383
+ * @example Incremental updates
384
+ * ```typescript
385
+ * // Get current value, modify, then set
386
+ * const settings = await settingsProperty.get(context, getDefaultSettings());
387
+ * settings.theme = "dark";
388
+ * settings.lastUpdated = new Date();
389
+ *
390
+ * await settingsProperty.set(context, settings);
391
+ * await userState.saveChanges(context);
392
+ * ```
393
+ *
394
+ * @example Custom key usage
395
+ * ```typescript
396
+ * const tenantKey = { key: `tenant_${tenantId}` };
397
+ * await dataProperty.set(context, updatedData, tenantKey);
398
+ * await userState.saveChanges(context);
399
+ * ```
169
400
  */
170
401
  async set (context: TurnContext, value: T, customKey?: CustomKey): Promise<void> {
171
402
  const obj: any = await this.state.load(context, false, customKey)
@@ -3,69 +3,99 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ /**
7
+ * HTTP status codes enumeration for agent hosting responses.
8
+ *
9
+ * This enum provides a comprehensive set of HTTP status codes commonly used
10
+ * in agent hosting scenarios, including success, redirection, client error,
11
+ * and server error status codes.
12
+ */
6
13
  export enum StatusCodes {
7
14
  /**
8
15
  * The request has succeeded.
16
+ * Standard response for successful HTTP requests.
9
17
  */
10
18
  OK = 200,
11
19
 
12
20
  /**
13
21
  * The request has been fulfilled and resulted in a new resource being created.
22
+ * Typically returned when a new agent, conversation, or resource is successfully created.
14
23
  */
15
24
  CREATED = 201,
16
25
 
17
26
  /**
18
27
  * Indicates multiple options for the resource that the client may follow.
28
+ * Used when there are multiple possible responses or resource locations available.
19
29
  */
20
30
  MULTIPLE_CHOICES = 300,
21
31
 
22
32
  /**
23
33
  * The server cannot or will not process the request due to a client error.
34
+ * Returned when the request contains invalid syntax, malformed parameters,
35
+ * or violates agent hosting protocol requirements.
24
36
  */
25
37
  BAD_REQUEST = 400,
26
38
 
27
39
  /**
28
40
  * The request requires user authentication.
41
+ * Indicates that the client must authenticate itself to get the requested response.
42
+ * Common in agent scenarios requiring valid authentication tokens or credentials.
29
43
  */
30
44
  UNAUTHORIZED = 401,
31
45
 
32
46
  /**
33
47
  * The requested resource could not be found.
48
+ * Returned when the specified agent, conversation, or endpoint does not exist
49
+ * or is not accessible with the current permissions.
34
50
  */
35
51
  NOT_FOUND = 404,
36
52
 
37
53
  /**
38
54
  * The request method is not allowed for the requested resource.
55
+ * Indicates that the HTTP method used is not supported for the specific
56
+ * agent endpoint or resource being accessed.
39
57
  */
40
58
  METHOD_NOT_ALLOWED = 405,
41
59
 
42
60
  /**
43
61
  * The request could not be completed due to a conflict with the current state of the resource.
62
+ * Common when attempting to create duplicate resources or when agent state
63
+ * conflicts prevent the operation from completing.
44
64
  */
45
65
  CONFLICT = 409,
46
66
 
47
67
  /**
48
68
  * The server does not meet one of the preconditions specified by the client.
69
+ * Returned when conditional requests fail, such as when required headers
70
+ * or agent capabilities are not present or valid.
49
71
  */
50
72
  PRECONDITION_FAILED = 412,
51
73
 
52
74
  /**
53
75
  * The client should switch to a different protocol.
76
+ * Used to indicate that the agent hosting service requires a protocol upgrade
77
+ * or different communication method to fulfill the request.
54
78
  */
55
79
  UPGRADE_REQUIRED = 426,
56
80
 
57
81
  /**
58
82
  * The server encountered an unexpected condition that prevented it from fulfilling the request.
83
+ * Generic error message when an unexpected agent hosting error occurs
84
+ * and no more specific message is suitable.
59
85
  */
60
86
  INTERNAL_SERVER_ERROR = 500,
61
87
 
62
88
  /**
63
89
  * The server does not support the functionality required to fulfill the request.
90
+ * Returned when the agent hosting service does not implement the requested
91
+ * feature or capability.
64
92
  */
65
93
  NOT_IMPLEMENTED = 501,
66
94
 
67
95
  /**
68
96
  * The server received an invalid response from the upstream server.
97
+ * Common when agent hosting services depend on external services
98
+ * that return invalid or malformed responses.
69
99
  */
70
100
  BAD_GATEWAY = 502,
71
101
  }
@@ -1,10 +1,69 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
1
6
  import path from 'path'
2
7
  import fs from 'fs'
3
8
  import { Storage, StoreItem } from './storage'
4
9
 
10
+ /**
11
+ * A file-based storage implementation that persists data to the local filesystem.
12
+ *
13
+ * @remarks
14
+ * FileStorage stores all data in a single JSON file named 'state.json' within a specified folder.
15
+ * This implementation is suitable for development scenarios, local testing, and single-instance
16
+ * deployments where shared state across multiple instances is not required.
17
+ *
18
+ * The storage format is a simple key-value JSON object where keys are strings and values
19
+ * can be any JSON-serializable data. All operations are synchronous file I/O operations
20
+ * wrapped in Promise interfaces to match the Storage contract.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const storage = new FileStorage('./data');
25
+ *
26
+ * // Write some data
27
+ * await storage.write({
28
+ * 'user123': { name: 'John', lastSeen: new Date().toISOString() },
29
+ * 'conversation456': { turn: 5, context: 'discussing weather' }
30
+ * });
31
+ *
32
+ * // Read specific keys
33
+ * const data = await storage.read(['user123']);
34
+ * console.log(data.user123); // { name: 'John', lastSeen: '...' }
35
+ *
36
+ * // Delete data
37
+ * await storage.delete(['conversation456']);
38
+ * ```
39
+ *
40
+ * @warning
41
+ * This implementation does not provide:
42
+ * - Thread safety for concurrent access
43
+ * - Optimistic concurrency control (eTag support)
44
+ * - Atomic operations across multiple keys
45
+ * - Scale for large datasets
46
+ *
47
+ * For production scenarios requiring these features, consider using
48
+ * database-backed storage implementations instead.
49
+ */
5
50
  export class FileStorage implements Storage {
6
51
  private _folder: string
7
52
  private _stateFile: Record<string, string>
53
+
54
+ /**
55
+ * Creates a new FileStorage instance that stores data in the specified folder.
56
+ *
57
+ * @param folder The absolute or relative path to the folder where the state.json file will be stored
58
+ *
59
+ * @remarks
60
+ * The constructor performs the following initialization steps:
61
+ * 1. Creates the target folder if it doesn't exist (including parent directories)
62
+ * 2. Creates an empty state.json file if it doesn't exist
63
+ * 3. Loads existing data from state.json into memory for fast access
64
+ *
65
+ * @throws May throw filesystem errors if the folder cannot be created or accessed
66
+ */
8
67
  constructor (folder: string) {
9
68
  this._folder = folder
10
69
  if (!fs.existsSync(folder)) {
@@ -17,6 +76,19 @@ export class FileStorage implements Storage {
17
76
  this._stateFile = JSON.parse(data)
18
77
  }
19
78
 
79
+ /**
80
+ * Reads store items from the filesystem storage.
81
+ *
82
+ * @param keys Array of keys to read from storage
83
+ * @returns Promise resolving to an object containing the requested items (keys that don't exist are omitted)
84
+ *
85
+ * @throws ReferenceError if keys array is empty or undefined
86
+ *
87
+ * @remarks
88
+ * This method reads from the in-memory cache that was loaded during construction,
89
+ * making it very fast but potentially returning stale data if the file was
90
+ * modified by external processes.
91
+ */
20
92
  read (keys: string[]) : Promise<StoreItem> {
21
93
  return new Promise((resolve, reject) => {
22
94
  if (!keys || keys.length === 0) {
@@ -34,6 +106,20 @@ export class FileStorage implements Storage {
34
106
  })
35
107
  }
36
108
 
109
+ /**
110
+ * Writes store items to the filesystem storage.
111
+ *
112
+ * @param changes Object containing key-value pairs to write to storage
113
+ * @returns Promise that resolves when the write operation completes
114
+ *
115
+ * @remarks
116
+ * This method updates both the in-memory cache and writes the entire state
117
+ * to the state.json file. The file is written with pretty-printing (2-space indentation)
118
+ * for better readability during development and debugging.
119
+ *
120
+ * Note: This implementation does not support eTag-based optimistic concurrency control.
121
+ * Any eTag values in the changes object are ignored.
122
+ */
37
123
  write (changes: StoreItem) : Promise<void> {
38
124
  const keys = Object.keys(changes)
39
125
  for (const key of keys) {
@@ -43,6 +129,19 @@ export class FileStorage implements Storage {
43
129
  return Promise.resolve()
44
130
  }
45
131
 
132
+ /**
133
+ * Deletes store items from the filesystem storage.
134
+ *
135
+ * @param keys Array of keys to delete from storage
136
+ * @returns Promise that resolves when the delete operation completes
137
+ *
138
+ * @throws ReferenceError if keys array is empty or undefined
139
+ *
140
+ * @remarks
141
+ * This method removes the specified keys from both the in-memory cache
142
+ * and writes the updated state to the state.json file. Keys that don't
143
+ * exist in storage are silently ignored.
144
+ */
46
145
  delete (keys: string[]) : Promise<void> {
47
146
  return new Promise((resolve, reject) => {
48
147
  if (!keys || keys.length === 0) {
@@ -4,13 +4,14 @@
4
4
  */
5
5
 
6
6
  import { Storage, StoreItem } from './storage'
7
- import { debug } from '../logger'
7
+ import { debug } from '@microsoft/agents-activity/src/logger'
8
8
 
9
9
  const logger = debug('agents:memory-storage')
10
10
 
11
11
  /**
12
12
  * A simple in-memory storage provider that implements the Storage interface.
13
13
  *
14
+ * @remarks
14
15
  * This class provides a volatile storage solution that keeps data in memory,
15
16
  * which means data is lost when the process terminates. It's primarily useful for:
16
17
  * - Development and testing scenarios
@@ -18,7 +19,7 @@ const logger = debug('agents:memory-storage')
18
19
  * - Stateless environments where external storage isn't available
19
20
  *
20
21
  * MemoryStorage supports optimistic concurrency control through eTags and
21
- * can be used as a singleton through the getSingleInstance() method to
22
+ * can be used as a singleton through the {@link MemoryStorage.getSingleInstance | getSingleInstance() method} to
22
23
  * share state across different parts of an application.
23
24
  */
24
25
  export class MemoryStorage implements Storage {
@@ -48,6 +48,7 @@ export type StorageKeyFactory = (context: TurnContext) => string | Promise<strin
48
48
  /**
49
49
  * Defines the interface for storage operations in the Agents platform.
50
50
  *
51
+ * @remarks
51
52
  * Storage providers persist state data across conversation turns, enabling
52
53
  * agents to maintain context over time. Different implementations may store
53
54
  * data in memory, databases, blob storage, or other persistence mechanisms.
@@ -3,7 +3,7 @@ import { ResourceResponse } from '../connector-client'
3
3
  import { Middleware } from '../middlewareSet'
4
4
  import { TranscriptLogger } from './transcriptLogger'
5
5
  import { Activity, ActivityEventNames, ActivityTypes, ConversationReference, RoleTypes } from '@microsoft/agents-activity'
6
- import { debug } from '../logger'
6
+ import { debug } from '@microsoft/agents-activity/src/logger'
7
7
 
8
8
  const appLogger = debug('agents:rest-client')
9
9
 
@@ -51,6 +51,7 @@ export interface TurnContext {}
51
51
  /**
52
52
  * Represents the context for a single turn in a conversation between a user and an agent.
53
53
  *
54
+ * @remarks
54
55
  * TurnContext is a central concept in the Agents framework - it contains:
55
56
  * - The incoming activity that started the turn
56
57
  * - Access to the adapter that can be used to send responses