@agentforge/core 0.16.71 → 0.16.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +119 -111
  2. package/dist/index.js +119 -111
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3057,6 +3057,18 @@ function withCache(node, options = {}) {
3057
3057
  return createCachedNode(node, cache2, resolvedOptions);
3058
3058
  }
3059
3059
 
3060
+ // src/langgraph/middleware/controller-runtime.ts
3061
+ function createControlledNode(node, resolveControlValue, executeWithController) {
3062
+ return async (state) => {
3063
+ const controlValue = resolveControlValue(state);
3064
+ return executeWithController(
3065
+ state,
3066
+ controlValue,
3067
+ (nextState) => Promise.resolve(node(nextState))
3068
+ );
3069
+ };
3070
+ }
3071
+
3060
3072
  // src/langgraph/middleware/rate-limiting.ts
3061
3073
  var TokenBucket = class {
3062
3074
  constructor(maxTokens, refillRate) {
@@ -3131,6 +3143,61 @@ var FixedWindow = class {
3131
3143
  this.windowStart = Date.now();
3132
3144
  }
3133
3145
  };
3146
+ function createRateLimiter(strategy, maxRequests, windowMs) {
3147
+ switch (strategy) {
3148
+ case "token-bucket":
3149
+ return new TokenBucket(maxRequests, maxRequests / windowMs);
3150
+ case "sliding-window":
3151
+ return new SlidingWindow(maxRequests, windowMs);
3152
+ case "fixed-window":
3153
+ return new FixedWindow(maxRequests, windowMs);
3154
+ default:
3155
+ throw new Error(`Unknown rate limit strategy: ${strategy}`);
3156
+ }
3157
+ }
3158
+ var RateLimiterRegistry = class {
3159
+ constructor(maxRequests, windowMs, strategy, onRateLimitExceeded, onRateLimitReset) {
3160
+ this.maxRequests = maxRequests;
3161
+ this.windowMs = windowMs;
3162
+ this.strategy = strategy;
3163
+ this.onRateLimitExceeded = onRateLimitExceeded;
3164
+ this.onRateLimitReset = onRateLimitReset;
3165
+ }
3166
+ limiters = /* @__PURE__ */ new Map();
3167
+ async execute(state, key, executor) {
3168
+ const limiter = this.getOrCreate(key);
3169
+ if (!limiter.tryConsume()) {
3170
+ this.onRateLimitExceeded?.(key);
3171
+ throw new Error(`Rate limit exceeded for key: ${key}`);
3172
+ }
3173
+ return executor(state);
3174
+ }
3175
+ reset(key) {
3176
+ if (key) {
3177
+ this.resetLimiter(key, this.limiters.get(key));
3178
+ return;
3179
+ }
3180
+ this.limiters.forEach((limiter, limiterKey) => {
3181
+ this.resetLimiter(limiterKey, limiter);
3182
+ });
3183
+ }
3184
+ getOrCreate(key) {
3185
+ const existing = this.limiters.get(key);
3186
+ if (existing) {
3187
+ return existing;
3188
+ }
3189
+ const limiter = createRateLimiter(this.strategy, this.maxRequests, this.windowMs);
3190
+ this.limiters.set(key, limiter);
3191
+ return limiter;
3192
+ }
3193
+ resetLimiter(key, limiter) {
3194
+ if (!limiter) {
3195
+ return;
3196
+ }
3197
+ limiter.reset();
3198
+ this.onRateLimitReset?.(key);
3199
+ }
3200
+ };
3134
3201
  function withRateLimit(node, options) {
3135
3202
  const {
3136
3203
  maxRequests,
@@ -3140,35 +3207,18 @@ function withRateLimit(node, options) {
3140
3207
  onRateLimitReset,
3141
3208
  keyGenerator = () => "global"
3142
3209
  } = options;
3143
- const limiters = /* @__PURE__ */ new Map();
3144
- return async (state) => {
3145
- const key = keyGenerator(state);
3146
- if (!limiters.has(key)) {
3147
- let limiter2;
3148
- switch (strategy) {
3149
- case "token-bucket":
3150
- limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
3151
- break;
3152
- case "sliding-window":
3153
- limiter2 = new SlidingWindow(maxRequests, windowMs);
3154
- break;
3155
- case "fixed-window":
3156
- limiter2 = new FixedWindow(maxRequests, windowMs);
3157
- break;
3158
- default:
3159
- throw new Error(`Unknown rate limit strategy: ${strategy}`);
3160
- }
3161
- limiters.set(key, limiter2);
3162
- }
3163
- const limiter = limiters.get(key);
3164
- if (!limiter.tryConsume()) {
3165
- if (onRateLimitExceeded) {
3166
- onRateLimitExceeded(key);
3167
- }
3168
- throw new Error(`Rate limit exceeded for key: ${key}`);
3169
- }
3170
- return await Promise.resolve(node(state));
3171
- };
3210
+ const registry = new RateLimiterRegistry(
3211
+ maxRequests,
3212
+ windowMs,
3213
+ strategy,
3214
+ onRateLimitExceeded,
3215
+ onRateLimitReset
3216
+ );
3217
+ return createControlledNode(
3218
+ node,
3219
+ keyGenerator,
3220
+ (state, key, executor) => registry.execute(state, key, executor)
3221
+ );
3172
3222
  }
3173
3223
  function createSharedRateLimiter(options) {
3174
3224
  const {
@@ -3178,55 +3228,23 @@ function createSharedRateLimiter(options) {
3178
3228
  onRateLimitExceeded,
3179
3229
  onRateLimitReset
3180
3230
  } = options;
3181
- const limiters = /* @__PURE__ */ new Map();
3231
+ const registry = new RateLimiterRegistry(
3232
+ maxRequests,
3233
+ windowMs,
3234
+ strategy,
3235
+ onRateLimitExceeded,
3236
+ onRateLimitReset
3237
+ );
3182
3238
  return {
3183
- withRateLimit: (node, keyGenerator = (state) => "global") => {
3184
- return async (state) => {
3185
- const key = keyGenerator(state);
3186
- if (!limiters.has(key)) {
3187
- let limiter2;
3188
- switch (strategy) {
3189
- case "token-bucket":
3190
- limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
3191
- break;
3192
- case "sliding-window":
3193
- limiter2 = new SlidingWindow(maxRequests, windowMs);
3194
- break;
3195
- case "fixed-window":
3196
- limiter2 = new FixedWindow(maxRequests, windowMs);
3197
- break;
3198
- default:
3199
- throw new Error(`Unknown rate limit strategy: ${strategy}`);
3200
- }
3201
- limiters.set(key, limiter2);
3202
- }
3203
- const limiter = limiters.get(key);
3204
- if (!limiter.tryConsume()) {
3205
- if (onRateLimitExceeded) {
3206
- onRateLimitExceeded(key);
3207
- }
3208
- throw new Error(`Rate limit exceeded for key: ${key}`);
3209
- }
3210
- return await Promise.resolve(node(state));
3211
- };
3239
+ withRateLimit: (node, keyGenerator = () => "global") => {
3240
+ return createControlledNode(
3241
+ node,
3242
+ keyGenerator,
3243
+ (state, key, executor) => registry.execute(state, key, executor)
3244
+ );
3212
3245
  },
3213
3246
  reset: (key) => {
3214
- if (key) {
3215
- const limiter = limiters.get(key);
3216
- if (limiter) {
3217
- limiter.reset();
3218
- if (onRateLimitReset) {
3219
- onRateLimitReset(key);
3220
- }
3221
- }
3222
- } else {
3223
- limiters.forEach((limiter, k) => {
3224
- limiter.reset();
3225
- if (onRateLimitReset) {
3226
- onRateLimitReset(k);
3227
- }
3228
- });
3229
- }
3247
+ registry.reset(key);
3230
3248
  }
3231
3249
  };
3232
3250
  }
@@ -3400,7 +3418,7 @@ var ConcurrencyController = class {
3400
3418
  this.queue = [];
3401
3419
  }
3402
3420
  };
3403
- function withConcurrency(node, options = {}) {
3421
+ function createConfiguredConcurrencyController(options = {}) {
3404
3422
  const {
3405
3423
  maxConcurrent = 1,
3406
3424
  maxQueueSize = 0,
@@ -3411,46 +3429,36 @@ function withConcurrency(node, options = {}) {
3411
3429
  onQueueFull,
3412
3430
  queueTimeout = 0
3413
3431
  } = options;
3414
- const controller = new ConcurrencyController(
3415
- maxConcurrent,
3416
- maxQueueSize,
3417
- onQueued,
3418
- onExecutionStart,
3419
- onExecutionComplete,
3420
- onQueueFull,
3421
- queueTimeout
3422
- );
3423
- return async (state) => {
3424
- const priority = priorityFn(state);
3425
- return controller.execute(state, priority, async (s) => await node(s));
3432
+ return {
3433
+ controller: new ConcurrencyController(
3434
+ maxConcurrent,
3435
+ maxQueueSize,
3436
+ onQueued,
3437
+ onExecutionStart,
3438
+ onExecutionComplete,
3439
+ onQueueFull,
3440
+ queueTimeout
3441
+ ),
3442
+ priorityFn
3426
3443
  };
3427
3444
  }
3428
- function createSharedConcurrencyController(options = {}) {
3429
- const {
3430
- maxConcurrent = 1,
3431
- maxQueueSize = 0,
3432
- priorityFn = () => "normal",
3433
- onQueued,
3434
- onExecutionStart,
3435
- onExecutionComplete,
3436
- onQueueFull,
3437
- queueTimeout = 0
3438
- } = options;
3439
- const controller = new ConcurrencyController(
3440
- maxConcurrent,
3441
- maxQueueSize,
3442
- onQueued,
3443
- onExecutionStart,
3444
- onExecutionComplete,
3445
- onQueueFull,
3446
- queueTimeout
3445
+ function withConcurrency(node, options = {}) {
3446
+ const { controller, priorityFn } = createConfiguredConcurrencyController(options);
3447
+ return createControlledNode(
3448
+ node,
3449
+ priorityFn,
3450
+ (state, priority, executor) => controller.execute(state, priority, executor)
3447
3451
  );
3452
+ }
3453
+ function createSharedConcurrencyController(options = {}) {
3454
+ const { controller, priorityFn } = createConfiguredConcurrencyController(options);
3448
3455
  return {
3449
3456
  withConcurrency: (node) => {
3450
- return async (state) => {
3451
- const priority = priorityFn(state);
3452
- return controller.execute(state, priority, async (s) => await node(s));
3453
- };
3457
+ return createControlledNode(
3458
+ node,
3459
+ priorityFn,
3460
+ (state, priority, executor) => controller.execute(state, priority, executor)
3461
+ );
3454
3462
  },
3455
3463
  getStats: () => controller.getStats(),
3456
3464
  clear: () => controller.clear()
package/dist/index.js CHANGED
@@ -2881,6 +2881,18 @@ function withCache(node, options = {}) {
2881
2881
  return createCachedNode(node, cache2, resolvedOptions);
2882
2882
  }
2883
2883
 
2884
+ // src/langgraph/middleware/controller-runtime.ts
2885
+ function createControlledNode(node, resolveControlValue, executeWithController) {
2886
+ return async (state) => {
2887
+ const controlValue = resolveControlValue(state);
2888
+ return executeWithController(
2889
+ state,
2890
+ controlValue,
2891
+ (nextState) => Promise.resolve(node(nextState))
2892
+ );
2893
+ };
2894
+ }
2895
+
2884
2896
  // src/langgraph/middleware/rate-limiting.ts
2885
2897
  var TokenBucket = class {
2886
2898
  constructor(maxTokens, refillRate) {
@@ -2955,6 +2967,61 @@ var FixedWindow = class {
2955
2967
  this.windowStart = Date.now();
2956
2968
  }
2957
2969
  };
2970
+ function createRateLimiter(strategy, maxRequests, windowMs) {
2971
+ switch (strategy) {
2972
+ case "token-bucket":
2973
+ return new TokenBucket(maxRequests, maxRequests / windowMs);
2974
+ case "sliding-window":
2975
+ return new SlidingWindow(maxRequests, windowMs);
2976
+ case "fixed-window":
2977
+ return new FixedWindow(maxRequests, windowMs);
2978
+ default:
2979
+ throw new Error(`Unknown rate limit strategy: ${strategy}`);
2980
+ }
2981
+ }
2982
+ var RateLimiterRegistry = class {
2983
+ constructor(maxRequests, windowMs, strategy, onRateLimitExceeded, onRateLimitReset) {
2984
+ this.maxRequests = maxRequests;
2985
+ this.windowMs = windowMs;
2986
+ this.strategy = strategy;
2987
+ this.onRateLimitExceeded = onRateLimitExceeded;
2988
+ this.onRateLimitReset = onRateLimitReset;
2989
+ }
2990
+ limiters = /* @__PURE__ */ new Map();
2991
+ async execute(state, key, executor) {
2992
+ const limiter = this.getOrCreate(key);
2993
+ if (!limiter.tryConsume()) {
2994
+ this.onRateLimitExceeded?.(key);
2995
+ throw new Error(`Rate limit exceeded for key: ${key}`);
2996
+ }
2997
+ return executor(state);
2998
+ }
2999
+ reset(key) {
3000
+ if (key) {
3001
+ this.resetLimiter(key, this.limiters.get(key));
3002
+ return;
3003
+ }
3004
+ this.limiters.forEach((limiter, limiterKey) => {
3005
+ this.resetLimiter(limiterKey, limiter);
3006
+ });
3007
+ }
3008
+ getOrCreate(key) {
3009
+ const existing = this.limiters.get(key);
3010
+ if (existing) {
3011
+ return existing;
3012
+ }
3013
+ const limiter = createRateLimiter(this.strategy, this.maxRequests, this.windowMs);
3014
+ this.limiters.set(key, limiter);
3015
+ return limiter;
3016
+ }
3017
+ resetLimiter(key, limiter) {
3018
+ if (!limiter) {
3019
+ return;
3020
+ }
3021
+ limiter.reset();
3022
+ this.onRateLimitReset?.(key);
3023
+ }
3024
+ };
2958
3025
  function withRateLimit(node, options) {
2959
3026
  const {
2960
3027
  maxRequests,
@@ -2964,35 +3031,18 @@ function withRateLimit(node, options) {
2964
3031
  onRateLimitReset,
2965
3032
  keyGenerator = () => "global"
2966
3033
  } = options;
2967
- const limiters = /* @__PURE__ */ new Map();
2968
- return async (state) => {
2969
- const key = keyGenerator(state);
2970
- if (!limiters.has(key)) {
2971
- let limiter2;
2972
- switch (strategy) {
2973
- case "token-bucket":
2974
- limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
2975
- break;
2976
- case "sliding-window":
2977
- limiter2 = new SlidingWindow(maxRequests, windowMs);
2978
- break;
2979
- case "fixed-window":
2980
- limiter2 = new FixedWindow(maxRequests, windowMs);
2981
- break;
2982
- default:
2983
- throw new Error(`Unknown rate limit strategy: ${strategy}`);
2984
- }
2985
- limiters.set(key, limiter2);
2986
- }
2987
- const limiter = limiters.get(key);
2988
- if (!limiter.tryConsume()) {
2989
- if (onRateLimitExceeded) {
2990
- onRateLimitExceeded(key);
2991
- }
2992
- throw new Error(`Rate limit exceeded for key: ${key}`);
2993
- }
2994
- return await Promise.resolve(node(state));
2995
- };
3034
+ const registry = new RateLimiterRegistry(
3035
+ maxRequests,
3036
+ windowMs,
3037
+ strategy,
3038
+ onRateLimitExceeded,
3039
+ onRateLimitReset
3040
+ );
3041
+ return createControlledNode(
3042
+ node,
3043
+ keyGenerator,
3044
+ (state, key, executor) => registry.execute(state, key, executor)
3045
+ );
2996
3046
  }
2997
3047
  function createSharedRateLimiter(options) {
2998
3048
  const {
@@ -3002,55 +3052,23 @@ function createSharedRateLimiter(options) {
3002
3052
  onRateLimitExceeded,
3003
3053
  onRateLimitReset
3004
3054
  } = options;
3005
- const limiters = /* @__PURE__ */ new Map();
3055
+ const registry = new RateLimiterRegistry(
3056
+ maxRequests,
3057
+ windowMs,
3058
+ strategy,
3059
+ onRateLimitExceeded,
3060
+ onRateLimitReset
3061
+ );
3006
3062
  return {
3007
- withRateLimit: (node, keyGenerator = (state) => "global") => {
3008
- return async (state) => {
3009
- const key = keyGenerator(state);
3010
- if (!limiters.has(key)) {
3011
- let limiter2;
3012
- switch (strategy) {
3013
- case "token-bucket":
3014
- limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
3015
- break;
3016
- case "sliding-window":
3017
- limiter2 = new SlidingWindow(maxRequests, windowMs);
3018
- break;
3019
- case "fixed-window":
3020
- limiter2 = new FixedWindow(maxRequests, windowMs);
3021
- break;
3022
- default:
3023
- throw new Error(`Unknown rate limit strategy: ${strategy}`);
3024
- }
3025
- limiters.set(key, limiter2);
3026
- }
3027
- const limiter = limiters.get(key);
3028
- if (!limiter.tryConsume()) {
3029
- if (onRateLimitExceeded) {
3030
- onRateLimitExceeded(key);
3031
- }
3032
- throw new Error(`Rate limit exceeded for key: ${key}`);
3033
- }
3034
- return await Promise.resolve(node(state));
3035
- };
3063
+ withRateLimit: (node, keyGenerator = () => "global") => {
3064
+ return createControlledNode(
3065
+ node,
3066
+ keyGenerator,
3067
+ (state, key, executor) => registry.execute(state, key, executor)
3068
+ );
3036
3069
  },
3037
3070
  reset: (key) => {
3038
- if (key) {
3039
- const limiter = limiters.get(key);
3040
- if (limiter) {
3041
- limiter.reset();
3042
- if (onRateLimitReset) {
3043
- onRateLimitReset(key);
3044
- }
3045
- }
3046
- } else {
3047
- limiters.forEach((limiter, k) => {
3048
- limiter.reset();
3049
- if (onRateLimitReset) {
3050
- onRateLimitReset(k);
3051
- }
3052
- });
3053
- }
3071
+ registry.reset(key);
3054
3072
  }
3055
3073
  };
3056
3074
  }
@@ -3224,7 +3242,7 @@ var ConcurrencyController = class {
3224
3242
  this.queue = [];
3225
3243
  }
3226
3244
  };
3227
- function withConcurrency(node, options = {}) {
3245
+ function createConfiguredConcurrencyController(options = {}) {
3228
3246
  const {
3229
3247
  maxConcurrent = 1,
3230
3248
  maxQueueSize = 0,
@@ -3235,46 +3253,36 @@ function withConcurrency(node, options = {}) {
3235
3253
  onQueueFull,
3236
3254
  queueTimeout = 0
3237
3255
  } = options;
3238
- const controller = new ConcurrencyController(
3239
- maxConcurrent,
3240
- maxQueueSize,
3241
- onQueued,
3242
- onExecutionStart,
3243
- onExecutionComplete,
3244
- onQueueFull,
3245
- queueTimeout
3246
- );
3247
- return async (state) => {
3248
- const priority = priorityFn(state);
3249
- return controller.execute(state, priority, async (s) => await node(s));
3256
+ return {
3257
+ controller: new ConcurrencyController(
3258
+ maxConcurrent,
3259
+ maxQueueSize,
3260
+ onQueued,
3261
+ onExecutionStart,
3262
+ onExecutionComplete,
3263
+ onQueueFull,
3264
+ queueTimeout
3265
+ ),
3266
+ priorityFn
3250
3267
  };
3251
3268
  }
3252
- function createSharedConcurrencyController(options = {}) {
3253
- const {
3254
- maxConcurrent = 1,
3255
- maxQueueSize = 0,
3256
- priorityFn = () => "normal",
3257
- onQueued,
3258
- onExecutionStart,
3259
- onExecutionComplete,
3260
- onQueueFull,
3261
- queueTimeout = 0
3262
- } = options;
3263
- const controller = new ConcurrencyController(
3264
- maxConcurrent,
3265
- maxQueueSize,
3266
- onQueued,
3267
- onExecutionStart,
3268
- onExecutionComplete,
3269
- onQueueFull,
3270
- queueTimeout
3269
+ function withConcurrency(node, options = {}) {
3270
+ const { controller, priorityFn } = createConfiguredConcurrencyController(options);
3271
+ return createControlledNode(
3272
+ node,
3273
+ priorityFn,
3274
+ (state, priority, executor) => controller.execute(state, priority, executor)
3271
3275
  );
3276
+ }
3277
+ function createSharedConcurrencyController(options = {}) {
3278
+ const { controller, priorityFn } = createConfiguredConcurrencyController(options);
3272
3279
  return {
3273
3280
  withConcurrency: (node) => {
3274
- return async (state) => {
3275
- const priority = priorityFn(state);
3276
- return controller.execute(state, priority, async (s) => await node(s));
3277
- };
3281
+ return createControlledNode(
3282
+ node,
3283
+ priorityFn,
3284
+ (state, priority, executor) => controller.execute(state, priority, executor)
3285
+ );
3278
3286
  },
3279
3287
  getStats: () => controller.getStats(),
3280
3288
  clear: () => controller.clear()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge/core",
3
- "version": "0.16.71",
3
+ "version": "0.16.73",
4
4
  "description": "Production-ready TypeScript agent framework built on LangGraph with orchestration, middleware, and typed abstractions.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",