@bowenqt/qiniu-ai-sdk 0.28.1 → 0.28.2

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.
@@ -23,6 +23,7 @@ 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.
26
27
  */
27
28
  callTool(request: CallToolRequest): Promise<A2AMessage>;
28
29
  /**
@@ -33,6 +34,5 @@ export declare class AgentExpert {
33
34
  * Get list of exposed tool names (without prefix).
34
35
  */
35
36
  getExposedToolNames(): string[];
36
- private waitForRateLimitSlot;
37
37
  }
38
38
  //# sourceMappingURL=expert.d.ts.map
@@ -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;AAcjB;;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;IAsBP;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,WAAW;IAmCjE;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAsF7D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAkB9D;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;YAQjB,oBAAoB;CAgBrC"}
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;AAcjB;;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;IAkCjE;;;OAGG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IA0E7D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAgB9D;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;CAGlC"}
@@ -14,7 +14,7 @@ const rate_limiter_1 = require("./rate-limiter");
14
14
  * Wraps an Agent to expose selected tools for A2A collaboration.
15
15
  */
16
16
  class AgentExpert {
17
- constructor(agent, config, tools, originalTools) {
17
+ constructor(agent, config, tools, originalTools, rateLimiter) {
18
18
  this.agent = agent;
19
19
  this.id = agent.id;
20
20
  this.config = {
@@ -25,25 +25,21 @@ class AgentExpert {
25
25
  };
26
26
  this.tools = tools;
27
27
  this.originalTools = originalTools;
28
- if (config.rateLimit) {
29
- this.rateLimiter = new rate_limiter_1.A2ARateLimiter(config.rateLimit);
30
- }
28
+ this.rateLimiter = rateLimiter;
31
29
  }
32
30
  /**
33
31
  * Create an AgentExpert from an Agent.
34
32
  */
35
33
  static from(agent, config) {
36
- // Get original tools
37
34
  const originalTools = agent._tools;
38
- // Build exposed tools with prefix
39
- const exposedTools = {};
40
35
  const prefix = config.prefix ?? `${agent.id}_`;
41
36
  const expertId = agent.id;
42
- const rateLimit = config.rateLimit;
43
- let rateLimiter;
44
- if (rateLimit) {
45
- rateLimiter = new rate_limiter_1.A2ARateLimiter(rateLimit);
46
- }
37
+ // Single shared rate limiter instance
38
+ const rateLimiter = config.rateLimit
39
+ ? new rate_limiter_1.A2ARateLimiter(config.rateLimit)
40
+ : undefined;
41
+ // Build exposed tools
42
+ const exposedTools = {};
47
43
  for (const toolName of config.expose) {
48
44
  const tool = originalTools[toolName];
49
45
  if (!tool) {
@@ -51,17 +47,18 @@ class AgentExpert {
51
47
  continue;
52
48
  }
53
49
  const prefixedName = `${prefix}${toolName}`;
54
- exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true);
50
+ exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true, config.rateLimit?.onLimit ?? 'reject');
55
51
  }
56
- return new AgentExpert(agent, config, exposedTools, originalTools);
52
+ return new AgentExpert(agent, config, exposedTools, originalTools, rateLimiter);
57
53
  }
58
54
  /**
59
55
  * Direct tool call with full request.
56
+ * Note: `from` field is ignored for rate limiting - expert.id is always used.
60
57
  */
61
58
  async callTool(request) {
62
59
  const requestId = request.requestId ?? (0, types_1.generateRequestId)();
63
60
  const { from = '', tool, args, signal } = request;
64
- // Create base request for error responses
61
+ // Create base request for responses
65
62
  const baseRequest = {
66
63
  requestId,
67
64
  type: 'request',
@@ -84,18 +81,10 @@ class AgentExpert {
84
81
  if (signal?.aborted) {
85
82
  return (0, types_1.createA2AError)(baseRequest, 'CANCELLED', 'Request was cancelled');
86
83
  }
87
- // Rate limiting
84
+ // Rate limiting (use expert.id, not caller-provided from)
88
85
  if (this.rateLimiter) {
89
86
  try {
90
- const allowed = this.rateLimiter.isAllowed(from || this.id, tool);
91
- if (!allowed) {
92
- if (this.config.rateLimit?.onLimit === 'reject') {
93
- throw new rate_limiter_1.RateLimitError(from || this.id, tool, this.rateLimiter.getTimeUntilSlot(from || this.id, tool));
94
- }
95
- // Queue mode - wait for slot
96
- await this.waitForRateLimitSlot(from || this.id, tool);
97
- }
98
- this.rateLimiter.track(from || this.id, tool);
87
+ await this.rateLimiter.execute(this.id, tool, async () => { });
99
88
  }
100
89
  catch (error) {
101
90
  if (error instanceof rate_limiter_1.RateLimitError) {
@@ -133,11 +122,9 @@ class AgentExpert {
133
122
  async runTask(request) {
134
123
  const requestId = request.requestId ?? (0, types_1.generateRequestId)();
135
124
  const { prompt, signal } = request;
136
- // Check abort
137
125
  if (signal?.aborted) {
138
126
  throw new Error('Request was cancelled');
139
127
  }
140
- // Run the agent
141
128
  const result = await this.agent.run({ prompt });
142
129
  return {
143
130
  output: result.text ?? '',
@@ -150,22 +137,6 @@ class AgentExpert {
150
137
  getExposedToolNames() {
151
138
  return [...this.config.expose];
152
139
  }
153
- // ========================================================================
154
- // Private Methods
155
- // ========================================================================
156
- async waitForRateLimitSlot(callerId, tool) {
157
- const maxWait = this.config.rateLimit?.windowMs ?? 60000;
158
- const checkInterval = 50;
159
- let waited = 0;
160
- while (waited < maxWait) {
161
- await new Promise(resolve => setTimeout(resolve, checkInterval));
162
- waited += checkInterval;
163
- if (this.rateLimiter?.isAllowed(callerId, tool)) {
164
- return;
165
- }
166
- }
167
- throw new rate_limiter_1.RateLimitError(callerId, tool, 0);
168
- }
169
140
  }
170
141
  exports.AgentExpert = AgentExpert;
171
142
  // ============================================================================
@@ -174,24 +145,30 @@ exports.AgentExpert = AgentExpert;
174
145
  /**
175
146
  * Create a wrapped tool preserving all metadata.
176
147
  */
177
- function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs) {
148
+ function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs, onLimit) {
178
149
  return {
179
- // Preserve all metadata
180
150
  description: original.description,
181
151
  parameters: original.parameters,
182
152
  requiresApproval: original.requiresApproval,
183
153
  approvalHandler: original.approvalHandler,
184
154
  source: original.source,
185
155
  execute: async (args, context) => {
186
- // Rate limiting for exposed tools path
156
+ // Rate limiting with proper queue support
187
157
  if (rateLimiter) {
188
- const callerId = expertId; // Use expert ID as caller for exposed tools
189
- if (!rateLimiter.isAllowed(callerId, toolName)) {
190
- throw new rate_limiter_1.RateLimitError(callerId, toolName, rateLimiter.getTimeUntilSlot(callerId, toolName));
158
+ if (onLimit === 'queue') {
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);
191
169
  }
192
- rateLimiter.track(callerId, toolName);
193
170
  }
194
- // Validate if enabled
171
+ // Validate
195
172
  if (validateArgs && original.parameters) {
196
173
  const result = (0, validation_1.validateSchema)(args, original.parameters);
197
174
  if (!result.valid) {
@@ -1 +1 @@
1
- {"version":3,"file":"expert.js","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"expert.js","sourceRoot":"","sources":["../../../src/ai/a2a/expert.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ import { A2ARateLimiter, RateLimitError } from './rate-limiter.mjs';
11
11
  * Wraps an Agent to expose selected tools for A2A collaboration.
12
12
  */
13
13
  export class AgentExpert {
14
- constructor(agent, config, tools, originalTools) {
14
+ constructor(agent, config, tools, originalTools, rateLimiter) {
15
15
  this.agent = agent;
16
16
  this.id = agent.id;
17
17
  this.config = {
@@ -22,25 +22,21 @@ export class AgentExpert {
22
22
  };
23
23
  this.tools = tools;
24
24
  this.originalTools = originalTools;
25
- if (config.rateLimit) {
26
- this.rateLimiter = new A2ARateLimiter(config.rateLimit);
27
- }
25
+ this.rateLimiter = rateLimiter;
28
26
  }
29
27
  /**
30
28
  * Create an AgentExpert from an Agent.
31
29
  */
32
30
  static from(agent, config) {
33
- // Get original tools
34
31
  const originalTools = agent._tools;
35
- // Build exposed tools with prefix
36
- const exposedTools = {};
37
32
  const prefix = config.prefix ?? `${agent.id}_`;
38
33
  const expertId = agent.id;
39
- const rateLimit = config.rateLimit;
40
- let rateLimiter;
41
- if (rateLimit) {
42
- rateLimiter = new A2ARateLimiter(rateLimit);
43
- }
34
+ // Single shared rate limiter instance
35
+ const rateLimiter = config.rateLimit
36
+ ? new A2ARateLimiter(config.rateLimit)
37
+ : undefined;
38
+ // Build exposed tools
39
+ const exposedTools = {};
44
40
  for (const toolName of config.expose) {
45
41
  const tool = originalTools[toolName];
46
42
  if (!tool) {
@@ -48,17 +44,18 @@ export class AgentExpert {
48
44
  continue;
49
45
  }
50
46
  const prefixedName = `${prefix}${toolName}`;
51
- exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true);
47
+ exposedTools[prefixedName] = createWrappedTool(tool, toolName, expertId, rateLimiter, config.validateArgs ?? true, config.rateLimit?.onLimit ?? 'reject');
52
48
  }
53
- return new AgentExpert(agent, config, exposedTools, originalTools);
49
+ return new AgentExpert(agent, config, exposedTools, originalTools, rateLimiter);
54
50
  }
55
51
  /**
56
52
  * Direct tool call with full request.
53
+ * Note: `from` field is ignored for rate limiting - expert.id is always used.
57
54
  */
58
55
  async callTool(request) {
59
56
  const requestId = request.requestId ?? generateRequestId();
60
57
  const { from = '', tool, args, signal } = request;
61
- // Create base request for error responses
58
+ // Create base request for responses
62
59
  const baseRequest = {
63
60
  requestId,
64
61
  type: 'request',
@@ -81,18 +78,10 @@ export class AgentExpert {
81
78
  if (signal?.aborted) {
82
79
  return createA2AError(baseRequest, 'CANCELLED', 'Request was cancelled');
83
80
  }
84
- // Rate limiting
81
+ // Rate limiting (use expert.id, not caller-provided from)
85
82
  if (this.rateLimiter) {
86
83
  try {
87
- const allowed = this.rateLimiter.isAllowed(from || this.id, tool);
88
- if (!allowed) {
89
- if (this.config.rateLimit?.onLimit === 'reject') {
90
- throw new RateLimitError(from || this.id, tool, this.rateLimiter.getTimeUntilSlot(from || this.id, tool));
91
- }
92
- // Queue mode - wait for slot
93
- await this.waitForRateLimitSlot(from || this.id, tool);
94
- }
95
- this.rateLimiter.track(from || this.id, tool);
84
+ await this.rateLimiter.execute(this.id, tool, async () => { });
96
85
  }
97
86
  catch (error) {
98
87
  if (error instanceof RateLimitError) {
@@ -130,11 +119,9 @@ export class AgentExpert {
130
119
  async runTask(request) {
131
120
  const requestId = request.requestId ?? generateRequestId();
132
121
  const { prompt, signal } = request;
133
- // Check abort
134
122
  if (signal?.aborted) {
135
123
  throw new Error('Request was cancelled');
136
124
  }
137
- // Run the agent
138
125
  const result = await this.agent.run({ prompt });
139
126
  return {
140
127
  output: result.text ?? '',
@@ -147,22 +134,6 @@ export class AgentExpert {
147
134
  getExposedToolNames() {
148
135
  return [...this.config.expose];
149
136
  }
150
- // ========================================================================
151
- // Private Methods
152
- // ========================================================================
153
- async waitForRateLimitSlot(callerId, tool) {
154
- const maxWait = this.config.rateLimit?.windowMs ?? 60000;
155
- const checkInterval = 50;
156
- let waited = 0;
157
- while (waited < maxWait) {
158
- await new Promise(resolve => setTimeout(resolve, checkInterval));
159
- waited += checkInterval;
160
- if (this.rateLimiter?.isAllowed(callerId, tool)) {
161
- return;
162
- }
163
- }
164
- throw new RateLimitError(callerId, tool, 0);
165
- }
166
137
  }
167
138
  // ============================================================================
168
139
  // Helper Functions
@@ -170,24 +141,30 @@ export class AgentExpert {
170
141
  /**
171
142
  * Create a wrapped tool preserving all metadata.
172
143
  */
173
- function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs) {
144
+ function createWrappedTool(original, toolName, expertId, rateLimiter, validateArgs, onLimit) {
174
145
  return {
175
- // Preserve all metadata
176
146
  description: original.description,
177
147
  parameters: original.parameters,
178
148
  requiresApproval: original.requiresApproval,
179
149
  approvalHandler: original.approvalHandler,
180
150
  source: original.source,
181
151
  execute: async (args, context) => {
182
- // Rate limiting for exposed tools path
152
+ // Rate limiting with proper queue support
183
153
  if (rateLimiter) {
184
- const callerId = expertId; // Use expert ID as caller for exposed tools
185
- if (!rateLimiter.isAllowed(callerId, toolName)) {
186
- throw new RateLimitError(callerId, toolName, rateLimiter.getTimeUntilSlot(callerId, toolName));
154
+ if (onLimit === 'queue') {
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);
187
165
  }
188
- rateLimiter.track(callerId, toolName);
189
166
  }
190
- // Validate if enabled
167
+ // Validate
191
168
  if (validateArgs && original.parameters) {
192
169
  const result = validateSchema(args, original.parameters);
193
170
  if (!result.valid) {
@@ -13,26 +13,24 @@ export declare class A2ARateLimiter {
13
13
  constructor(config: RateLimitConfig);
14
14
  /**
15
15
  * Check if a call is allowed.
16
- *
17
- * @param agentId - The agent making the call
18
- * @param toolName - The tool being called (used if scope is 'tool')
19
- * @returns Whether the call is allowed
20
16
  */
21
17
  isAllowed(agentId: string, toolName: string): boolean;
22
18
  /**
23
- * Track a call (should be called after isAllowed returns true).
19
+ * Track a call.
24
20
  */
25
21
  track(agentId: string, toolName: string): void;
26
22
  /**
27
23
  * Execute a call with rate limiting.
28
24
  *
29
- * @param agentId - The agent making the call
30
- * @param toolName - The tool being called
31
- * @param execute - The function to execute
32
- * @returns Result of execution
33
- * @throws Error if rate limited and onLimit is 'reject'
25
+ * @throws RateLimitError if onLimit is 'reject' and limit exceeded
26
+ * @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
34
27
  */
35
28
  execute<T>(agentId: string, toolName: string, execute: () => Promise<T>): Promise<T>;
29
+ /**
30
+ * Wait for a slot to become available (for external use).
31
+ * Throws if timeout exceeded.
32
+ */
33
+ waitForSlot(agentId: string, toolName: string, timeoutMs?: number): Promise<void>;
36
34
  /**
37
35
  * Get time until next available slot (ms).
38
36
  */
@@ -50,7 +48,6 @@ export declare class A2ARateLimiter {
50
48
  private pruneExpired;
51
49
  private enqueue;
52
50
  private processQueue;
53
- private waitForSlot;
54
51
  }
55
52
  export declare class RateLimitError extends Error {
56
53
  readonly code: "RATE_LIMITED";
@@ -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;AAsB/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;;;;;;OAMG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAWrD;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAM9C;;;;;;;;OAQG;IACG,OAAO,CAAC,CAAC,EACX,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC;IAkBb;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAmB3D;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAoB/C;;OAEG;IACH,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;YAKN,OAAO;YAiBP,YAAY;YA6BZ,WAAW;CAgB5B;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"}
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;AAsB/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;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EACX,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC;IAkBb;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvF;;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;YAiBP,YAAY;CAyB7B;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"}
@@ -24,21 +24,16 @@ class A2ARateLimiter {
24
24
  }
25
25
  /**
26
26
  * Check if a call is allowed.
27
- *
28
- * @param agentId - The agent making the call
29
- * @param toolName - The tool being called (used if scope is 'tool')
30
- * @returns Whether the call is allowed
31
27
  */
32
28
  isAllowed(agentId, toolName) {
33
29
  const key = this.getKey(agentId, toolName);
34
30
  const now = Date.now();
35
31
  const entry = this.getOrCreateEntry(key);
36
- // Remove expired timestamps
37
32
  this.pruneExpired(entry, now);
38
33
  return entry.timestamps.length < this.config.maxCalls;
39
34
  }
40
35
  /**
41
- * Track a call (should be called after isAllowed returns true).
36
+ * Track a call.
42
37
  */
43
38
  track(agentId, toolName) {
44
39
  const key = this.getKey(agentId, toolName);
@@ -48,11 +43,8 @@ class A2ARateLimiter {
48
43
  /**
49
44
  * Execute a call with rate limiting.
50
45
  *
51
- * @param agentId - The agent making the call
52
- * @param toolName - The tool being called
53
- * @param execute - The function to execute
54
- * @returns Result of execution
55
- * @throws Error if rate limited and onLimit is 'reject'
46
+ * @throws RateLimitError if onLimit is 'reject' and limit exceeded
47
+ * @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
56
48
  */
57
49
  async execute(agentId, toolName, execute) {
58
50
  if (this.isAllowed(agentId, toolName)) {
@@ -62,9 +54,26 @@ class A2ARateLimiter {
62
54
  if (this.config.onLimit === 'reject') {
63
55
  throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
64
56
  }
65
- // Queue the call with context
57
+ // Queue mode (strict): wait for slot or throw
66
58
  return this.enqueue(agentId, toolName, execute);
67
59
  }
60
+ /**
61
+ * Wait for a slot to become available (for external use).
62
+ * Throws if timeout exceeded.
63
+ */
64
+ async waitForSlot(agentId, toolName, timeoutMs) {
65
+ const timeout = timeoutMs ?? this.config.windowMs * 2;
66
+ const checkInterval = 50;
67
+ let waited = 0;
68
+ while (waited < timeout) {
69
+ if (this.isAllowed(agentId, toolName)) {
70
+ return;
71
+ }
72
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
73
+ waited += checkInterval;
74
+ }
75
+ throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
76
+ }
68
77
  /**
69
78
  * Get time until next available slot (ms).
70
79
  */
@@ -79,7 +88,6 @@ class A2ARateLimiter {
79
88
  if (entry.timestamps.length < this.config.maxCalls) {
80
89
  return 0;
81
90
  }
82
- // Time until oldest timestamp expires
83
91
  const oldest = entry.timestamps[0];
84
92
  return Math.max(0, oldest + this.config.windowMs - now);
85
93
  }
@@ -89,11 +97,9 @@ class A2ARateLimiter {
89
97
  reset(agentId, toolName) {
90
98
  if (this.config.scope === 'tool') {
91
99
  if (toolName) {
92
- // Reset specific tool
93
100
  this.entries.delete(this.getKey(agentId, toolName));
94
101
  }
95
102
  else {
96
- // Reset all tools for this agent
97
103
  const prefix = `${agentId}:`;
98
104
  for (const key of [...this.entries.keys()]) {
99
105
  if (key.startsWith(prefix)) {
@@ -103,7 +109,6 @@ class A2ARateLimiter {
103
109
  }
104
110
  }
105
111
  else {
106
- // scope === 'agent': key is just agentId
107
112
  this.entries.delete(agentId);
108
113
  }
109
114
  }
@@ -115,7 +120,7 @@ class A2ARateLimiter {
115
120
  this.queue = [];
116
121
  }
117
122
  // ========================================================================
118
- // Private Methods
123
+ // Private
119
124
  // ========================================================================
120
125
  getKey(agentId, toolName) {
121
126
  return this.config.scope === 'tool'
@@ -153,35 +158,21 @@ class A2ARateLimiter {
153
158
  this.processing = true;
154
159
  while (this.queue.length > 0) {
155
160
  const call = this.queue[0];
156
- // Wait until slot is available for this specific call
157
- await this.waitForSlot(call.agentId, call.toolName);
158
- // Track before execution (count it)
159
- this.track(call.agentId, call.toolName);
160
- this.queue.shift();
161
161
  try {
162
+ // Strict wait - throws on timeout
163
+ await this.waitForSlot(call.agentId, call.toolName);
164
+ this.track(call.agentId, call.toolName);
165
+ this.queue.shift();
162
166
  const result = await call.execute();
163
167
  call.resolve(result);
164
168
  }
165
169
  catch (error) {
170
+ this.queue.shift();
166
171
  call.reject(error);
167
172
  }
168
173
  }
169
174
  this.processing = false;
170
175
  }
171
- async waitForSlot(agentId, toolName) {
172
- const checkInterval = 50;
173
- const maxWait = this.config.windowMs * 2;
174
- let waited = 0;
175
- while (waited < maxWait) {
176
- if (this.isAllowed(agentId, toolName)) {
177
- return;
178
- }
179
- await new Promise(resolve => setTimeout(resolve, checkInterval));
180
- waited += checkInterval;
181
- }
182
- // Timeout - still execute but may exceed limit
183
- console.warn(`[A2ARateLimiter] Queue timeout for ${agentId}:${toolName}`);
184
- }
185
176
  }
186
177
  exports.A2ARateLimiter = A2ARateLimiter;
187
178
  // ============================================================================
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/ai/a2a/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -21,21 +21,16 @@ export class A2ARateLimiter {
21
21
  }
22
22
  /**
23
23
  * Check if a call is allowed.
24
- *
25
- * @param agentId - The agent making the call
26
- * @param toolName - The tool being called (used if scope is 'tool')
27
- * @returns Whether the call is allowed
28
24
  */
29
25
  isAllowed(agentId, toolName) {
30
26
  const key = this.getKey(agentId, toolName);
31
27
  const now = Date.now();
32
28
  const entry = this.getOrCreateEntry(key);
33
- // Remove expired timestamps
34
29
  this.pruneExpired(entry, now);
35
30
  return entry.timestamps.length < this.config.maxCalls;
36
31
  }
37
32
  /**
38
- * Track a call (should be called after isAllowed returns true).
33
+ * Track a call.
39
34
  */
40
35
  track(agentId, toolName) {
41
36
  const key = this.getKey(agentId, toolName);
@@ -45,11 +40,8 @@ export class A2ARateLimiter {
45
40
  /**
46
41
  * Execute a call with rate limiting.
47
42
  *
48
- * @param agentId - The agent making the call
49
- * @param toolName - The tool being called
50
- * @param execute - The function to execute
51
- * @returns Result of execution
52
- * @throws Error if rate limited and onLimit is 'reject'
43
+ * @throws RateLimitError if onLimit is 'reject' and limit exceeded
44
+ * @throws RateLimitError if onLimit is 'queue' and wait times out (strict mode)
53
45
  */
54
46
  async execute(agentId, toolName, execute) {
55
47
  if (this.isAllowed(agentId, toolName)) {
@@ -59,9 +51,26 @@ export class A2ARateLimiter {
59
51
  if (this.config.onLimit === 'reject') {
60
52
  throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
61
53
  }
62
- // Queue the call with context
54
+ // Queue mode (strict): wait for slot or throw
63
55
  return this.enqueue(agentId, toolName, execute);
64
56
  }
57
+ /**
58
+ * Wait for a slot to become available (for external use).
59
+ * Throws if timeout exceeded.
60
+ */
61
+ async waitForSlot(agentId, toolName, timeoutMs) {
62
+ const timeout = timeoutMs ?? this.config.windowMs * 2;
63
+ const checkInterval = 50;
64
+ let waited = 0;
65
+ while (waited < timeout) {
66
+ if (this.isAllowed(agentId, toolName)) {
67
+ return;
68
+ }
69
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
70
+ waited += checkInterval;
71
+ }
72
+ throw new RateLimitError(agentId, toolName, this.getTimeUntilSlot(agentId, toolName));
73
+ }
65
74
  /**
66
75
  * Get time until next available slot (ms).
67
76
  */
@@ -76,7 +85,6 @@ export class A2ARateLimiter {
76
85
  if (entry.timestamps.length < this.config.maxCalls) {
77
86
  return 0;
78
87
  }
79
- // Time until oldest timestamp expires
80
88
  const oldest = entry.timestamps[0];
81
89
  return Math.max(0, oldest + this.config.windowMs - now);
82
90
  }
@@ -86,11 +94,9 @@ export class A2ARateLimiter {
86
94
  reset(agentId, toolName) {
87
95
  if (this.config.scope === 'tool') {
88
96
  if (toolName) {
89
- // Reset specific tool
90
97
  this.entries.delete(this.getKey(agentId, toolName));
91
98
  }
92
99
  else {
93
- // Reset all tools for this agent
94
100
  const prefix = `${agentId}:`;
95
101
  for (const key of [...this.entries.keys()]) {
96
102
  if (key.startsWith(prefix)) {
@@ -100,7 +106,6 @@ export class A2ARateLimiter {
100
106
  }
101
107
  }
102
108
  else {
103
- // scope === 'agent': key is just agentId
104
109
  this.entries.delete(agentId);
105
110
  }
106
111
  }
@@ -112,7 +117,7 @@ export class A2ARateLimiter {
112
117
  this.queue = [];
113
118
  }
114
119
  // ========================================================================
115
- // Private Methods
120
+ // Private
116
121
  // ========================================================================
117
122
  getKey(agentId, toolName) {
118
123
  return this.config.scope === 'tool'
@@ -150,35 +155,21 @@ export class A2ARateLimiter {
150
155
  this.processing = true;
151
156
  while (this.queue.length > 0) {
152
157
  const call = this.queue[0];
153
- // Wait until slot is available for this specific call
154
- await this.waitForSlot(call.agentId, call.toolName);
155
- // Track before execution (count it)
156
- this.track(call.agentId, call.toolName);
157
- this.queue.shift();
158
158
  try {
159
+ // Strict wait - throws on timeout
160
+ await this.waitForSlot(call.agentId, call.toolName);
161
+ this.track(call.agentId, call.toolName);
162
+ this.queue.shift();
159
163
  const result = await call.execute();
160
164
  call.resolve(result);
161
165
  }
162
166
  catch (error) {
167
+ this.queue.shift();
163
168
  call.reject(error);
164
169
  }
165
170
  }
166
171
  this.processing = false;
167
172
  }
168
- async waitForSlot(agentId, toolName) {
169
- const checkInterval = 50;
170
- const maxWait = this.config.windowMs * 2;
171
- let waited = 0;
172
- while (waited < maxWait) {
173
- if (this.isAllowed(agentId, toolName)) {
174
- return;
175
- }
176
- await new Promise(resolve => setTimeout(resolve, checkInterval));
177
- waited += checkInterval;
178
- }
179
- // Timeout - still execute but may exceed limit
180
- console.warn(`[A2ARateLimiter] Queue timeout for ${agentId}:${toolName}`);
181
- }
182
173
  }
183
174
  // ============================================================================
184
175
  // Errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bowenqt/qiniu-ai-sdk",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "TypeScript SDK for Qiniu Cloud AI Token API - Chat, Image, Video generation and more",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",