@agentforge/core 0.16.53 → 0.16.55
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.cjs +99 -113
- package/dist/index.d.cts +25 -25
- package/dist/index.d.ts +25 -25
- package/dist/index.js +99 -113
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2888,36 +2888,61 @@ var presets = {
|
|
|
2888
2888
|
testing
|
|
2889
2889
|
};
|
|
2890
2890
|
|
|
2891
|
-
// src/langgraph/middleware/caching.ts
|
|
2891
|
+
// src/langgraph/middleware/caching-options.ts
|
|
2892
|
+
function defaultCacheKeyGenerator(state) {
|
|
2893
|
+
try {
|
|
2894
|
+
return JSON.stringify(state);
|
|
2895
|
+
} catch {
|
|
2896
|
+
return String(state);
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
function resolveCachingOptions(options) {
|
|
2900
|
+
return {
|
|
2901
|
+
ttl: options.ttl ?? 36e5,
|
|
2902
|
+
maxSize: options.maxSize ?? 100,
|
|
2903
|
+
evictionStrategy: options.evictionStrategy ?? "lru",
|
|
2904
|
+
keyGenerator: options.keyGenerator ?? defaultCacheKeyGenerator,
|
|
2905
|
+
cacheErrors: options.cacheErrors ?? false,
|
|
2906
|
+
onCacheHit: options.onCacheHit,
|
|
2907
|
+
onCacheMiss: options.onCacheMiss,
|
|
2908
|
+
onEviction: options.onEviction
|
|
2909
|
+
};
|
|
2910
|
+
}
|
|
2911
|
+
function resolveSharedCacheKeyGenerator(keyGenerator) {
|
|
2912
|
+
return keyGenerator ?? defaultCacheKeyGenerator;
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
// src/langgraph/middleware/caching-store.ts
|
|
2892
2916
|
var LRUCache = class {
|
|
2893
|
-
cache = /* @__PURE__ */ new Map();
|
|
2894
|
-
maxSize;
|
|
2895
|
-
evictionStrategy;
|
|
2896
2917
|
constructor(maxSize, evictionStrategy = "lru") {
|
|
2897
2918
|
this.maxSize = maxSize;
|
|
2898
2919
|
this.evictionStrategy = evictionStrategy;
|
|
2899
2920
|
}
|
|
2921
|
+
cache = /* @__PURE__ */ new Map();
|
|
2900
2922
|
get(key) {
|
|
2901
2923
|
const entry = this.cache.get(key);
|
|
2902
|
-
if (!entry)
|
|
2924
|
+
if (!entry) {
|
|
2925
|
+
return void 0;
|
|
2926
|
+
}
|
|
2903
2927
|
entry.hits++;
|
|
2904
2928
|
entry.lastAccessed = Date.now();
|
|
2905
2929
|
return entry.value;
|
|
2906
2930
|
}
|
|
2931
|
+
getEntry(key) {
|
|
2932
|
+
return this.cache.get(key);
|
|
2933
|
+
}
|
|
2907
2934
|
set(key, value) {
|
|
2908
2935
|
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
2909
2936
|
this.evict();
|
|
2910
2937
|
}
|
|
2938
|
+
const now = Date.now();
|
|
2911
2939
|
this.cache.set(key, {
|
|
2912
2940
|
value,
|
|
2913
|
-
timestamp:
|
|
2941
|
+
timestamp: now,
|
|
2914
2942
|
hits: 0,
|
|
2915
|
-
lastAccessed:
|
|
2943
|
+
lastAccessed: now
|
|
2916
2944
|
});
|
|
2917
2945
|
}
|
|
2918
|
-
has(key) {
|
|
2919
|
-
return this.cache.has(key);
|
|
2920
|
-
}
|
|
2921
2946
|
delete(key) {
|
|
2922
2947
|
return this.cache.delete(key);
|
|
2923
2948
|
}
|
|
@@ -2928,138 +2953,99 @@ var LRUCache = class {
|
|
|
2928
2953
|
return this.cache.size;
|
|
2929
2954
|
}
|
|
2930
2955
|
evict() {
|
|
2931
|
-
if (this.cache.size === 0)
|
|
2932
|
-
|
|
2933
|
-
if (this.evictionStrategy === "lru") {
|
|
2934
|
-
let oldestAccess = Infinity;
|
|
2935
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
2936
|
-
if (entry.lastAccessed < oldestAccess) {
|
|
2937
|
-
oldestAccess = entry.lastAccessed;
|
|
2938
|
-
keyToEvict = key;
|
|
2939
|
-
}
|
|
2940
|
-
}
|
|
2941
|
-
} else if (this.evictionStrategy === "lfu") {
|
|
2942
|
-
let lowestHits = Infinity;
|
|
2943
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
2944
|
-
if (entry.hits < lowestHits) {
|
|
2945
|
-
lowestHits = entry.hits;
|
|
2946
|
-
keyToEvict = key;
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
|
-
} else {
|
|
2950
|
-
keyToEvict = this.cache.keys().next().value;
|
|
2956
|
+
if (this.cache.size === 0) {
|
|
2957
|
+
return;
|
|
2951
2958
|
}
|
|
2952
|
-
|
|
2959
|
+
const keyToEvict = this.findKeyToEvict();
|
|
2960
|
+
if (keyToEvict !== void 0) {
|
|
2953
2961
|
this.cache.delete(keyToEvict);
|
|
2954
2962
|
}
|
|
2955
2963
|
}
|
|
2964
|
+
findKeyToEvict() {
|
|
2965
|
+
if (this.evictionStrategy === "fifo") {
|
|
2966
|
+
return this.cache.keys().next().value;
|
|
2967
|
+
}
|
|
2968
|
+
let selectedKey;
|
|
2969
|
+
let selectedValue = Infinity;
|
|
2970
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
2971
|
+
const candidateValue = this.evictionStrategy === "lfu" ? entry.hits : entry.lastAccessed;
|
|
2972
|
+
if (candidateValue < selectedValue) {
|
|
2973
|
+
selectedValue = candidateValue;
|
|
2974
|
+
selectedKey = key;
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
return selectedKey;
|
|
2978
|
+
}
|
|
2956
2979
|
};
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
return
|
|
2980
|
+
|
|
2981
|
+
// src/langgraph/middleware/caching-entry.ts
|
|
2982
|
+
function isFreshCacheEntry(entry, ttl) {
|
|
2983
|
+
if (!entry) {
|
|
2984
|
+
return false;
|
|
2962
2985
|
}
|
|
2986
|
+
return Date.now() - entry.timestamp < ttl;
|
|
2963
2987
|
}
|
|
2964
|
-
function
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
keyGenerator = defaultKeyGenerator,
|
|
2971
|
-
cacheErrors = false,
|
|
2972
|
-
onCacheHit,
|
|
2973
|
-
onCacheMiss,
|
|
2974
|
-
onEviction
|
|
2975
|
-
} = options;
|
|
2976
|
-
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
2988
|
+
function createCachedErrorResult(error) {
|
|
2989
|
+
return { error: error.message };
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
// src/langgraph/middleware/caching-wrapper.ts
|
|
2993
|
+
function createCachedNode(node, cache2, options, keyGenerator = options.keyGenerator) {
|
|
2977
2994
|
return async (state) => {
|
|
2978
2995
|
const cacheKey = keyGenerator(state);
|
|
2979
2996
|
const cachedValue = cache2.get(cacheKey);
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
if (onCacheHit) {
|
|
2985
|
-
onCacheHit(cacheKey, cachedValue);
|
|
2986
|
-
}
|
|
2987
|
-
return cachedValue;
|
|
2988
|
-
} else {
|
|
2989
|
-
cache2.delete(cacheKey);
|
|
2990
|
-
if (onEviction) {
|
|
2991
|
-
onEviction(cacheKey, cachedValue);
|
|
2992
|
-
}
|
|
2993
|
-
}
|
|
2997
|
+
const entry = cache2.getEntry(cacheKey);
|
|
2998
|
+
if (cachedValue !== void 0 && isFreshCacheEntry(entry, options.ttl)) {
|
|
2999
|
+
options.onCacheHit?.(cacheKey, cachedValue);
|
|
3000
|
+
return cachedValue;
|
|
2994
3001
|
}
|
|
2995
|
-
if (
|
|
2996
|
-
|
|
3002
|
+
if (cachedValue !== void 0 && entry) {
|
|
3003
|
+
cache2.delete(cacheKey);
|
|
3004
|
+
options.onEviction?.(cacheKey, cachedValue);
|
|
2997
3005
|
}
|
|
3006
|
+
options.onCacheMiss?.(cacheKey);
|
|
2998
3007
|
try {
|
|
2999
3008
|
const result = await Promise.resolve(node(state));
|
|
3000
3009
|
cache2.set(cacheKey, result);
|
|
3001
3010
|
return result;
|
|
3002
3011
|
} catch (error) {
|
|
3003
|
-
if (cacheErrors && error instanceof Error) {
|
|
3004
|
-
|
|
3005
|
-
cache2.set(cacheKey, errorResult);
|
|
3012
|
+
if (options.cacheErrors && error instanceof Error) {
|
|
3013
|
+
cache2.set(cacheKey, createCachedErrorResult(error));
|
|
3006
3014
|
}
|
|
3007
3015
|
throw error;
|
|
3008
3016
|
}
|
|
3009
3017
|
};
|
|
3010
3018
|
}
|
|
3019
|
+
|
|
3020
|
+
// src/langgraph/middleware/caching-shared.ts
|
|
3011
3021
|
function createSharedCache(options = {}) {
|
|
3012
|
-
const
|
|
3013
|
-
|
|
3014
|
-
maxSize
|
|
3015
|
-
evictionStrategy
|
|
3016
|
-
|
|
3017
|
-
onCacheHit,
|
|
3018
|
-
onCacheMiss,
|
|
3019
|
-
onEviction
|
|
3020
|
-
} = options;
|
|
3021
|
-
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
3022
|
+
const resolvedOptions = resolveCachingOptions(options);
|
|
3023
|
+
const cache2 = new LRUCache(
|
|
3024
|
+
resolvedOptions.maxSize,
|
|
3025
|
+
resolvedOptions.evictionStrategy
|
|
3026
|
+
);
|
|
3022
3027
|
return {
|
|
3023
|
-
withCache: (node, keyGenerator
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
const age = Date.now() - entry.timestamp;
|
|
3030
|
-
if (age < ttl) {
|
|
3031
|
-
if (onCacheHit) {
|
|
3032
|
-
onCacheHit(cacheKey, cachedValue);
|
|
3033
|
-
}
|
|
3034
|
-
return cachedValue;
|
|
3035
|
-
} else {
|
|
3036
|
-
cache2.delete(cacheKey);
|
|
3037
|
-
if (onEviction) {
|
|
3038
|
-
onEviction(cacheKey, cachedValue);
|
|
3039
|
-
}
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
if (onCacheMiss) {
|
|
3043
|
-
onCacheMiss(cacheKey);
|
|
3044
|
-
}
|
|
3045
|
-
try {
|
|
3046
|
-
const result = await Promise.resolve(node(state));
|
|
3047
|
-
cache2.set(cacheKey, result);
|
|
3048
|
-
return result;
|
|
3049
|
-
} catch (error) {
|
|
3050
|
-
if (cacheErrors && error instanceof Error) {
|
|
3051
|
-
const errorResult = { error: error.message };
|
|
3052
|
-
cache2.set(cacheKey, errorResult);
|
|
3053
|
-
}
|
|
3054
|
-
throw error;
|
|
3055
|
-
}
|
|
3056
|
-
};
|
|
3057
|
-
},
|
|
3028
|
+
withCache: (node, keyGenerator) => createCachedNode(
|
|
3029
|
+
node,
|
|
3030
|
+
cache2,
|
|
3031
|
+
resolvedOptions,
|
|
3032
|
+
resolveSharedCacheKeyGenerator(keyGenerator)
|
|
3033
|
+
),
|
|
3058
3034
|
clear: () => cache2.clear(),
|
|
3059
3035
|
size: () => cache2.size()
|
|
3060
3036
|
};
|
|
3061
3037
|
}
|
|
3062
3038
|
|
|
3039
|
+
// src/langgraph/middleware/caching.ts
|
|
3040
|
+
function withCache(node, options = {}) {
|
|
3041
|
+
const resolvedOptions = resolveCachingOptions(options);
|
|
3042
|
+
const cache2 = new LRUCache(
|
|
3043
|
+
resolvedOptions.maxSize,
|
|
3044
|
+
resolvedOptions.evictionStrategy
|
|
3045
|
+
);
|
|
3046
|
+
return createCachedNode(node, cache2, resolvedOptions);
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3063
3049
|
// src/langgraph/middleware/rate-limiting.ts
|
|
3064
3050
|
var TokenBucket = class {
|
|
3065
3051
|
constructor(maxTokens, refillRate) {
|
package/dist/index.d.cts
CHANGED
|
@@ -2445,12 +2445,6 @@ interface TracingOptions {
|
|
|
2445
2445
|
*/
|
|
2446
2446
|
declare function withTracing<State>(node: (state: State) => State | Promise<State> | Partial<State> | Promise<Partial<State>>, options: TracingOptions): (state: State) => Promise<State | Partial<State>>;
|
|
2447
2447
|
|
|
2448
|
-
/**
|
|
2449
|
-
* Caching Middleware for LangGraph Nodes
|
|
2450
|
-
*
|
|
2451
|
-
* Provides caching capabilities with TTL, LRU eviction, and custom key generation.
|
|
2452
|
-
*/
|
|
2453
|
-
|
|
2454
2448
|
/**
|
|
2455
2449
|
* Cache key generator function
|
|
2456
2450
|
*/
|
|
@@ -2464,54 +2458,68 @@ type EvictionStrategy = 'lru' | 'lfu' | 'fifo';
|
|
|
2464
2458
|
*/
|
|
2465
2459
|
interface CachingOptions<State> {
|
|
2466
2460
|
/**
|
|
2467
|
-
* Time-to-live in milliseconds
|
|
2461
|
+
* Time-to-live in milliseconds.
|
|
2468
2462
|
* @default 3600000 (1 hour)
|
|
2469
2463
|
*/
|
|
2470
2464
|
ttl?: number;
|
|
2471
2465
|
/**
|
|
2472
|
-
* Maximum number of cache entries
|
|
2466
|
+
* Maximum number of cache entries.
|
|
2473
2467
|
* @default 100
|
|
2474
2468
|
*/
|
|
2475
2469
|
maxSize?: number;
|
|
2476
2470
|
/**
|
|
2477
|
-
* Eviction strategy when cache is full
|
|
2471
|
+
* Eviction strategy when the cache is full.
|
|
2478
2472
|
* @default 'lru'
|
|
2479
2473
|
*/
|
|
2480
2474
|
evictionStrategy?: EvictionStrategy;
|
|
2481
2475
|
/**
|
|
2482
|
-
* Custom cache key generator
|
|
2483
|
-
* @default JSON.stringify
|
|
2476
|
+
* Custom cache key generator.
|
|
2477
|
+
* @default JSON.stringify with String(...) fallback
|
|
2484
2478
|
*/
|
|
2485
2479
|
keyGenerator?: CacheKeyGenerator<State>;
|
|
2486
2480
|
/**
|
|
2487
|
-
* Whether to cache
|
|
2481
|
+
* Whether to cache thrown `Error` results as `{ error: message }`.
|
|
2488
2482
|
* @default false
|
|
2489
2483
|
*/
|
|
2490
2484
|
cacheErrors?: boolean;
|
|
2491
2485
|
/**
|
|
2492
|
-
* Optional callback when
|
|
2486
|
+
* Optional callback invoked when a fresh cached value is returned.
|
|
2493
2487
|
*/
|
|
2494
2488
|
onCacheHit?: (key: string, value: State | Partial<State>) => void;
|
|
2495
2489
|
/**
|
|
2496
|
-
* Optional callback when
|
|
2490
|
+
* Optional callback invoked when no cached value is available.
|
|
2497
2491
|
*/
|
|
2498
2492
|
onCacheMiss?: (key: string) => void;
|
|
2499
2493
|
/**
|
|
2500
|
-
* Optional callback when
|
|
2494
|
+
* Optional callback invoked when a stale cached value is evicted.
|
|
2501
2495
|
*/
|
|
2502
2496
|
onEviction?: (key: string, value: State | Partial<State>) => void;
|
|
2503
2497
|
}
|
|
2498
|
+
interface SharedCache<State> {
|
|
2499
|
+
withCache: (node: NodeFunction<State>, keyGenerator?: CacheKeyGenerator<State>) => NodeFunction<State>;
|
|
2500
|
+
clear: () => void;
|
|
2501
|
+
size: () => number;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
declare function createSharedCache<State>(options?: Omit<CachingOptions<State>, 'keyGenerator'>): SharedCache<State>;
|
|
2505
|
+
|
|
2506
|
+
/**
|
|
2507
|
+
* Caching Middleware for LangGraph Nodes
|
|
2508
|
+
*
|
|
2509
|
+
* Provides caching capabilities with TTL, LRU eviction, and custom key generation.
|
|
2510
|
+
*/
|
|
2511
|
+
|
|
2504
2512
|
/**
|
|
2505
2513
|
* Wraps a node function with caching logic.
|
|
2506
2514
|
*
|
|
2507
2515
|
* @example
|
|
2508
2516
|
* ```typescript
|
|
2509
2517
|
* const cachedNode = withCache(expensiveNode, {
|
|
2510
|
-
* ttl: 3600000,
|
|
2518
|
+
* ttl: 3600000,
|
|
2511
2519
|
* maxSize: 100,
|
|
2512
2520
|
* evictionStrategy: 'lru',
|
|
2513
2521
|
* keyGenerator: (state) => state.userId,
|
|
2514
|
-
* onCacheHit: (key) =>
|
|
2522
|
+
* onCacheHit: (key) => recordCacheHitMetric(key),
|
|
2515
2523
|
* });
|
|
2516
2524
|
*
|
|
2517
2525
|
* graph.addNode('cached', cachedNode);
|
|
@@ -2522,14 +2530,6 @@ interface CachingOptions<State> {
|
|
|
2522
2530
|
* @returns A wrapped node function with caching
|
|
2523
2531
|
*/
|
|
2524
2532
|
declare function withCache<State>(node: NodeFunction<State>, options?: CachingOptions<State>): NodeFunction<State>;
|
|
2525
|
-
/**
|
|
2526
|
-
* Create a cache instance that can be shared across multiple nodes
|
|
2527
|
-
*/
|
|
2528
|
-
declare function createSharedCache<State>(options?: Omit<CachingOptions<State>, 'keyGenerator'>): {
|
|
2529
|
-
withCache: (node: NodeFunction<State>, keyGenerator?: CacheKeyGenerator<State>) => NodeFunction<State>;
|
|
2530
|
-
clear: () => void;
|
|
2531
|
-
size: () => number;
|
|
2532
|
-
};
|
|
2533
2533
|
|
|
2534
2534
|
/**
|
|
2535
2535
|
* Rate limiting strategy
|
package/dist/index.d.ts
CHANGED
|
@@ -2445,12 +2445,6 @@ interface TracingOptions {
|
|
|
2445
2445
|
*/
|
|
2446
2446
|
declare function withTracing<State>(node: (state: State) => State | Promise<State> | Partial<State> | Promise<Partial<State>>, options: TracingOptions): (state: State) => Promise<State | Partial<State>>;
|
|
2447
2447
|
|
|
2448
|
-
/**
|
|
2449
|
-
* Caching Middleware for LangGraph Nodes
|
|
2450
|
-
*
|
|
2451
|
-
* Provides caching capabilities with TTL, LRU eviction, and custom key generation.
|
|
2452
|
-
*/
|
|
2453
|
-
|
|
2454
2448
|
/**
|
|
2455
2449
|
* Cache key generator function
|
|
2456
2450
|
*/
|
|
@@ -2464,54 +2458,68 @@ type EvictionStrategy = 'lru' | 'lfu' | 'fifo';
|
|
|
2464
2458
|
*/
|
|
2465
2459
|
interface CachingOptions<State> {
|
|
2466
2460
|
/**
|
|
2467
|
-
* Time-to-live in milliseconds
|
|
2461
|
+
* Time-to-live in milliseconds.
|
|
2468
2462
|
* @default 3600000 (1 hour)
|
|
2469
2463
|
*/
|
|
2470
2464
|
ttl?: number;
|
|
2471
2465
|
/**
|
|
2472
|
-
* Maximum number of cache entries
|
|
2466
|
+
* Maximum number of cache entries.
|
|
2473
2467
|
* @default 100
|
|
2474
2468
|
*/
|
|
2475
2469
|
maxSize?: number;
|
|
2476
2470
|
/**
|
|
2477
|
-
* Eviction strategy when cache is full
|
|
2471
|
+
* Eviction strategy when the cache is full.
|
|
2478
2472
|
* @default 'lru'
|
|
2479
2473
|
*/
|
|
2480
2474
|
evictionStrategy?: EvictionStrategy;
|
|
2481
2475
|
/**
|
|
2482
|
-
* Custom cache key generator
|
|
2483
|
-
* @default JSON.stringify
|
|
2476
|
+
* Custom cache key generator.
|
|
2477
|
+
* @default JSON.stringify with String(...) fallback
|
|
2484
2478
|
*/
|
|
2485
2479
|
keyGenerator?: CacheKeyGenerator<State>;
|
|
2486
2480
|
/**
|
|
2487
|
-
* Whether to cache
|
|
2481
|
+
* Whether to cache thrown `Error` results as `{ error: message }`.
|
|
2488
2482
|
* @default false
|
|
2489
2483
|
*/
|
|
2490
2484
|
cacheErrors?: boolean;
|
|
2491
2485
|
/**
|
|
2492
|
-
* Optional callback when
|
|
2486
|
+
* Optional callback invoked when a fresh cached value is returned.
|
|
2493
2487
|
*/
|
|
2494
2488
|
onCacheHit?: (key: string, value: State | Partial<State>) => void;
|
|
2495
2489
|
/**
|
|
2496
|
-
* Optional callback when
|
|
2490
|
+
* Optional callback invoked when no cached value is available.
|
|
2497
2491
|
*/
|
|
2498
2492
|
onCacheMiss?: (key: string) => void;
|
|
2499
2493
|
/**
|
|
2500
|
-
* Optional callback when
|
|
2494
|
+
* Optional callback invoked when a stale cached value is evicted.
|
|
2501
2495
|
*/
|
|
2502
2496
|
onEviction?: (key: string, value: State | Partial<State>) => void;
|
|
2503
2497
|
}
|
|
2498
|
+
interface SharedCache<State> {
|
|
2499
|
+
withCache: (node: NodeFunction<State>, keyGenerator?: CacheKeyGenerator<State>) => NodeFunction<State>;
|
|
2500
|
+
clear: () => void;
|
|
2501
|
+
size: () => number;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
declare function createSharedCache<State>(options?: Omit<CachingOptions<State>, 'keyGenerator'>): SharedCache<State>;
|
|
2505
|
+
|
|
2506
|
+
/**
|
|
2507
|
+
* Caching Middleware for LangGraph Nodes
|
|
2508
|
+
*
|
|
2509
|
+
* Provides caching capabilities with TTL, LRU eviction, and custom key generation.
|
|
2510
|
+
*/
|
|
2511
|
+
|
|
2504
2512
|
/**
|
|
2505
2513
|
* Wraps a node function with caching logic.
|
|
2506
2514
|
*
|
|
2507
2515
|
* @example
|
|
2508
2516
|
* ```typescript
|
|
2509
2517
|
* const cachedNode = withCache(expensiveNode, {
|
|
2510
|
-
* ttl: 3600000,
|
|
2518
|
+
* ttl: 3600000,
|
|
2511
2519
|
* maxSize: 100,
|
|
2512
2520
|
* evictionStrategy: 'lru',
|
|
2513
2521
|
* keyGenerator: (state) => state.userId,
|
|
2514
|
-
* onCacheHit: (key) =>
|
|
2522
|
+
* onCacheHit: (key) => recordCacheHitMetric(key),
|
|
2515
2523
|
* });
|
|
2516
2524
|
*
|
|
2517
2525
|
* graph.addNode('cached', cachedNode);
|
|
@@ -2522,14 +2530,6 @@ interface CachingOptions<State> {
|
|
|
2522
2530
|
* @returns A wrapped node function with caching
|
|
2523
2531
|
*/
|
|
2524
2532
|
declare function withCache<State>(node: NodeFunction<State>, options?: CachingOptions<State>): NodeFunction<State>;
|
|
2525
|
-
/**
|
|
2526
|
-
* Create a cache instance that can be shared across multiple nodes
|
|
2527
|
-
*/
|
|
2528
|
-
declare function createSharedCache<State>(options?: Omit<CachingOptions<State>, 'keyGenerator'>): {
|
|
2529
|
-
withCache: (node: NodeFunction<State>, keyGenerator?: CacheKeyGenerator<State>) => NodeFunction<State>;
|
|
2530
|
-
clear: () => void;
|
|
2531
|
-
size: () => number;
|
|
2532
|
-
};
|
|
2533
2533
|
|
|
2534
2534
|
/**
|
|
2535
2535
|
* Rate limiting strategy
|
package/dist/index.js
CHANGED
|
@@ -2713,36 +2713,61 @@ var presets = {
|
|
|
2713
2713
|
testing
|
|
2714
2714
|
};
|
|
2715
2715
|
|
|
2716
|
-
// src/langgraph/middleware/caching.ts
|
|
2716
|
+
// src/langgraph/middleware/caching-options.ts
|
|
2717
|
+
function defaultCacheKeyGenerator(state) {
|
|
2718
|
+
try {
|
|
2719
|
+
return JSON.stringify(state);
|
|
2720
|
+
} catch {
|
|
2721
|
+
return String(state);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
function resolveCachingOptions(options) {
|
|
2725
|
+
return {
|
|
2726
|
+
ttl: options.ttl ?? 36e5,
|
|
2727
|
+
maxSize: options.maxSize ?? 100,
|
|
2728
|
+
evictionStrategy: options.evictionStrategy ?? "lru",
|
|
2729
|
+
keyGenerator: options.keyGenerator ?? defaultCacheKeyGenerator,
|
|
2730
|
+
cacheErrors: options.cacheErrors ?? false,
|
|
2731
|
+
onCacheHit: options.onCacheHit,
|
|
2732
|
+
onCacheMiss: options.onCacheMiss,
|
|
2733
|
+
onEviction: options.onEviction
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
function resolveSharedCacheKeyGenerator(keyGenerator) {
|
|
2737
|
+
return keyGenerator ?? defaultCacheKeyGenerator;
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
// src/langgraph/middleware/caching-store.ts
|
|
2717
2741
|
var LRUCache = class {
|
|
2718
|
-
cache = /* @__PURE__ */ new Map();
|
|
2719
|
-
maxSize;
|
|
2720
|
-
evictionStrategy;
|
|
2721
2742
|
constructor(maxSize, evictionStrategy = "lru") {
|
|
2722
2743
|
this.maxSize = maxSize;
|
|
2723
2744
|
this.evictionStrategy = evictionStrategy;
|
|
2724
2745
|
}
|
|
2746
|
+
cache = /* @__PURE__ */ new Map();
|
|
2725
2747
|
get(key) {
|
|
2726
2748
|
const entry = this.cache.get(key);
|
|
2727
|
-
if (!entry)
|
|
2749
|
+
if (!entry) {
|
|
2750
|
+
return void 0;
|
|
2751
|
+
}
|
|
2728
2752
|
entry.hits++;
|
|
2729
2753
|
entry.lastAccessed = Date.now();
|
|
2730
2754
|
return entry.value;
|
|
2731
2755
|
}
|
|
2756
|
+
getEntry(key) {
|
|
2757
|
+
return this.cache.get(key);
|
|
2758
|
+
}
|
|
2732
2759
|
set(key, value) {
|
|
2733
2760
|
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
2734
2761
|
this.evict();
|
|
2735
2762
|
}
|
|
2763
|
+
const now = Date.now();
|
|
2736
2764
|
this.cache.set(key, {
|
|
2737
2765
|
value,
|
|
2738
|
-
timestamp:
|
|
2766
|
+
timestamp: now,
|
|
2739
2767
|
hits: 0,
|
|
2740
|
-
lastAccessed:
|
|
2768
|
+
lastAccessed: now
|
|
2741
2769
|
});
|
|
2742
2770
|
}
|
|
2743
|
-
has(key) {
|
|
2744
|
-
return this.cache.has(key);
|
|
2745
|
-
}
|
|
2746
2771
|
delete(key) {
|
|
2747
2772
|
return this.cache.delete(key);
|
|
2748
2773
|
}
|
|
@@ -2753,138 +2778,99 @@ var LRUCache = class {
|
|
|
2753
2778
|
return this.cache.size;
|
|
2754
2779
|
}
|
|
2755
2780
|
evict() {
|
|
2756
|
-
if (this.cache.size === 0)
|
|
2757
|
-
|
|
2758
|
-
if (this.evictionStrategy === "lru") {
|
|
2759
|
-
let oldestAccess = Infinity;
|
|
2760
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
2761
|
-
if (entry.lastAccessed < oldestAccess) {
|
|
2762
|
-
oldestAccess = entry.lastAccessed;
|
|
2763
|
-
keyToEvict = key;
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
} else if (this.evictionStrategy === "lfu") {
|
|
2767
|
-
let lowestHits = Infinity;
|
|
2768
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
2769
|
-
if (entry.hits < lowestHits) {
|
|
2770
|
-
lowestHits = entry.hits;
|
|
2771
|
-
keyToEvict = key;
|
|
2772
|
-
}
|
|
2773
|
-
}
|
|
2774
|
-
} else {
|
|
2775
|
-
keyToEvict = this.cache.keys().next().value;
|
|
2781
|
+
if (this.cache.size === 0) {
|
|
2782
|
+
return;
|
|
2776
2783
|
}
|
|
2777
|
-
|
|
2784
|
+
const keyToEvict = this.findKeyToEvict();
|
|
2785
|
+
if (keyToEvict !== void 0) {
|
|
2778
2786
|
this.cache.delete(keyToEvict);
|
|
2779
2787
|
}
|
|
2780
2788
|
}
|
|
2789
|
+
findKeyToEvict() {
|
|
2790
|
+
if (this.evictionStrategy === "fifo") {
|
|
2791
|
+
return this.cache.keys().next().value;
|
|
2792
|
+
}
|
|
2793
|
+
let selectedKey;
|
|
2794
|
+
let selectedValue = Infinity;
|
|
2795
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
2796
|
+
const candidateValue = this.evictionStrategy === "lfu" ? entry.hits : entry.lastAccessed;
|
|
2797
|
+
if (candidateValue < selectedValue) {
|
|
2798
|
+
selectedValue = candidateValue;
|
|
2799
|
+
selectedKey = key;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
return selectedKey;
|
|
2803
|
+
}
|
|
2781
2804
|
};
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
return
|
|
2805
|
+
|
|
2806
|
+
// src/langgraph/middleware/caching-entry.ts
|
|
2807
|
+
function isFreshCacheEntry(entry, ttl) {
|
|
2808
|
+
if (!entry) {
|
|
2809
|
+
return false;
|
|
2787
2810
|
}
|
|
2811
|
+
return Date.now() - entry.timestamp < ttl;
|
|
2788
2812
|
}
|
|
2789
|
-
function
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
keyGenerator = defaultKeyGenerator,
|
|
2796
|
-
cacheErrors = false,
|
|
2797
|
-
onCacheHit,
|
|
2798
|
-
onCacheMiss,
|
|
2799
|
-
onEviction
|
|
2800
|
-
} = options;
|
|
2801
|
-
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
2813
|
+
function createCachedErrorResult(error) {
|
|
2814
|
+
return { error: error.message };
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
// src/langgraph/middleware/caching-wrapper.ts
|
|
2818
|
+
function createCachedNode(node, cache2, options, keyGenerator = options.keyGenerator) {
|
|
2802
2819
|
return async (state) => {
|
|
2803
2820
|
const cacheKey = keyGenerator(state);
|
|
2804
2821
|
const cachedValue = cache2.get(cacheKey);
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
if (onCacheHit) {
|
|
2810
|
-
onCacheHit(cacheKey, cachedValue);
|
|
2811
|
-
}
|
|
2812
|
-
return cachedValue;
|
|
2813
|
-
} else {
|
|
2814
|
-
cache2.delete(cacheKey);
|
|
2815
|
-
if (onEviction) {
|
|
2816
|
-
onEviction(cacheKey, cachedValue);
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2822
|
+
const entry = cache2.getEntry(cacheKey);
|
|
2823
|
+
if (cachedValue !== void 0 && isFreshCacheEntry(entry, options.ttl)) {
|
|
2824
|
+
options.onCacheHit?.(cacheKey, cachedValue);
|
|
2825
|
+
return cachedValue;
|
|
2819
2826
|
}
|
|
2820
|
-
if (
|
|
2821
|
-
|
|
2827
|
+
if (cachedValue !== void 0 && entry) {
|
|
2828
|
+
cache2.delete(cacheKey);
|
|
2829
|
+
options.onEviction?.(cacheKey, cachedValue);
|
|
2822
2830
|
}
|
|
2831
|
+
options.onCacheMiss?.(cacheKey);
|
|
2823
2832
|
try {
|
|
2824
2833
|
const result = await Promise.resolve(node(state));
|
|
2825
2834
|
cache2.set(cacheKey, result);
|
|
2826
2835
|
return result;
|
|
2827
2836
|
} catch (error) {
|
|
2828
|
-
if (cacheErrors && error instanceof Error) {
|
|
2829
|
-
|
|
2830
|
-
cache2.set(cacheKey, errorResult);
|
|
2837
|
+
if (options.cacheErrors && error instanceof Error) {
|
|
2838
|
+
cache2.set(cacheKey, createCachedErrorResult(error));
|
|
2831
2839
|
}
|
|
2832
2840
|
throw error;
|
|
2833
2841
|
}
|
|
2834
2842
|
};
|
|
2835
2843
|
}
|
|
2844
|
+
|
|
2845
|
+
// src/langgraph/middleware/caching-shared.ts
|
|
2836
2846
|
function createSharedCache(options = {}) {
|
|
2837
|
-
const
|
|
2838
|
-
|
|
2839
|
-
maxSize
|
|
2840
|
-
evictionStrategy
|
|
2841
|
-
|
|
2842
|
-
onCacheHit,
|
|
2843
|
-
onCacheMiss,
|
|
2844
|
-
onEviction
|
|
2845
|
-
} = options;
|
|
2846
|
-
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
2847
|
+
const resolvedOptions = resolveCachingOptions(options);
|
|
2848
|
+
const cache2 = new LRUCache(
|
|
2849
|
+
resolvedOptions.maxSize,
|
|
2850
|
+
resolvedOptions.evictionStrategy
|
|
2851
|
+
);
|
|
2847
2852
|
return {
|
|
2848
|
-
withCache: (node, keyGenerator
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
const age = Date.now() - entry.timestamp;
|
|
2855
|
-
if (age < ttl) {
|
|
2856
|
-
if (onCacheHit) {
|
|
2857
|
-
onCacheHit(cacheKey, cachedValue);
|
|
2858
|
-
}
|
|
2859
|
-
return cachedValue;
|
|
2860
|
-
} else {
|
|
2861
|
-
cache2.delete(cacheKey);
|
|
2862
|
-
if (onEviction) {
|
|
2863
|
-
onEviction(cacheKey, cachedValue);
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
}
|
|
2867
|
-
if (onCacheMiss) {
|
|
2868
|
-
onCacheMiss(cacheKey);
|
|
2869
|
-
}
|
|
2870
|
-
try {
|
|
2871
|
-
const result = await Promise.resolve(node(state));
|
|
2872
|
-
cache2.set(cacheKey, result);
|
|
2873
|
-
return result;
|
|
2874
|
-
} catch (error) {
|
|
2875
|
-
if (cacheErrors && error instanceof Error) {
|
|
2876
|
-
const errorResult = { error: error.message };
|
|
2877
|
-
cache2.set(cacheKey, errorResult);
|
|
2878
|
-
}
|
|
2879
|
-
throw error;
|
|
2880
|
-
}
|
|
2881
|
-
};
|
|
2882
|
-
},
|
|
2853
|
+
withCache: (node, keyGenerator) => createCachedNode(
|
|
2854
|
+
node,
|
|
2855
|
+
cache2,
|
|
2856
|
+
resolvedOptions,
|
|
2857
|
+
resolveSharedCacheKeyGenerator(keyGenerator)
|
|
2858
|
+
),
|
|
2883
2859
|
clear: () => cache2.clear(),
|
|
2884
2860
|
size: () => cache2.size()
|
|
2885
2861
|
};
|
|
2886
2862
|
}
|
|
2887
2863
|
|
|
2864
|
+
// src/langgraph/middleware/caching.ts
|
|
2865
|
+
function withCache(node, options = {}) {
|
|
2866
|
+
const resolvedOptions = resolveCachingOptions(options);
|
|
2867
|
+
const cache2 = new LRUCache(
|
|
2868
|
+
resolvedOptions.maxSize,
|
|
2869
|
+
resolvedOptions.evictionStrategy
|
|
2870
|
+
);
|
|
2871
|
+
return createCachedNode(node, cache2, resolvedOptions);
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2888
2874
|
// src/langgraph/middleware/rate-limiting.ts
|
|
2889
2875
|
var TokenBucket = class {
|
|
2890
2876
|
constructor(maxTokens, refillRate) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/core",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.55",
|
|
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",
|