@bowenqt/qiniu-ai-sdk 0.28.2 → 0.28.3
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/dist/ai/a2a/expert.d.ts +0 -1
- package/dist/ai/a2a/expert.d.ts.map +1 -1
- package/dist/ai/a2a/expert.js +12 -20
- package/dist/ai/a2a/expert.js.map +1 -1
- package/dist/ai/a2a/expert.mjs +13 -21
- package/dist/ai/a2a/index.d.ts +1 -1
- package/dist/ai/a2a/index.d.ts.map +1 -1
- package/dist/ai/a2a/index.js +2 -1
- package/dist/ai/a2a/index.js.map +1 -1
- package/dist/ai/a2a/index.mjs +1 -1
- package/dist/ai/a2a/rate-limiter.d.ts +9 -7
- package/dist/ai/a2a/rate-limiter.d.ts.map +1 -1
- package/dist/ai/a2a/rate-limiter.js +55 -15
- package/dist/ai/a2a/rate-limiter.js.map +1 -1
- package/dist/ai/a2a/rate-limiter.mjs +53 -14
- package/package.json +1 -1
package/dist/ai/a2a/expert.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export declare class AgentExpert {
|
|
|
23
23
|
static from(agent: Agent, config: AgentExpertConfig): AgentExpert;
|
|
24
24
|
/**
|
|
25
25
|
* Direct tool call with full request.
|
|
26
|
-
* Note: `from` field is ignored for rate limiting - expert.id is always used.
|
|
27
26
|
*/
|
|
28
27
|
callTool(request: CallToolRequest): Promise<A2AMessage>;
|
|
29
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expert.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAA+B,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EACR,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,cAAc,EACd,aAAa,EAChB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"expert.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAA+B,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EACR,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,cAAc,EACd,aAAa,EAChB,MAAM,SAAS,CAAC;AAajB;;GAEG;AACH,qBAAa,WAAW;IACpB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAErC,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAkG;IAChH,OAAO,CAAC,WAAW,CAAC,CAAiB;IACrC,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO;IAoBP;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,WAAW;IAiCjE;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IA8E7D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAgB9D;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;CAGlC"}
|
package/dist/ai/a2a/expert.js
CHANGED
|
@@ -38,7 +38,7 @@ class AgentExpert {
|
|
|
38
38
|
const rateLimiter = config.rateLimit
|
|
39
39
|
? new rate_limiter_1.A2ARateLimiter(config.rateLimit)
|
|
40
40
|
: undefined;
|
|
41
|
-
// Build exposed tools
|
|
41
|
+
// Build exposed tools - all go through execute() for FIFO fairness
|
|
42
42
|
const exposedTools = {};
|
|
43
43
|
for (const toolName of config.expose) {
|
|
44
44
|
const tool = originalTools[toolName];
|
|
@@ -47,13 +47,12 @@ class AgentExpert {
|
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
49
|
const prefixedName = `${prefix}${toolName}`;
|
|
50
|
-
exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true
|
|
50
|
+
exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true);
|
|
51
51
|
}
|
|
52
52
|
return new AgentExpert(agent, config, exposedTools, originalTools, rateLimiter);
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Direct tool call with full request.
|
|
56
|
-
* Note: `from` field is ignored for rate limiting - expert.id is always used.
|
|
57
56
|
*/
|
|
58
57
|
async callTool(request) {
|
|
59
58
|
const requestId = request.requestId ?? (0, types_1.generateRequestId)();
|
|
@@ -81,15 +80,19 @@ class AgentExpert {
|
|
|
81
80
|
if (signal?.aborted) {
|
|
82
81
|
return (0, types_1.createA2AError)(baseRequest, 'CANCELLED', 'Request was cancelled');
|
|
83
82
|
}
|
|
84
|
-
// Rate limiting (
|
|
83
|
+
// Rate limiting via execute() for FIFO fairness with exposed tools
|
|
85
84
|
if (this.rateLimiter) {
|
|
86
85
|
try {
|
|
87
|
-
|
|
86
|
+
// Use execute() which handles queue fairness and abort
|
|
87
|
+
await this.rateLimiter.execute(this.id, tool, async () => { }, signal);
|
|
88
88
|
}
|
|
89
89
|
catch (error) {
|
|
90
90
|
if (error instanceof rate_limiter_1.RateLimitError) {
|
|
91
91
|
return (0, types_1.createA2AError)(baseRequest, 'RATE_LIMITED', error.message);
|
|
92
92
|
}
|
|
93
|
+
if (error instanceof rate_limiter_1.AbortError) {
|
|
94
|
+
return (0, types_1.createA2AError)(baseRequest, 'CANCELLED', error.message);
|
|
95
|
+
}
|
|
93
96
|
throw error;
|
|
94
97
|
}
|
|
95
98
|
}
|
|
@@ -143,9 +146,9 @@ exports.AgentExpert = AgentExpert;
|
|
|
143
146
|
// Helper Functions
|
|
144
147
|
// ============================================================================
|
|
145
148
|
/**
|
|
146
|
-
* Create a wrapped tool
|
|
149
|
+
* Create a wrapped tool - all tools go through execute() for FIFO fairness.
|
|
147
150
|
*/
|
|
148
|
-
function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs
|
|
151
|
+
function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs) {
|
|
149
152
|
return {
|
|
150
153
|
description: original.description,
|
|
151
154
|
parameters: original.parameters,
|
|
@@ -153,20 +156,9 @@ function createWrappedTool(original, toolName, expertId, rateLimiter, validateAr
|
|
|
153
156
|
approvalHandler: original.approvalHandler,
|
|
154
157
|
source: original.source,
|
|
155
158
|
execute: async (args, context) => {
|
|
156
|
-
// Rate limiting
|
|
159
|
+
// Rate limiting via execute() for FIFO fairness
|
|
157
160
|
if (rateLimiter) {
|
|
158
|
-
|
|
159
|
-
// Wait for slot (throws on timeout)
|
|
160
|
-
await rateLimiter.waitForSlot(expertId, toolName);
|
|
161
|
-
rateLimiter.track(expertId, toolName);
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
// Reject immediately if not allowed
|
|
165
|
-
if (!rateLimiter.isAllowed(expertId, toolName)) {
|
|
166
|
-
throw new rate_limiter_1.RateLimitError(expertId, toolName, rateLimiter.getTimeUntilSlot(expertId, toolName));
|
|
167
|
-
}
|
|
168
|
-
rateLimiter.track(expertId, toolName);
|
|
169
|
-
}
|
|
161
|
+
await rateLimiter.execute(expertId, toolName, async () => { }, context.abortSignal);
|
|
170
162
|
}
|
|
171
163
|
// Validate
|
|
172
164
|
if (validateArgs && original.parameters) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expert.js","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAWH,
|
|
1
|
+
{"version":3,"file":"expert.js","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":"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"}
|
package/dist/ai/a2a/expert.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { generateRequestId, createA2AResponse, createA2AError, } from './types.mjs';
|
|
5
5
|
import { validateSchema } from './validation.mjs';
|
|
6
|
-
import { A2ARateLimiter, RateLimitError } from './rate-limiter.mjs';
|
|
6
|
+
import { A2ARateLimiter, RateLimitError, AbortError } from './rate-limiter.mjs';
|
|
7
7
|
// ============================================================================
|
|
8
8
|
// AgentExpert
|
|
9
9
|
// ============================================================================
|
|
@@ -35,7 +35,7 @@ export class AgentExpert {
|
|
|
35
35
|
const rateLimiter = config.rateLimit
|
|
36
36
|
? new A2ARateLimiter(config.rateLimit)
|
|
37
37
|
: undefined;
|
|
38
|
-
// Build exposed tools
|
|
38
|
+
// Build exposed tools - all go through execute() for FIFO fairness
|
|
39
39
|
const exposedTools = {};
|
|
40
40
|
for (const toolName of config.expose) {
|
|
41
41
|
const tool = originalTools[toolName];
|
|
@@ -44,13 +44,12 @@ export class AgentExpert {
|
|
|
44
44
|
continue;
|
|
45
45
|
}
|
|
46
46
|
const prefixedName = `${prefix}${toolName}`;
|
|
47
|
-
exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true
|
|
47
|
+
exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true);
|
|
48
48
|
}
|
|
49
49
|
return new AgentExpert(agent, config, exposedTools, originalTools, rateLimiter);
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Direct tool call with full request.
|
|
53
|
-
* Note: `from` field is ignored for rate limiting - expert.id is always used.
|
|
54
53
|
*/
|
|
55
54
|
async callTool(request) {
|
|
56
55
|
const requestId = request.requestId ?? generateRequestId();
|
|
@@ -78,15 +77,19 @@ export class AgentExpert {
|
|
|
78
77
|
if (signal?.aborted) {
|
|
79
78
|
return createA2AError(baseRequest, 'CANCELLED', 'Request was cancelled');
|
|
80
79
|
}
|
|
81
|
-
// Rate limiting (
|
|
80
|
+
// Rate limiting via execute() for FIFO fairness with exposed tools
|
|
82
81
|
if (this.rateLimiter) {
|
|
83
82
|
try {
|
|
84
|
-
|
|
83
|
+
// Use execute() which handles queue fairness and abort
|
|
84
|
+
await this.rateLimiter.execute(this.id, tool, async () => { }, signal);
|
|
85
85
|
}
|
|
86
86
|
catch (error) {
|
|
87
87
|
if (error instanceof RateLimitError) {
|
|
88
88
|
return createA2AError(baseRequest, 'RATE_LIMITED', error.message);
|
|
89
89
|
}
|
|
90
|
+
if (error instanceof AbortError) {
|
|
91
|
+
return createA2AError(baseRequest, 'CANCELLED', error.message);
|
|
92
|
+
}
|
|
90
93
|
throw error;
|
|
91
94
|
}
|
|
92
95
|
}
|
|
@@ -139,9 +142,9 @@ export class AgentExpert {
|
|
|
139
142
|
// Helper Functions
|
|
140
143
|
// ============================================================================
|
|
141
144
|
/**
|
|
142
|
-
* Create a wrapped tool
|
|
145
|
+
* Create a wrapped tool - all tools go through execute() for FIFO fairness.
|
|
143
146
|
*/
|
|
144
|
-
function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs
|
|
147
|
+
function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs) {
|
|
145
148
|
return {
|
|
146
149
|
description: original.description,
|
|
147
150
|
parameters: original.parameters,
|
|
@@ -149,20 +152,9 @@ function createWrappedTool(original, toolName, expertId, rateLimiter, validateAr
|
|
|
149
152
|
approvalHandler: original.approvalHandler,
|
|
150
153
|
source: original.source,
|
|
151
154
|
execute: async (args, context) => {
|
|
152
|
-
// Rate limiting
|
|
155
|
+
// Rate limiting via execute() for FIFO fairness
|
|
153
156
|
if (rateLimiter) {
|
|
154
|
-
|
|
155
|
-
// Wait for slot (throws on timeout)
|
|
156
|
-
await rateLimiter.waitForSlot(expertId, toolName);
|
|
157
|
-
rateLimiter.track(expertId, toolName);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
// Reject immediately if not allowed
|
|
161
|
-
if (!rateLimiter.isAllowed(expertId, toolName)) {
|
|
162
|
-
throw new RateLimitError(expertId, toolName, rateLimiter.getTimeUntilSlot(expertId, toolName));
|
|
163
|
-
}
|
|
164
|
-
rateLimiter.track(expertId, toolName);
|
|
165
|
-
}
|
|
157
|
+
await rateLimiter.execute(expertId, toolName, async () => { }, context.abortSignal);
|
|
166
158
|
}
|
|
167
159
|
// Validate
|
|
168
160
|
if (validateArgs && original.parameters) {
|
package/dist/ai/a2a/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
export type { A2AMessage, A2AError, A2AErrorCode, RateLimitConfig, AgentExpertConfig, CallToolRequest, RunTaskRequest, RunTaskResult, } from './types';
|
|
5
5
|
export { generateRequestId, createA2ARequest, createA2AResponse, createA2AError, } from './types';
|
|
6
6
|
export { validateSchema, sanitizeArgs, cloneAndSanitize, type ValidationResult, type JsonSchema, } from './validation';
|
|
7
|
-
export { A2ARateLimiter, RateLimitError } from './rate-limiter';
|
|
7
|
+
export { A2ARateLimiter, RateLimitError, AbortError } from './rate-limiter';
|
|
8
8
|
export { AgentExpert } from './expert';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACR,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACR,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,aAAa,GAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/ai/a2a/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* A2A (Agent-to-Agent) Protocol - Public exports.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.AgentExpert = exports.RateLimitError = exports.A2ARateLimiter = exports.cloneAndSanitize = exports.sanitizeArgs = exports.validateSchema = exports.createA2AError = exports.createA2AResponse = exports.createA2ARequest = exports.generateRequestId = void 0;
|
|
6
|
+
exports.AgentExpert = exports.AbortError = exports.RateLimitError = exports.A2ARateLimiter = exports.cloneAndSanitize = exports.sanitizeArgs = exports.validateSchema = exports.createA2AError = exports.createA2AResponse = exports.createA2ARequest = exports.generateRequestId = void 0;
|
|
7
7
|
// Utilities
|
|
8
8
|
var types_1 = require("./types");
|
|
9
9
|
Object.defineProperty(exports, "generateRequestId", { enumerable: true, get: function () { return types_1.generateRequestId; } });
|
|
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "cloneAndSanitize", { enumerable: true, get: func
|
|
|
19
19
|
var rate_limiter_1 = require("./rate-limiter");
|
|
20
20
|
Object.defineProperty(exports, "A2ARateLimiter", { enumerable: true, get: function () { return rate_limiter_1.A2ARateLimiter; } });
|
|
21
21
|
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return rate_limiter_1.RateLimitError; } });
|
|
22
|
+
Object.defineProperty(exports, "AbortError", { enumerable: true, get: function () { return rate_limiter_1.AbortError; } });
|
|
22
23
|
// AgentExpert
|
|
23
24
|
var expert_1 = require("./expert");
|
|
24
25
|
Object.defineProperty(exports, "AgentExpert", { enumerable: true, get: function () { return expert_1.AgentExpert; } });
|
package/dist/ai/a2a/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai/a2a/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAcH,YAAY;AACZ,iCAKiB;AAJb,0GAAA,iBAAiB,OAAA;AACjB,yGAAA,gBAAgB,OAAA;AAChB,0GAAA,iBAAiB,OAAA;AACjB,uGAAA,cAAc,OAAA;AAGlB,aAAa;AACb,2CAMsB;AALlB,4GAAA,cAAc,OAAA;AACd,0GAAA,YAAY,OAAA;AACZ,8GAAA,gBAAgB,OAAA;AAKpB,eAAe;AACf,+
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai/a2a/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAcH,YAAY;AACZ,iCAKiB;AAJb,0GAAA,iBAAiB,OAAA;AACjB,yGAAA,gBAAgB,OAAA;AAChB,0GAAA,iBAAiB,OAAA;AACjB,uGAAA,cAAc,OAAA;AAGlB,aAAa;AACb,2CAMsB;AALlB,4GAAA,cAAc,OAAA;AACd,0GAAA,YAAY,OAAA;AACZ,8GAAA,gBAAgB,OAAA;AAKpB,eAAe;AACf,+CAA4E;AAAnE,8GAAA,cAAc,OAAA;AAAE,8GAAA,cAAc,OAAA;AAAE,0GAAA,UAAU,OAAA;AAEnD,cAAc;AACd,mCAAuC;AAA9B,qGAAA,WAAW,OAAA"}
|
package/dist/ai/a2a/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ export { generateRequestId, createA2ARequest, createA2AResponse, createA2AError,
|
|
|
6
6
|
// Validation
|
|
7
7
|
export { validateSchema, sanitizeArgs, cloneAndSanitize, } from './validation.mjs';
|
|
8
8
|
// Rate Limiter
|
|
9
|
-
export { A2ARateLimiter, RateLimitError } from './rate-limiter.mjs';
|
|
9
|
+
export { A2ARateLimiter, RateLimitError, AbortError } from './rate-limiter.mjs';
|
|
10
10
|
// AgentExpert
|
|
11
11
|
export { AgentExpert } from './expert.mjs';
|
|
12
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -21,16 +21,14 @@ export declare class A2ARateLimiter {
|
|
|
21
21
|
track(agentId: string, toolName: string): void;
|
|
22
22
|
/**
|
|
23
23
|
* Execute a call with rate limiting.
|
|
24
|
-
*
|
|
25
|
-
* @throws RateLimitError if onLimit is 'reject' and limit exceeded
|
|
26
|
-
* @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
|
|
24
|
+
* Supports AbortSignal for cancellation during wait.
|
|
27
25
|
*/
|
|
28
|
-
execute<T>(agentId: string, toolName: string, execute: () => Promise<T
|
|
26
|
+
execute<T>(agentId: string, toolName: string, execute: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
29
27
|
/**
|
|
30
|
-
* Wait for a slot to become available
|
|
31
|
-
*
|
|
28
|
+
* Wait for a slot to become available.
|
|
29
|
+
* Supports AbortSignal for cancellation.
|
|
32
30
|
*/
|
|
33
|
-
waitForSlot(agentId: string, toolName: string, timeoutMs?: number): Promise<void>;
|
|
31
|
+
waitForSlot(agentId: string, toolName: string, timeoutMs?: number, signal?: AbortSignal): Promise<void>;
|
|
34
32
|
/**
|
|
35
33
|
* Get time until next available slot (ms).
|
|
36
34
|
*/
|
|
@@ -56,4 +54,8 @@ export declare class RateLimitError extends Error {
|
|
|
56
54
|
readonly retryAfterMs: number;
|
|
57
55
|
constructor(agentId: string, toolName: string, retryAfterMs: number);
|
|
58
56
|
}
|
|
57
|
+
export declare class AbortError extends Error {
|
|
58
|
+
readonly code: "CANCELLED";
|
|
59
|
+
constructor(message?: string);
|
|
60
|
+
}
|
|
59
61
|
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAuB/C;;GAEG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,eAAe;IASnC;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQrD;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAM9C;;;OAGG;IACG,OAAO,CAAC,CAAC,EACX,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,CAAC,CAAC;IAuBb;;;OAGG;IACG,WAAW,CACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,IAAI,CAAC;IAyBhB;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAkB3D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiB/C;;OAEG;IACH,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;YAKN,OAAO;YAiCP,YAAY;CAuC7B;AAMD,qBAAa,cAAe,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;CAOtE;AAED,qBAAa,UAAW,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAU;gBAEzB,OAAO,GAAE,MAA0B;CAIlD"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* A2A Rate Limiter - Sliding window rate limiting for agent calls.
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.RateLimitError = exports.A2ARateLimiter = void 0;
|
|
6
|
+
exports.AbortError = exports.RateLimitError = exports.A2ARateLimiter = void 0;
|
|
7
7
|
// ============================================================================
|
|
8
8
|
// Rate Limiter
|
|
9
9
|
// ============================================================================
|
|
@@ -42,11 +42,13 @@ class A2ARateLimiter {
|
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Execute a call with rate limiting.
|
|
45
|
-
*
|
|
46
|
-
* @throws RateLimitError if onLimit is 'reject' and limit exceeded
|
|
47
|
-
* @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
|
|
45
|
+
* Supports AbortSignal for cancellation during wait.
|
|
48
46
|
*/
|
|
49
|
-
async execute(agentId, toolName, execute) {
|
|
47
|
+
async execute(agentId, toolName, execute, signal) {
|
|
48
|
+
// Check if already aborted
|
|
49
|
+
if (signal?.aborted) {
|
|
50
|
+
throw new AbortError('Request aborted');
|
|
51
|
+
}
|
|
50
52
|
if (this.isAllowed(agentId, toolName)) {
|
|
51
53
|
this.track(agentId, toolName);
|
|
52
54
|
return execute();
|
|
@@ -54,18 +56,24 @@ class A2ARateLimiter {
|
|
|
54
56
|
if (this.config.onLimit === 'reject') {
|
|
55
57
|
throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
|
|
56
58
|
}
|
|
57
|
-
// Queue mode
|
|
58
|
-
return this.enqueue(agentId, toolName, execute);
|
|
59
|
+
// Queue mode: wait for slot with abort support
|
|
60
|
+
return this.enqueue(agentId, toolName, execute, signal);
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
61
|
-
* Wait for a slot to become available
|
|
62
|
-
*
|
|
63
|
+
* Wait for a slot to become available.
|
|
64
|
+
* Supports AbortSignal for cancellation.
|
|
63
65
|
*/
|
|
64
|
-
async waitForSlot(agentId, toolName, timeoutMs) {
|
|
66
|
+
async waitForSlot(agentId, toolName, timeoutMs, signal) {
|
|
67
|
+
if (signal?.aborted) {
|
|
68
|
+
throw new AbortError('Request aborted');
|
|
69
|
+
}
|
|
65
70
|
const timeout = timeoutMs ?? this.config.windowMs * 2;
|
|
66
71
|
const checkInterval = 50;
|
|
67
72
|
let waited = 0;
|
|
68
73
|
while (waited < timeout) {
|
|
74
|
+
if (signal?.aborted) {
|
|
75
|
+
throw new AbortError('Request aborted during rate limit wait');
|
|
76
|
+
}
|
|
69
77
|
if (this.isAllowed(agentId, toolName)) {
|
|
70
78
|
return;
|
|
71
79
|
}
|
|
@@ -139,15 +147,28 @@ class A2ARateLimiter {
|
|
|
139
147
|
const cutoff = now - this.config.windowMs;
|
|
140
148
|
entry.timestamps = entry.timestamps.filter(t => t > cutoff);
|
|
141
149
|
}
|
|
142
|
-
async enqueue(agentId, toolName, execute) {
|
|
150
|
+
async enqueue(agentId, toolName, execute, signal) {
|
|
143
151
|
return new Promise((resolve, reject) => {
|
|
144
|
-
|
|
152
|
+
const call = {
|
|
145
153
|
agentId,
|
|
146
154
|
toolName,
|
|
155
|
+
signal,
|
|
147
156
|
execute: execute,
|
|
148
157
|
resolve: resolve,
|
|
149
158
|
reject,
|
|
150
|
-
}
|
|
159
|
+
};
|
|
160
|
+
// Handle abort while in queue
|
|
161
|
+
if (signal) {
|
|
162
|
+
const abortHandler = () => {
|
|
163
|
+
const index = this.queue.indexOf(call);
|
|
164
|
+
if (index !== -1) {
|
|
165
|
+
this.queue.splice(index, 1);
|
|
166
|
+
reject(new AbortError('Request aborted while queued'));
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
signal.addEventListener('abort', abortHandler, { once: true });
|
|
170
|
+
}
|
|
171
|
+
this.queue.push(call);
|
|
151
172
|
this.processQueue();
|
|
152
173
|
});
|
|
153
174
|
}
|
|
@@ -158,9 +179,20 @@ class A2ARateLimiter {
|
|
|
158
179
|
this.processing = true;
|
|
159
180
|
while (this.queue.length > 0) {
|
|
160
181
|
const call = this.queue[0];
|
|
182
|
+
// Check if aborted before processing
|
|
183
|
+
if (call.signal?.aborted) {
|
|
184
|
+
this.queue.shift();
|
|
185
|
+
call.reject(new AbortError('Request aborted'));
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
161
188
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
189
|
+
await this.waitForSlot(call.agentId, call.toolName, undefined, call.signal);
|
|
190
|
+
// Check again after wait
|
|
191
|
+
if (call.signal?.aborted) {
|
|
192
|
+
this.queue.shift();
|
|
193
|
+
call.reject(new AbortError('Request aborted after wait'));
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
164
196
|
this.track(call.agentId, call.toolName);
|
|
165
197
|
this.queue.shift();
|
|
166
198
|
const result = await call.execute();
|
|
@@ -189,4 +221,12 @@ class RateLimitError extends Error {
|
|
|
189
221
|
}
|
|
190
222
|
}
|
|
191
223
|
exports.RateLimitError = RateLimitError;
|
|
224
|
+
class AbortError extends Error {
|
|
225
|
+
constructor(message = 'Request aborted') {
|
|
226
|
+
super(message);
|
|
227
|
+
this.code = 'CANCELLED';
|
|
228
|
+
this.name = 'AbortError';
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.AbortError = AbortError;
|
|
192
232
|
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":";AAAA;;GAEG;;;
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,11 +39,13 @@ export class A2ARateLimiter {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Execute a call with rate limiting.
|
|
42
|
-
*
|
|
43
|
-
* @throws RateLimitError if onLimit is 'reject' and limit exceeded
|
|
44
|
-
* @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
|
|
42
|
+
* Supports AbortSignal for cancellation during wait.
|
|
45
43
|
*/
|
|
46
|
-
async execute(agentId, toolName, execute) {
|
|
44
|
+
async execute(agentId, toolName, execute, signal) {
|
|
45
|
+
// Check if already aborted
|
|
46
|
+
if (signal?.aborted) {
|
|
47
|
+
throw new AbortError('Request aborted');
|
|
48
|
+
}
|
|
47
49
|
if (this.isAllowed(agentId, toolName)) {
|
|
48
50
|
this.track(agentId, toolName);
|
|
49
51
|
return execute();
|
|
@@ -51,18 +53,24 @@ export class A2ARateLimiter {
|
|
|
51
53
|
if (this.config.onLimit === 'reject') {
|
|
52
54
|
throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
|
|
53
55
|
}
|
|
54
|
-
// Queue mode
|
|
55
|
-
return this.enqueue(agentId, toolName, execute);
|
|
56
|
+
// Queue mode: wait for slot with abort support
|
|
57
|
+
return this.enqueue(agentId, toolName, execute, signal);
|
|
56
58
|
}
|
|
57
59
|
/**
|
|
58
|
-
* Wait for a slot to become available
|
|
59
|
-
*
|
|
60
|
+
* Wait for a slot to become available.
|
|
61
|
+
* Supports AbortSignal for cancellation.
|
|
60
62
|
*/
|
|
61
|
-
async waitForSlot(agentId, toolName, timeoutMs) {
|
|
63
|
+
async waitForSlot(agentId, toolName, timeoutMs, signal) {
|
|
64
|
+
if (signal?.aborted) {
|
|
65
|
+
throw new AbortError('Request aborted');
|
|
66
|
+
}
|
|
62
67
|
const timeout = timeoutMs ?? this.config.windowMs * 2;
|
|
63
68
|
const checkInterval = 50;
|
|
64
69
|
let waited = 0;
|
|
65
70
|
while (waited < timeout) {
|
|
71
|
+
if (signal?.aborted) {
|
|
72
|
+
throw new AbortError('Request aborted during rate limit wait');
|
|
73
|
+
}
|
|
66
74
|
if (this.isAllowed(agentId, toolName)) {
|
|
67
75
|
return;
|
|
68
76
|
}
|
|
@@ -136,15 +144,28 @@ export class A2ARateLimiter {
|
|
|
136
144
|
const cutoff = now - this.config.windowMs;
|
|
137
145
|
entry.timestamps = entry.timestamps.filter(t => t > cutoff);
|
|
138
146
|
}
|
|
139
|
-
async enqueue(agentId, toolName, execute) {
|
|
147
|
+
async enqueue(agentId, toolName, execute, signal) {
|
|
140
148
|
return new Promise((resolve, reject) => {
|
|
141
|
-
|
|
149
|
+
const call = {
|
|
142
150
|
agentId,
|
|
143
151
|
toolName,
|
|
152
|
+
signal,
|
|
144
153
|
execute: execute,
|
|
145
154
|
resolve: resolve,
|
|
146
155
|
reject,
|
|
147
|
-
}
|
|
156
|
+
};
|
|
157
|
+
// Handle abort while in queue
|
|
158
|
+
if (signal) {
|
|
159
|
+
const abortHandler = () => {
|
|
160
|
+
const index = this.queue.indexOf(call);
|
|
161
|
+
if (index !== -1) {
|
|
162
|
+
this.queue.splice(index, 1);
|
|
163
|
+
reject(new AbortError('Request aborted while queued'));
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
signal.addEventListener('abort', abortHandler, { once: true });
|
|
167
|
+
}
|
|
168
|
+
this.queue.push(call);
|
|
148
169
|
this.processQueue();
|
|
149
170
|
});
|
|
150
171
|
}
|
|
@@ -155,9 +176,20 @@ export class A2ARateLimiter {
|
|
|
155
176
|
this.processing = true;
|
|
156
177
|
while (this.queue.length > 0) {
|
|
157
178
|
const call = this.queue[0];
|
|
179
|
+
// Check if aborted before processing
|
|
180
|
+
if (call.signal?.aborted) {
|
|
181
|
+
this.queue.shift();
|
|
182
|
+
call.reject(new AbortError('Request aborted'));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
158
185
|
try {
|
|
159
|
-
|
|
160
|
-
|
|
186
|
+
await this.waitForSlot(call.agentId, call.toolName, undefined, call.signal);
|
|
187
|
+
// Check again after wait
|
|
188
|
+
if (call.signal?.aborted) {
|
|
189
|
+
this.queue.shift();
|
|
190
|
+
call.reject(new AbortError('Request aborted after wait'));
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
161
193
|
this.track(call.agentId, call.toolName);
|
|
162
194
|
this.queue.shift();
|
|
163
195
|
const result = await call.execute();
|
|
@@ -184,4 +216,11 @@ export class RateLimitError extends Error {
|
|
|
184
216
|
this.retryAfterMs = retryAfterMs;
|
|
185
217
|
}
|
|
186
218
|
}
|
|
219
|
+
export class AbortError extends Error {
|
|
220
|
+
constructor(message = 'Request aborted') {
|
|
221
|
+
super(message);
|
|
222
|
+
this.code = 'CANCELLED';
|
|
223
|
+
this.name = 'AbortError';
|
|
224
|
+
}
|
|
225
|
+
}
|
|
187
226
|
//# sourceMappingURL=rate-limiter.js.map
|
package/package.json
CHANGED