@elisym/cli 0.17.1 → 0.17.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.
- package/dist/index.js +38 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2035,8 +2035,10 @@ function resolveHealthPair(skill) {
|
|
|
2035
2035
|
return null;
|
|
2036
2036
|
}
|
|
2037
2037
|
var RATE_LIMIT_WINDOW_MS = 10 * 60 * 1e3;
|
|
2038
|
-
var
|
|
2039
|
-
var
|
|
2038
|
+
var FREE_MAX_JOBS_PER_CUSTOMER = 20;
|
|
2039
|
+
var FREE_GLOBAL_MAX_JOBS_PER_WINDOW = 200;
|
|
2040
|
+
var PAID_MAX_JOBS_PER_CUSTOMER = 200;
|
|
2041
|
+
var PAID_GLOBAL_MAX_JOBS_PER_WINDOW = 2e3;
|
|
2040
2042
|
var MAX_TRACKED_CUSTOMERS = 1e3;
|
|
2041
2043
|
var GLOBAL_LIMITER_KEY = "__global__";
|
|
2042
2044
|
var AgentRuntime = class {
|
|
@@ -2060,16 +2062,32 @@ var AgentRuntime = class {
|
|
|
2060
2062
|
recoveryInterval = null;
|
|
2061
2063
|
gcInterval = null;
|
|
2062
2064
|
stopped = false;
|
|
2063
|
-
/** Per-customer sliding-window rate limiter
|
|
2064
|
-
|
|
2065
|
+
/** Per-customer sliding-window rate limiter for free skills. */
|
|
2066
|
+
freeCustomerLimiter = createSlidingWindowLimiter({
|
|
2065
2067
|
windowMs: RATE_LIMIT_WINDOW_MS,
|
|
2066
|
-
maxPerWindow:
|
|
2068
|
+
maxPerWindow: FREE_MAX_JOBS_PER_CUSTOMER,
|
|
2067
2069
|
maxKeys: MAX_TRACKED_CUSTOMERS
|
|
2068
2070
|
});
|
|
2069
|
-
/** Global sliding-window rate limiter (Sybil protection). */
|
|
2070
|
-
|
|
2071
|
+
/** Global sliding-window rate limiter for free skills (Sybil protection). */
|
|
2072
|
+
freeGlobalLimiter = createSlidingWindowLimiter({
|
|
2071
2073
|
windowMs: RATE_LIMIT_WINDOW_MS,
|
|
2072
|
-
maxPerWindow:
|
|
2074
|
+
maxPerWindow: FREE_GLOBAL_MAX_JOBS_PER_WINDOW,
|
|
2075
|
+
maxKeys: 1
|
|
2076
|
+
});
|
|
2077
|
+
/**
|
|
2078
|
+
* Per-customer sliding-window limiter for paid skills (10x looser than free).
|
|
2079
|
+
* Payment is the primary economic deterrent; this cap exists to bound the
|
|
2080
|
+
* "claim paid skill but never pay" queue-spam vector.
|
|
2081
|
+
*/
|
|
2082
|
+
paidCustomerLimiter = createSlidingWindowLimiter({
|
|
2083
|
+
windowMs: RATE_LIMIT_WINDOW_MS,
|
|
2084
|
+
maxPerWindow: PAID_MAX_JOBS_PER_CUSTOMER,
|
|
2085
|
+
maxKeys: MAX_TRACKED_CUSTOMERS
|
|
2086
|
+
});
|
|
2087
|
+
/** Global sliding-window limiter for paid skills (Sybil protection, 10x free). */
|
|
2088
|
+
paidGlobalLimiter = createSlidingWindowLimiter({
|
|
2089
|
+
windowMs: RATE_LIMIT_WINDOW_MS,
|
|
2090
|
+
maxPerWindow: PAID_GLOBAL_MAX_JOBS_PER_WINDOW,
|
|
2073
2091
|
maxKeys: 1
|
|
2074
2092
|
});
|
|
2075
2093
|
/**
|
|
@@ -2247,17 +2265,20 @@ var AgentRuntime = class {
|
|
|
2247
2265
|
});
|
|
2248
2266
|
return;
|
|
2249
2267
|
}
|
|
2250
|
-
|
|
2268
|
+
const matched = this.skills.route(job.tags);
|
|
2269
|
+
const isPaid = matched ? matched.priceSubunits > 0 : false;
|
|
2270
|
+
const customerLimiter = isPaid ? this.paidCustomerLimiter : this.freeCustomerLimiter;
|
|
2271
|
+
const globalLimiter = isPaid ? this.paidGlobalLimiter : this.freeGlobalLimiter;
|
|
2272
|
+
if (!customerLimiter.peek(job.customerId).allowed) {
|
|
2251
2273
|
this.transport.sendFeedback(job, { type: "error", message: "Rate limited, try again later" }).catch(() => {
|
|
2252
2274
|
});
|
|
2253
2275
|
return;
|
|
2254
2276
|
}
|
|
2255
|
-
if (!
|
|
2277
|
+
if (!globalLimiter.peek(GLOBAL_LIMITER_KEY).allowed) {
|
|
2256
2278
|
this.transport.sendFeedback(job, { type: "error", message: "Server busy, try again later" }).catch(() => {
|
|
2257
2279
|
});
|
|
2258
2280
|
return;
|
|
2259
2281
|
}
|
|
2260
|
-
const matched = this.skills.route(job.tags);
|
|
2261
2282
|
const isFreeLlm = matched?.mode === "llm" && matched.priceSubunits === 0;
|
|
2262
2283
|
let perCustomerLimiter;
|
|
2263
2284
|
let perSkillKey;
|
|
@@ -2278,8 +2299,8 @@ var AgentRuntime = class {
|
|
|
2278
2299
|
return;
|
|
2279
2300
|
}
|
|
2280
2301
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2302
|
+
customerLimiter.check(job.customerId);
|
|
2303
|
+
globalLimiter.check(GLOBAL_LIMITER_KEY);
|
|
2283
2304
|
if (isFreeLlm && perCustomerLimiter && perSkillKey) {
|
|
2284
2305
|
this.freeLlmLimiters.globalLimiter.check(FREE_LLM_GLOBAL_KEY);
|
|
2285
2306
|
perCustomerLimiter.check(perSkillKey);
|
|
@@ -2313,8 +2334,10 @@ var AgentRuntime = class {
|
|
|
2313
2334
|
}
|
|
2314
2335
|
/** Drop expired hits from every sliding-window limiter. */
|
|
2315
2336
|
cleanupRateLimits() {
|
|
2316
|
-
this.
|
|
2317
|
-
this.
|
|
2337
|
+
this.freeCustomerLimiter.prune();
|
|
2338
|
+
this.freeGlobalLimiter.prune();
|
|
2339
|
+
this.paidCustomerLimiter.prune();
|
|
2340
|
+
this.paidGlobalLimiter.prune();
|
|
2318
2341
|
this.freeLlmLimiters.globalLimiter.prune();
|
|
2319
2342
|
this.freeLlmLimiters.prunePerCustomer();
|
|
2320
2343
|
}
|