@microsoft/agents-hosting 1.9.0-beta.18.g6b8111bba5 → 1.9.0-beta.20.g0c48a31a21
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 +18 -10
- package/dist/package.json +3 -3
- package/dist/src/app/agentApplication.d.ts +1 -0
- package/dist/src/app/agentApplication.js +18 -5
- 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 +10 -4
- 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/errorHelper.js +40 -9
- package/dist/src/errorHelper.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/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 -71
- package/dist/src/storage/fileStorage.js +272 -136
- package/dist/src/storage/fileStorage.js.map +1 -1
- package/dist/src/storage/memoryStorage.d.ts +85 -62
- package/dist/src/storage/memoryStorage.js +240 -109
- package/dist/src/storage/memoryStorage.js.map +1 -1
- package/dist/src/storage/storage.d.ts +101 -16
- 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/package.json +3 -3
- package/src/app/agentApplication.ts +16 -0
- package/src/app/agentApplicationBuilder.ts +13 -2
- package/src/app/agentApplicationOptions.ts +11 -4
- 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/errorHelper.ts +46 -8
- package/src/observability/traces.ts +8 -7
- 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 +289 -134
- package/src/storage/memoryStorage.ts +266 -109
- package/src/storage/storage.ts +115 -17
- package/src/storage/storageCompatibility.ts +185 -0
|
@@ -45,19 +45,6 @@ export interface StoreItems {
|
|
|
45
45
|
*/
|
|
46
46
|
[key: string]: any;
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Options for writing items to storage.
|
|
50
|
-
*/
|
|
51
|
-
export interface StorageWriteOptions {
|
|
52
|
-
/**
|
|
53
|
-
* Optional time to live, in seconds, for written items.
|
|
54
|
-
*
|
|
55
|
-
* @remarks
|
|
56
|
-
* When set, storage providers should stop returning the written items after
|
|
57
|
-
* this duration has elapsed. Values must be finite numbers greater than zero.
|
|
58
|
-
*/
|
|
59
|
-
ttl?: number;
|
|
60
|
-
}
|
|
61
48
|
/**
|
|
62
49
|
* A factory function to generate storage keys based on the conversation context.
|
|
63
50
|
*
|
|
@@ -70,7 +57,7 @@ export interface StorageWriteOptions {
|
|
|
70
57
|
*/
|
|
71
58
|
export type StorageKeyFactory = (context: TurnContext) => string | Promise<string>;
|
|
72
59
|
/**
|
|
73
|
-
* Defines the interface for storage operations in the Agents platform.
|
|
60
|
+
* Defines the version 1 interface for storage operations in the Agents platform.
|
|
74
61
|
*
|
|
75
62
|
* @remarks
|
|
76
63
|
* Storage providers persist state data across conversation turns, enabling
|
|
@@ -79,7 +66,9 @@ export type StorageKeyFactory = (context: TurnContext) => string | Promise<strin
|
|
|
79
66
|
*
|
|
80
67
|
* The interface is designed to be simple with just three core operations:
|
|
81
68
|
* read, write, and delete. All operations are asynchronous to support both
|
|
82
|
-
* in-memory and remote storage providers.
|
|
69
|
+
* in-memory and remote storage providers. New implementations should use
|
|
70
|
+
* {@link StorageV2}; this V1 interface remains supported by
|
|
71
|
+
* {@link StorageProvider} through a compatibility adapter.
|
|
83
72
|
*/
|
|
84
73
|
export interface Storage {
|
|
85
74
|
/**
|
|
@@ -97,7 +86,7 @@ export interface Storage {
|
|
|
97
86
|
* @returns A promise that resolves when the write operation is complete
|
|
98
87
|
* @throws If the changes object is empty or undefined, or if an eTag conflict occurs and optimistic concurrency is enabled
|
|
99
88
|
*/
|
|
100
|
-
write: (changes: StoreItem
|
|
89
|
+
write: (changes: StoreItem) => Promise<void>;
|
|
101
90
|
/**
|
|
102
91
|
* Deletes store items from storage.
|
|
103
92
|
*
|
|
@@ -106,3 +95,99 @@ export interface Storage {
|
|
|
106
95
|
*/
|
|
107
96
|
delete: (keys: string[]) => Promise<void>;
|
|
108
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* The result of a version 2 storage read operation.
|
|
100
|
+
*
|
|
101
|
+
* A result is returned for every requested key. `value` and `version` are
|
|
102
|
+
* available when `status` is {@link StorageOperationStatus.Succeeded}.
|
|
103
|
+
*/
|
|
104
|
+
export interface StorageReadResult<T extends object = Record<string, unknown>> {
|
|
105
|
+
key: string;
|
|
106
|
+
status: StorageOperationStatus;
|
|
107
|
+
value?: T;
|
|
108
|
+
version?: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The result of a version 2 storage write operation.
|
|
112
|
+
*/
|
|
113
|
+
export interface StorageWriteResult {
|
|
114
|
+
key: string;
|
|
115
|
+
status: StorageOperationStatus;
|
|
116
|
+
version?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The result of a version 2 storage delete operation.
|
|
120
|
+
*/
|
|
121
|
+
export interface StorageDeleteResult {
|
|
122
|
+
key: string;
|
|
123
|
+
status: StorageOperationStatus;
|
|
124
|
+
version?: string;
|
|
125
|
+
}
|
|
126
|
+
/** A keyed set of storage read results. */
|
|
127
|
+
export type StorageReadResults<T extends object = Record<string, unknown>> = Record<string, StorageReadResult<T>>;
|
|
128
|
+
/** A keyed set of storage write results. */
|
|
129
|
+
export type StorageWriteResults = Record<string, StorageWriteResult>;
|
|
130
|
+
/** A keyed set of storage delete results. */
|
|
131
|
+
export type StorageDeleteResults = Record<string, StorageDeleteResult>;
|
|
132
|
+
/** The outcome of one version 2 storage operation. */
|
|
133
|
+
export declare enum StorageOperationStatus {
|
|
134
|
+
Succeeded = "succeeded",
|
|
135
|
+
NotFound = "notFound",
|
|
136
|
+
Conflict = "conflict",
|
|
137
|
+
ConditionNotMet = "conditionNotMet"
|
|
138
|
+
}
|
|
139
|
+
/** The write mode for a version 2 storage operation. */
|
|
140
|
+
export declare enum StorageWriteMode {
|
|
141
|
+
Upsert = "upsert",
|
|
142
|
+
CreateOnly = "createOnly",
|
|
143
|
+
Replace = "replace"
|
|
144
|
+
}
|
|
145
|
+
/** Options applied to every item in a version 2 write operation. */
|
|
146
|
+
export interface StorageWriteOptions {
|
|
147
|
+
/**
|
|
148
|
+
* Optional time to live, in seconds, for written items.
|
|
149
|
+
*
|
|
150
|
+
* When set, storage providers stop returning the written items after this
|
|
151
|
+
* duration has elapsed. Values must be finite numbers greater than zero.
|
|
152
|
+
*/
|
|
153
|
+
ttl?: number;
|
|
154
|
+
mode?: StorageWriteMode;
|
|
155
|
+
expectedVersion?: string;
|
|
156
|
+
}
|
|
157
|
+
/** Options applied to every item in a version 2 delete operation. */
|
|
158
|
+
export interface StorageDeleteOptions {
|
|
159
|
+
expectedVersion?: string;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The version 2 storage contract.
|
|
163
|
+
*
|
|
164
|
+
* This does not extend {@link Storage}: JavaScript cannot overload methods by
|
|
165
|
+
* return type at runtime. V2 providers are exposed as separately named classes.
|
|
166
|
+
*/
|
|
167
|
+
export declare abstract class StorageV2 {
|
|
168
|
+
/**
|
|
169
|
+
* Reads stored values and returns one result for every requested key.
|
|
170
|
+
*
|
|
171
|
+
* @param keys The keys to read. An empty array is valid.
|
|
172
|
+
* @returns Keyed results containing a value and storage version when found.
|
|
173
|
+
*/
|
|
174
|
+
abstract read<T extends object = Record<string, unknown>>(keys: string[]): Promise<StorageReadResults<T>>;
|
|
175
|
+
/**
|
|
176
|
+
* Writes values with optional create, replace, or version conditions.
|
|
177
|
+
*
|
|
178
|
+
* @param changes Values indexed by their storage keys.
|
|
179
|
+
* @param options Conditions applied to every value in the batch.
|
|
180
|
+
* @returns One result for every supplied key.
|
|
181
|
+
*/
|
|
182
|
+
abstract write<T extends object = Record<string, unknown>>(changes: Record<string, T>, options?: StorageWriteOptions): Promise<StorageWriteResults>;
|
|
183
|
+
/**
|
|
184
|
+
* Deletes values with an optional version condition.
|
|
185
|
+
*
|
|
186
|
+
* @param keys The keys to delete. An empty array is valid.
|
|
187
|
+
* @param options Conditions applied to every key in the batch.
|
|
188
|
+
* @returns One result for every supplied key.
|
|
189
|
+
*/
|
|
190
|
+
abstract delete(keys: string[], options?: StorageDeleteOptions): Promise<StorageDeleteResults>;
|
|
191
|
+
}
|
|
192
|
+
/** A storage implementation supported by public hosting interfaces. */
|
|
193
|
+
export type StorageProvider = Storage | StorageV2;
|
|
@@ -4,4 +4,29 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.StorageV2 = exports.StorageWriteMode = exports.StorageOperationStatus = void 0;
|
|
8
|
+
/** The outcome of one version 2 storage operation. */
|
|
9
|
+
var StorageOperationStatus;
|
|
10
|
+
(function (StorageOperationStatus) {
|
|
11
|
+
StorageOperationStatus["Succeeded"] = "succeeded";
|
|
12
|
+
StorageOperationStatus["NotFound"] = "notFound";
|
|
13
|
+
StorageOperationStatus["Conflict"] = "conflict";
|
|
14
|
+
StorageOperationStatus["ConditionNotMet"] = "conditionNotMet";
|
|
15
|
+
})(StorageOperationStatus || (exports.StorageOperationStatus = StorageOperationStatus = {}));
|
|
16
|
+
/** The write mode for a version 2 storage operation. */
|
|
17
|
+
var StorageWriteMode;
|
|
18
|
+
(function (StorageWriteMode) {
|
|
19
|
+
StorageWriteMode["Upsert"] = "upsert";
|
|
20
|
+
StorageWriteMode["CreateOnly"] = "createOnly";
|
|
21
|
+
StorageWriteMode["Replace"] = "replace";
|
|
22
|
+
})(StorageWriteMode || (exports.StorageWriteMode = StorageWriteMode = {}));
|
|
23
|
+
/**
|
|
24
|
+
* The version 2 storage contract.
|
|
25
|
+
*
|
|
26
|
+
* This does not extend {@link Storage}: JavaScript cannot overload methods by
|
|
27
|
+
* return type at runtime. V2 providers are exposed as separately named classes.
|
|
28
|
+
*/
|
|
29
|
+
class StorageV2 {
|
|
30
|
+
}
|
|
31
|
+
exports.StorageV2 = StorageV2;
|
|
7
32
|
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/storage/storage.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/storage/storage.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA+IH,sDAAsD;AACtD,IAAY,sBAKX;AALD,WAAY,sBAAsB;IAChC,iDAAuB,CAAA;IACvB,+CAAqB,CAAA;IACrB,+CAAqB,CAAA;IACrB,6DAAmC,CAAA;AACrC,CAAC,EALW,sBAAsB,aAAtB,sBAAsB,GAAtB,sBAAsB,QAKjC;AAED,wDAAwD;AACxD,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,qCAAiB,CAAA;IACjB,6CAAyB,CAAA;IACzB,uCAAmB,CAAA;AACrB,CAAC,EAJW,gBAAgB,aAAhB,gBAAgB,GAAhB,gBAAgB,QAI3B;AAoBD;;;;;GAKG;AACH;CA0BC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { StorageDeleteResults, StorageProvider, StorageReadResults, StorageV2, StorageWriteResults } from './storage';
|
|
6
|
+
/** Returns true when a storage implementation declares the V2 contract. */
|
|
7
|
+
export declare function isStorageV2(storage: StorageProvider): storage is StorageV2;
|
|
8
|
+
/** Converts a supported storage implementation to the V2 contract. */
|
|
9
|
+
export declare function asStorageV2(storage: StorageProvider): StorageV2;
|
|
10
|
+
/** Returns a successful V2 read value, maps not-found to undefined, and rejects invalid results. */
|
|
11
|
+
export declare function getStorageReadValue<T extends object>(results: StorageReadResults<T> | null | undefined, key: string): T | undefined;
|
|
12
|
+
/** Throws when a V2 write did not succeed for every requested key. */
|
|
13
|
+
export declare function assertStorageWriteSucceeded(results: StorageWriteResults | null | undefined, keys: string[]): void;
|
|
14
|
+
/** Throws the state-specific concurrency error when a state write does not succeed. */
|
|
15
|
+
export declare function assertAgentStateWriteSucceeded(results: StorageWriteResults | null | undefined, key: string, name: string): void;
|
|
16
|
+
/** Throws when a V2 delete did not complete with idempotent V1 semantics. */
|
|
17
|
+
export declare function assertStorageDeleteSucceeded(results: StorageDeleteResults | null | undefined, keys: string[]): void;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isStorageV2 = isStorageV2;
|
|
8
|
+
exports.asStorageV2 = asStorageV2;
|
|
9
|
+
exports.getStorageReadValue = getStorageReadValue;
|
|
10
|
+
exports.assertStorageWriteSucceeded = assertStorageWriteSucceeded;
|
|
11
|
+
exports.assertAgentStateWriteSucceeded = assertAgentStateWriteSucceeded;
|
|
12
|
+
exports.assertStorageDeleteSucceeded = assertStorageDeleteSucceeded;
|
|
13
|
+
const agents_activity_1 = require("@microsoft/agents-activity");
|
|
14
|
+
const errorHelper_1 = require("../errorHelper");
|
|
15
|
+
const storage_1 = require("./storage");
|
|
16
|
+
/** Returns true when a storage implementation declares the V2 contract. */
|
|
17
|
+
function isStorageV2(storage) {
|
|
18
|
+
return storage instanceof storage_1.StorageV2;
|
|
19
|
+
}
|
|
20
|
+
/** Converts a supported storage implementation to the V2 contract. */
|
|
21
|
+
function asStorageV2(storage) {
|
|
22
|
+
return isStorageV2(storage) ? storage : new StorageToStorageV2Adapter(storage);
|
|
23
|
+
}
|
|
24
|
+
/** Returns a successful V2 read value, maps not-found to undefined, and rejects invalid results. */
|
|
25
|
+
function getStorageReadValue(results, key) {
|
|
26
|
+
const result = results === null || results === void 0 ? void 0 : results[key];
|
|
27
|
+
if ((result === null || result === void 0 ? void 0 : result.status) === storage_1.StorageOperationStatus.NotFound)
|
|
28
|
+
return undefined;
|
|
29
|
+
if ((result === null || result === void 0 ? void 0 : result.status) === storage_1.StorageOperationStatus.Succeeded)
|
|
30
|
+
return result.value;
|
|
31
|
+
throwStorageResultError('read', key, result === null || result === void 0 ? void 0 : result.status);
|
|
32
|
+
}
|
|
33
|
+
/** Adapts the legacy storage contract to version 2 where its semantics allow it. */
|
|
34
|
+
class StorageToStorageV2Adapter extends storage_1.StorageV2 {
|
|
35
|
+
constructor(storage) {
|
|
36
|
+
super();
|
|
37
|
+
this.storage = storage;
|
|
38
|
+
}
|
|
39
|
+
async read(keys) {
|
|
40
|
+
validateKeys(keys);
|
|
41
|
+
if (keys.length === 0)
|
|
42
|
+
return {};
|
|
43
|
+
const items = await this.storage.read(keys);
|
|
44
|
+
return Object.fromEntries(keys.map(key => {
|
|
45
|
+
const value = items[key];
|
|
46
|
+
return [key, Object.prototype.hasOwnProperty.call(items, key)
|
|
47
|
+
? { key, status: storage_1.StorageOperationStatus.Succeeded, value: value, version: value === null || value === void 0 ? void 0 : value.eTag }
|
|
48
|
+
: { key, status: storage_1.StorageOperationStatus.NotFound }];
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
async write(changes, options) {
|
|
52
|
+
validateChanges(changes);
|
|
53
|
+
if ((options === null || options === void 0 ? void 0 : options.mode) !== undefined && options.mode !== storage_1.StorageWriteMode.Upsert) {
|
|
54
|
+
throwUnsupportedOption('mode');
|
|
55
|
+
}
|
|
56
|
+
if ((options === null || options === void 0 ? void 0 : options.ttl) !== undefined) {
|
|
57
|
+
throwUnsupportedOption('ttl');
|
|
58
|
+
}
|
|
59
|
+
validateExpectedVersion(options === null || options === void 0 ? void 0 : options.expectedVersion);
|
|
60
|
+
if (Object.keys(changes).length === 0)
|
|
61
|
+
return {};
|
|
62
|
+
const legacyChanges = Object.fromEntries(Object.entries(changes).map(([key, value]) => [
|
|
63
|
+
key,
|
|
64
|
+
(options === null || options === void 0 ? void 0 : options.expectedVersion) === undefined
|
|
65
|
+
? removeLegacyETag(value)
|
|
66
|
+
: { ...removeLegacyETag(value), eTag: options.expectedVersion },
|
|
67
|
+
]));
|
|
68
|
+
await this.storage.write(legacyChanges);
|
|
69
|
+
return Object.fromEntries(Object.keys(changes).map(key => [key, { key, status: storage_1.StorageOperationStatus.Succeeded }]));
|
|
70
|
+
}
|
|
71
|
+
async delete(keys, options) {
|
|
72
|
+
validateDeleteKeys(keys);
|
|
73
|
+
validateExpectedVersion(options === null || options === void 0 ? void 0 : options.expectedVersion);
|
|
74
|
+
if ((options === null || options === void 0 ? void 0 : options.expectedVersion) !== undefined) {
|
|
75
|
+
throwUnsupportedOption('expectedVersion');
|
|
76
|
+
}
|
|
77
|
+
if (keys.length === 0)
|
|
78
|
+
return {};
|
|
79
|
+
await this.storage.delete(keys);
|
|
80
|
+
return Object.fromEntries(keys.map(key => [key, { key, status: storage_1.StorageOperationStatus.Succeeded }]));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function validateKeys(keys) {
|
|
84
|
+
if (!Array.isArray(keys)) {
|
|
85
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageReadKeysRequired);
|
|
86
|
+
}
|
|
87
|
+
if (keys.some(key => typeof key !== 'string' || key.trim() === '')) {
|
|
88
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageV2KeyRequired);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function validateDeleteKeys(keys) {
|
|
92
|
+
if (!Array.isArray(keys)) {
|
|
93
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageDeleteKeysRequired);
|
|
94
|
+
}
|
|
95
|
+
if (keys.some(key => typeof key !== 'string' || key.trim() === '')) {
|
|
96
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageV2KeyRequired);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function validateChanges(changes) {
|
|
100
|
+
if (changes === null || typeof changes !== 'object' || Array.isArray(changes)) {
|
|
101
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageWriteChangesRequired);
|
|
102
|
+
}
|
|
103
|
+
if (Object.keys(changes).some(key => key.trim() === '')) {
|
|
104
|
+
throw agents_activity_1.ExceptionHelper.generateException(ReferenceError, errorHelper_1.Errors.StorageV2KeyRequired);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function removeLegacyETag(value) {
|
|
108
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
109
|
+
return value;
|
|
110
|
+
const { eTag: _eTag, ...withoutETag } = value;
|
|
111
|
+
return withoutETag;
|
|
112
|
+
}
|
|
113
|
+
function validateExpectedVersion(expectedVersion) {
|
|
114
|
+
if (expectedVersion === '') {
|
|
115
|
+
throw agents_activity_1.ExceptionHelper.generateException(RangeError, errorHelper_1.Errors.StorageV2ExpectedVersionEmpty);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function throwUnsupportedOption(option) {
|
|
119
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.StorageV2UnsupportedOption, undefined, { option });
|
|
120
|
+
}
|
|
121
|
+
/** Throws when a V2 write did not succeed for every requested key. */
|
|
122
|
+
function assertStorageWriteSucceeded(results, keys) {
|
|
123
|
+
assertStorageResults('write', results, keys, new Set([storage_1.StorageOperationStatus.Succeeded]));
|
|
124
|
+
}
|
|
125
|
+
/** Throws the state-specific concurrency error when a state write does not succeed. */
|
|
126
|
+
function assertAgentStateWriteSucceeded(results, key, name) {
|
|
127
|
+
var _a;
|
|
128
|
+
const status = (_a = results === null || results === void 0 ? void 0 : results[key]) === null || _a === void 0 ? void 0 : _a.status;
|
|
129
|
+
if (status !== storage_1.StorageOperationStatus.Succeeded) {
|
|
130
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.AgentStateWriteConflict, undefined, {
|
|
131
|
+
name,
|
|
132
|
+
key,
|
|
133
|
+
status: status !== null && status !== void 0 ? status : 'missing',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Throws when a V2 delete did not complete with idempotent V1 semantics. */
|
|
138
|
+
function assertStorageDeleteSucceeded(results, keys) {
|
|
139
|
+
assertStorageResults('delete', results, keys, new Set([storage_1.StorageOperationStatus.Succeeded, storage_1.StorageOperationStatus.NotFound]));
|
|
140
|
+
}
|
|
141
|
+
function assertStorageResults(operation, results, keys, acceptedStatuses) {
|
|
142
|
+
var _a;
|
|
143
|
+
for (const key of keys) {
|
|
144
|
+
const status = (_a = results === null || results === void 0 ? void 0 : results[key]) === null || _a === void 0 ? void 0 : _a.status;
|
|
145
|
+
if (status === undefined || !acceptedStatuses.has(status)) {
|
|
146
|
+
throwStorageResultError(operation, key, status);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function throwStorageResultError(operation, key, status) {
|
|
151
|
+
throw agents_activity_1.ExceptionHelper.generateException(Error, errorHelper_1.Errors.StorageV2OperationFailed, undefined, {
|
|
152
|
+
operation,
|
|
153
|
+
key,
|
|
154
|
+
status: status !== null && status !== void 0 ? status : 'missing',
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=storageCompatibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageCompatibility.js","sourceRoot":"","sources":["../../../src/storage/storageCompatibility.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@microsoft/agents-hosting",
|
|
4
|
-
"version": "1.9.0-beta.
|
|
4
|
+
"version": "1.9.0-beta.20.g0c48a31a21",
|
|
5
5
|
"homepage": "https://github.com/microsoft/Agents-for-js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@azure/core-auth": "1.10.1",
|
|
23
23
|
"@azure/msal-node": "5.6.0",
|
|
24
|
-
"@microsoft/agents-activity": "1.9.0-beta.
|
|
25
|
-
"@microsoft/agents-telemetry": "1.9.0-beta.
|
|
24
|
+
"@microsoft/agents-activity": "1.9.0-beta.20.g0c48a31a21",
|
|
25
|
+
"@microsoft/agents-telemetry": "1.9.0-beta.20.g0c48a31a21",
|
|
26
26
|
"jsonwebtoken": "9.0.3",
|
|
27
27
|
"jwks-rsa": "4.0.1",
|
|
28
28
|
"zod": "3.25.75"
|
|
@@ -20,6 +20,7 @@ import { TranscriptLoggerMiddleware } from '../transcript'
|
|
|
20
20
|
import { CloudAdapter } from '../cloudAdapter'
|
|
21
21
|
import { Authorization, UserAuthorization, AuthorizationManager } from './auth'
|
|
22
22
|
import { Proactive } from './proactive'
|
|
23
|
+
import { AgentApplicationRateLimiter } from './rateLimit'
|
|
23
24
|
import { JwtPayload } from 'jsonwebtoken'
|
|
24
25
|
import { trace, debug, redactString } from '@microsoft/agents-telemetry'
|
|
25
26
|
import { AgentApplicationTraceDefinitions } from '../observability'
|
|
@@ -104,6 +105,7 @@ export class AgentApplication<TState extends TurnState> {
|
|
|
104
105
|
private readonly _proactive?: Proactive<TState>
|
|
105
106
|
protected readonly _extensions: AgentExtension<TState>[] = []
|
|
106
107
|
private readonly _adaptiveCards: AdaptiveCardsActions<TState>
|
|
108
|
+
private readonly _rateLimiter?: AgentApplicationRateLimiter
|
|
107
109
|
|
|
108
110
|
/**
|
|
109
111
|
* Creates a new instance of AgentApplication.
|
|
@@ -141,6 +143,7 @@ export class AgentApplication<TState extends TurnState> {
|
|
|
141
143
|
longRunningMessages: options?.longRunningMessages !== undefined ? options.longRunningMessages : false,
|
|
142
144
|
removeRecipientMention: options?.removeRecipientMention !== undefined ? options.removeRecipientMention : true,
|
|
143
145
|
transcriptLogger: options?.transcriptLogger || undefined,
|
|
146
|
+
rateLimit: options?.rateLimit || undefined,
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
this._adaptiveCards = new AdaptiveCardsActions<TState>(this)
|
|
@@ -158,6 +161,10 @@ export class AgentApplication<TState extends TurnState> {
|
|
|
158
161
|
|
|
159
162
|
this._adapter.setAgentName(this._options.agentName)
|
|
160
163
|
|
|
164
|
+
if (this._options.rateLimit && this._options.rateLimit.length > 0) {
|
|
165
|
+
this._rateLimiter = new AgentApplicationRateLimiter(this._options.rateLimit, this._options.storage)
|
|
166
|
+
}
|
|
167
|
+
|
|
161
168
|
// Create Proactive whenever proactive options are explicitly configured or a storage
|
|
162
169
|
// backend is available — no explicit `proactive` option is required.
|
|
163
170
|
if (this._options.proactive !== undefined || this._options.storage !== undefined) {
|
|
@@ -206,6 +213,7 @@ export class AgentApplication<TState extends TurnState> {
|
|
|
206
213
|
fileDownloaders: this._options.fileDownloaders ? 'configured' : undefined,
|
|
207
214
|
turnStateFactory: options?.turnStateFactory ? 'custom' : 'default',
|
|
208
215
|
adaptiveCardsOptions: this._options.adaptiveCardsOptions,
|
|
216
|
+
rateLimitRules: this._options.rateLimit?.length,
|
|
209
217
|
})
|
|
210
218
|
}
|
|
211
219
|
|
|
@@ -672,6 +680,14 @@ export class AgentApplication<TState extends TurnState> {
|
|
|
672
680
|
* ```
|
|
673
681
|
*/
|
|
674
682
|
public async runInternal (turnContext: TurnContext): Promise<boolean> {
|
|
683
|
+
if (this._rateLimiter) {
|
|
684
|
+
const rateLimitDecision = await this._rateLimiter.shouldAllowTurn(turnContext)
|
|
685
|
+
if (!rateLimitDecision.allowed) {
|
|
686
|
+
await this._rateLimiter.handleThrottledTurn(turnContext, rateLimitDecision.rule!, rateLimitDecision.result!)
|
|
687
|
+
return false
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
675
691
|
const { authorized, context } = await this.handleAuthorization(turnContext)
|
|
676
692
|
|
|
677
693
|
if (!authorized) {
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { StorageProvider } from '../storage'
|
|
7
7
|
import { AgentApplication } from './agentApplication'
|
|
8
8
|
import { AgentApplicationOptions } from './agentApplicationOptions'
|
|
9
9
|
import { AuthorizationOptions } from './auth/types'
|
|
10
10
|
import { ProactiveOptions } from './proactive'
|
|
11
|
+
import { RateLimitRule } from './rateLimit'
|
|
11
12
|
import { TurnState } from './turnState'
|
|
12
13
|
import { TypingOptions } from './agentApplicationOptions'
|
|
13
14
|
|
|
@@ -31,7 +32,7 @@ export class AgentApplicationBuilder<TState extends TurnState = TurnState> {
|
|
|
31
32
|
* @param storage The storage implementation to use
|
|
32
33
|
* @returns This builder instance for chaining
|
|
33
34
|
*/
|
|
34
|
-
public withStorage (storage:
|
|
35
|
+
public withStorage (storage: StorageProvider): this {
|
|
35
36
|
this._options.storage = storage
|
|
36
37
|
return this
|
|
37
38
|
}
|
|
@@ -86,6 +87,16 @@ export class AgentApplicationBuilder<TState extends TurnState = TurnState> {
|
|
|
86
87
|
return this
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Configures rate limit rules for incoming turns.
|
|
92
|
+
* @param rules The rate limit rules to apply
|
|
93
|
+
* @returns This builder instance for chaining
|
|
94
|
+
*/
|
|
95
|
+
public withRateLimit (rules: RateLimitRule[]): this {
|
|
96
|
+
this._options.rateLimit = rules
|
|
97
|
+
return this
|
|
98
|
+
}
|
|
99
|
+
|
|
89
100
|
/**
|
|
90
101
|
* Builds and returns a new AgentApplication instance configured with the provided options.
|
|
91
102
|
* @returns A new AgentApplication instance
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { CloudAdapter } from '../cloudAdapter'
|
|
7
|
-
import {
|
|
7
|
+
import { StorageProvider } from '../storage'
|
|
8
8
|
import { TranscriptLogger } from '../transcript'
|
|
9
9
|
import { AdaptiveCardsOptions } from './adaptiveCards'
|
|
10
10
|
import { InputFileDownloader } from './inputFileDownloader'
|
|
@@ -13,6 +13,7 @@ import { HeaderPropagationDefinition } from '../headerPropagation'
|
|
|
13
13
|
import { AuthorizationOptions } from './auth/types'
|
|
14
14
|
import { Connections } from '../auth/connections'
|
|
15
15
|
import { ProactiveOptions } from './proactive'
|
|
16
|
+
import { RateLimitRule } from './rateLimit'
|
|
16
17
|
import { ConfigurationContext } from '../configuration/configuration'
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -79,12 +80,12 @@ export interface AgentApplicationOptions<TState extends TurnState> {
|
|
|
79
80
|
|
|
80
81
|
/**
|
|
81
82
|
* The storage mechanism for persisting conversation and user state across turns.
|
|
82
|
-
* This can be
|
|
83
|
-
*
|
|
83
|
+
* This can be a legacy Storage implementation, a StorageV2 implementation,
|
|
84
|
+
* or a built-in storage provider.
|
|
84
85
|
*
|
|
85
86
|
* @default undefined (no persistence)
|
|
86
87
|
*/
|
|
87
|
-
storage?:
|
|
88
|
+
storage?: StorageProvider;
|
|
88
89
|
|
|
89
90
|
/**
|
|
90
91
|
* Whether to start a typing indicator timer when the bot begins processing a message.
|
|
@@ -208,4 +209,10 @@ export interface AgentApplicationOptions<TState extends TurnState> {
|
|
|
208
209
|
* When provided, `app.proactive` will be available.
|
|
209
210
|
*/
|
|
210
211
|
proactive?: ProactiveOptions
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Optional. Rate limit rules for incoming turns.
|
|
215
|
+
* When omitted or empty, no rate limiting is applied.
|
|
216
|
+
*/
|
|
217
|
+
rateLimit?: RateLimitRule[]
|
|
211
218
|
}
|
|
@@ -5,10 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
import { ActiveAuthorizationHandler } from './types'
|
|
7
7
|
import { TurnContext } from '../../turnContext'
|
|
8
|
-
import {
|
|
8
|
+
import { StorageProvider, StorageV2 } from '../../storage'
|
|
9
|
+
import {
|
|
10
|
+
asStorageV2,
|
|
11
|
+
assertStorageDeleteSucceeded,
|
|
12
|
+
assertStorageWriteSucceeded,
|
|
13
|
+
getStorageReadValue,
|
|
14
|
+
} from '../../storage/storageCompatibility'
|
|
9
15
|
import { ExceptionHelper } from '@microsoft/agents-activity'
|
|
10
16
|
import { Errors } from '../../errorHelper'
|
|
11
17
|
|
|
18
|
+
// Version metadata only bridges reads and writes in one turn. Cloned contexts share turnState.
|
|
19
|
+
const HANDLER_STORAGE_VERSIONS = Symbol('handlerStorageVersions')
|
|
20
|
+
|
|
12
21
|
/**
|
|
13
22
|
* Storage manager for handler state.
|
|
14
23
|
*/
|
|
@@ -18,7 +27,11 @@ export class HandlerStorage<TActiveHandler extends ActiveAuthorizationHandler =
|
|
|
18
27
|
* @param storage The storage provider.
|
|
19
28
|
* @param context The turn context.
|
|
20
29
|
*/
|
|
21
|
-
|
|
30
|
+
private readonly storage: StorageV2
|
|
31
|
+
|
|
32
|
+
constructor (storage: StorageProvider, private context: TurnContext) {
|
|
33
|
+
this.storage = asStorageV2(storage)
|
|
34
|
+
}
|
|
22
35
|
|
|
23
36
|
/**
|
|
24
37
|
* Gets the unique key for a handler session.
|
|
@@ -36,15 +49,23 @@ export class HandlerStorage<TActiveHandler extends ActiveAuthorizationHandler =
|
|
|
36
49
|
* Reads the active handler state from storage.
|
|
37
50
|
*/
|
|
38
51
|
public async read (): Promise<TActiveHandler | undefined> {
|
|
39
|
-
const ongoing = await this.storage.read([this.key])
|
|
40
|
-
|
|
52
|
+
const ongoing = await this.storage.read<TActiveHandler>([this.key])
|
|
53
|
+
const value = getStorageReadValue(ongoing, this.key)
|
|
54
|
+
this.version = ongoing[this.key]?.version
|
|
55
|
+
return value
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
/**
|
|
44
59
|
* Writes handler state to storage.
|
|
45
60
|
*/
|
|
46
|
-
public write (data: TActiveHandler) : Promise<void> {
|
|
47
|
-
|
|
61
|
+
public async write (data: TActiveHandler) : Promise<void> {
|
|
62
|
+
const { eTag: _eTag, ...value } = data
|
|
63
|
+
const results = await this.storage.write(
|
|
64
|
+
{ [this.key]: value },
|
|
65
|
+
this.version === undefined ? undefined : { expectedVersion: this.version }
|
|
66
|
+
)
|
|
67
|
+
assertStorageWriteSucceeded(results, [this.key])
|
|
68
|
+
this.version = results[this.key]?.version
|
|
48
69
|
}
|
|
49
70
|
|
|
50
71
|
/**
|
|
@@ -52,7 +73,9 @@ export class HandlerStorage<TActiveHandler extends ActiveAuthorizationHandler =
|
|
|
52
73
|
*/
|
|
53
74
|
public async delete (): Promise<void> {
|
|
54
75
|
try {
|
|
55
|
-
await this.storage.delete([this.key])
|
|
76
|
+
const results = await this.storage.delete([this.key])
|
|
77
|
+
assertStorageDeleteSucceeded(results, [this.key])
|
|
78
|
+
this.version = undefined
|
|
56
79
|
} catch (error) {
|
|
57
80
|
if (error instanceof Error && 'code' in error && error.code === 404) {
|
|
58
81
|
return
|
|
@@ -60,4 +83,25 @@ export class HandlerStorage<TActiveHandler extends ActiveAuthorizationHandler =
|
|
|
60
83
|
throw error
|
|
61
84
|
}
|
|
62
85
|
}
|
|
86
|
+
|
|
87
|
+
private get version (): string | undefined {
|
|
88
|
+
return this.context.turnState.get<Map<string, string>>(HANDLER_STORAGE_VERSIONS)?.get(this.key)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private set version (value: string | undefined) {
|
|
92
|
+
let versions = this.context.turnState.get<Map<string, string>>(HANDLER_STORAGE_VERSIONS)
|
|
93
|
+
if (value === undefined) {
|
|
94
|
+
versions?.delete(this.key)
|
|
95
|
+
if (versions?.size === 0) {
|
|
96
|
+
this.context.turnState.delete(HANDLER_STORAGE_VERSIONS)
|
|
97
|
+
}
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!versions) {
|
|
102
|
+
versions = new Map<string, string>()
|
|
103
|
+
this.context.turnState.set(HANDLER_STORAGE_VERSIONS, versions)
|
|
104
|
+
}
|
|
105
|
+
versions.set(this.key, value)
|
|
106
|
+
}
|
|
63
107
|
}
|
package/src/app/auth/types.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Activity } from '@microsoft/agents-activity'
|
|
7
|
-
import {
|
|
7
|
+
import { StorageProvider, StoreItem } from '../../storage'
|
|
8
8
|
import { TurnContext } from '../../turnContext'
|
|
9
9
|
import { AgenticAuthorizationOptions, AzureBotAuthorizationOptions } from './handlers'
|
|
10
10
|
import { TokenResponse } from '../../oauth'
|
|
@@ -97,7 +97,7 @@ export interface AuthorizationHandlerSettings {
|
|
|
97
97
|
/**
|
|
98
98
|
* Storage instance for persisting handler state.
|
|
99
99
|
*/
|
|
100
|
-
storage:
|
|
100
|
+
storage: StorageProvider
|
|
101
101
|
/**
|
|
102
102
|
* Connections instance for managing authentication connections.
|
|
103
103
|
*/
|
package/src/app/index.ts
CHANGED
|
@@ -28,3 +28,10 @@ export * from './streaming/streamingResponse'
|
|
|
28
28
|
export * from './streaming/citation'
|
|
29
29
|
export * from './teamsAttachmentDownloader'
|
|
30
30
|
export * from './proactive'
|
|
31
|
+
export type {
|
|
32
|
+
RateLimitMessageFactory,
|
|
33
|
+
RateLimitResult,
|
|
34
|
+
RateLimitRule,
|
|
35
|
+
RateLimitScope,
|
|
36
|
+
RateLimitStorageErrorBehavior
|
|
37
|
+
} from './rateLimit'
|