@agentforge/core 0.11.6 → 0.11.8
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 +658 -2
- package/dist/index.d.cts +453 -6
- package/dist/index.d.ts +453 -6
- package/dist/index.js +646 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -91,6 +91,9 @@ __export(index_exports, {
|
|
|
91
91
|
createProgressTracker: () => createProgressTracker,
|
|
92
92
|
createSSEFormatter: () => createSSEFormatter,
|
|
93
93
|
createSequentialWorkflow: () => createSequentialWorkflow,
|
|
94
|
+
createSharedCache: () => createSharedCache,
|
|
95
|
+
createSharedConcurrencyController: () => createSharedConcurrencyController,
|
|
96
|
+
createSharedRateLimiter: () => createSharedRateLimiter,
|
|
94
97
|
createSqliteCheckpointer: () => createSqliteCheckpointer,
|
|
95
98
|
createStateAnnotation: () => createStateAnnotation,
|
|
96
99
|
createSubgraph: () => createSubgraph,
|
|
@@ -121,6 +124,7 @@ __export(index_exports, {
|
|
|
121
124
|
isHumanRequestInterrupt: () => isHumanRequestInterrupt,
|
|
122
125
|
isMemoryCheckpointer: () => isMemoryCheckpointer,
|
|
123
126
|
isTracingEnabled: () => isTracingEnabled,
|
|
127
|
+
loadPrompt: () => loadPrompt,
|
|
124
128
|
map: () => map,
|
|
125
129
|
merge: () => merge,
|
|
126
130
|
mergeState: () => mergeState,
|
|
@@ -129,8 +133,10 @@ __export(index_exports, {
|
|
|
129
133
|
presets: () => presets,
|
|
130
134
|
production: () => production,
|
|
131
135
|
reduce: () => reduce,
|
|
136
|
+
renderTemplate: () => renderTemplate,
|
|
132
137
|
retry: () => retry,
|
|
133
138
|
safeValidateSchemaDescriptions: () => safeValidateSchemaDescriptions,
|
|
139
|
+
sanitizeValue: () => sanitizeValue,
|
|
134
140
|
sendMessage: () => sendMessage,
|
|
135
141
|
sequential: () => sequential,
|
|
136
142
|
sequentialBuilder: () => sequentialBuilder,
|
|
@@ -146,11 +152,16 @@ __export(index_exports, {
|
|
|
146
152
|
validateTool: () => validateTool,
|
|
147
153
|
validateToolMetadata: () => validateToolMetadata,
|
|
148
154
|
validateToolName: () => validateToolName,
|
|
155
|
+
withCache: () => withCache,
|
|
156
|
+
withConcurrency: () => withConcurrency,
|
|
149
157
|
withErrorHandler: () => withErrorHandler,
|
|
158
|
+
withLogging: () => withLogging,
|
|
150
159
|
withMetrics: () => withMetrics,
|
|
160
|
+
withRateLimit: () => withRateLimit,
|
|
151
161
|
withRetry: () => withRetry,
|
|
152
162
|
withTimeout: () => withTimeout,
|
|
153
|
-
withTracing: () => withTracing
|
|
163
|
+
withTracing: () => withTracing,
|
|
164
|
+
withValidation: () => withValidation
|
|
154
165
|
});
|
|
155
166
|
module.exports = __toCommonJS(index_exports);
|
|
156
167
|
|
|
@@ -2854,6 +2865,578 @@ var presets = {
|
|
|
2854
2865
|
testing
|
|
2855
2866
|
};
|
|
2856
2867
|
|
|
2868
|
+
// src/langgraph/middleware/caching.ts
|
|
2869
|
+
var LRUCache = class {
|
|
2870
|
+
cache = /* @__PURE__ */ new Map();
|
|
2871
|
+
maxSize;
|
|
2872
|
+
evictionStrategy;
|
|
2873
|
+
constructor(maxSize, evictionStrategy = "lru") {
|
|
2874
|
+
this.maxSize = maxSize;
|
|
2875
|
+
this.evictionStrategy = evictionStrategy;
|
|
2876
|
+
}
|
|
2877
|
+
get(key) {
|
|
2878
|
+
const entry = this.cache.get(key);
|
|
2879
|
+
if (!entry) return void 0;
|
|
2880
|
+
entry.hits++;
|
|
2881
|
+
entry.lastAccessed = Date.now();
|
|
2882
|
+
return entry.value;
|
|
2883
|
+
}
|
|
2884
|
+
set(key, value) {
|
|
2885
|
+
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
2886
|
+
this.evict();
|
|
2887
|
+
}
|
|
2888
|
+
this.cache.set(key, {
|
|
2889
|
+
value,
|
|
2890
|
+
timestamp: Date.now(),
|
|
2891
|
+
hits: 0,
|
|
2892
|
+
lastAccessed: Date.now()
|
|
2893
|
+
});
|
|
2894
|
+
}
|
|
2895
|
+
has(key) {
|
|
2896
|
+
return this.cache.has(key);
|
|
2897
|
+
}
|
|
2898
|
+
delete(key) {
|
|
2899
|
+
return this.cache.delete(key);
|
|
2900
|
+
}
|
|
2901
|
+
clear() {
|
|
2902
|
+
this.cache.clear();
|
|
2903
|
+
}
|
|
2904
|
+
size() {
|
|
2905
|
+
return this.cache.size;
|
|
2906
|
+
}
|
|
2907
|
+
evict() {
|
|
2908
|
+
if (this.cache.size === 0) return;
|
|
2909
|
+
let keyToEvict;
|
|
2910
|
+
if (this.evictionStrategy === "lru") {
|
|
2911
|
+
let oldestAccess = Infinity;
|
|
2912
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
2913
|
+
if (entry.lastAccessed < oldestAccess) {
|
|
2914
|
+
oldestAccess = entry.lastAccessed;
|
|
2915
|
+
keyToEvict = key;
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
} else if (this.evictionStrategy === "lfu") {
|
|
2919
|
+
let lowestHits = Infinity;
|
|
2920
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
2921
|
+
if (entry.hits < lowestHits) {
|
|
2922
|
+
lowestHits = entry.hits;
|
|
2923
|
+
keyToEvict = key;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
} else {
|
|
2927
|
+
keyToEvict = this.cache.keys().next().value;
|
|
2928
|
+
}
|
|
2929
|
+
if (keyToEvict) {
|
|
2930
|
+
this.cache.delete(keyToEvict);
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
};
|
|
2934
|
+
function defaultKeyGenerator(state) {
|
|
2935
|
+
try {
|
|
2936
|
+
return JSON.stringify(state);
|
|
2937
|
+
} catch {
|
|
2938
|
+
return String(state);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
function withCache(node, options = {}) {
|
|
2942
|
+
const {
|
|
2943
|
+
ttl = 36e5,
|
|
2944
|
+
// 1 hour default
|
|
2945
|
+
maxSize = 100,
|
|
2946
|
+
evictionStrategy = "lru",
|
|
2947
|
+
keyGenerator = defaultKeyGenerator,
|
|
2948
|
+
cacheErrors = false,
|
|
2949
|
+
onCacheHit,
|
|
2950
|
+
onCacheMiss,
|
|
2951
|
+
onEviction
|
|
2952
|
+
} = options;
|
|
2953
|
+
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
2954
|
+
return async (state) => {
|
|
2955
|
+
const cacheKey = keyGenerator(state);
|
|
2956
|
+
const cachedValue = cache2.get(cacheKey);
|
|
2957
|
+
if (cachedValue !== void 0) {
|
|
2958
|
+
const entry = cache2.cache.get(cacheKey);
|
|
2959
|
+
const age = Date.now() - entry.timestamp;
|
|
2960
|
+
if (age < ttl) {
|
|
2961
|
+
if (onCacheHit) {
|
|
2962
|
+
onCacheHit(cacheKey, cachedValue);
|
|
2963
|
+
}
|
|
2964
|
+
return cachedValue;
|
|
2965
|
+
} else {
|
|
2966
|
+
cache2.delete(cacheKey);
|
|
2967
|
+
if (onEviction) {
|
|
2968
|
+
onEviction(cacheKey, cachedValue);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
if (onCacheMiss) {
|
|
2973
|
+
onCacheMiss(cacheKey);
|
|
2974
|
+
}
|
|
2975
|
+
try {
|
|
2976
|
+
const result = await Promise.resolve(node(state));
|
|
2977
|
+
cache2.set(cacheKey, result);
|
|
2978
|
+
return result;
|
|
2979
|
+
} catch (error) {
|
|
2980
|
+
if (cacheErrors && error instanceof Error) {
|
|
2981
|
+
const errorResult = { error: error.message };
|
|
2982
|
+
cache2.set(cacheKey, errorResult);
|
|
2983
|
+
}
|
|
2984
|
+
throw error;
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
}
|
|
2988
|
+
function createSharedCache(options = {}) {
|
|
2989
|
+
const {
|
|
2990
|
+
ttl = 36e5,
|
|
2991
|
+
maxSize = 100,
|
|
2992
|
+
evictionStrategy = "lru",
|
|
2993
|
+
cacheErrors = false,
|
|
2994
|
+
onCacheHit,
|
|
2995
|
+
onCacheMiss,
|
|
2996
|
+
onEviction
|
|
2997
|
+
} = options;
|
|
2998
|
+
const cache2 = new LRUCache(maxSize, evictionStrategy);
|
|
2999
|
+
return {
|
|
3000
|
+
withCache: (node, keyGenerator = defaultKeyGenerator) => {
|
|
3001
|
+
return async (state) => {
|
|
3002
|
+
const cacheKey = keyGenerator(state);
|
|
3003
|
+
const cachedValue = cache2.get(cacheKey);
|
|
3004
|
+
if (cachedValue !== void 0) {
|
|
3005
|
+
const entry = cache2.cache.get(cacheKey);
|
|
3006
|
+
const age = Date.now() - entry.timestamp;
|
|
3007
|
+
if (age < ttl) {
|
|
3008
|
+
if (onCacheHit) {
|
|
3009
|
+
onCacheHit(cacheKey, cachedValue);
|
|
3010
|
+
}
|
|
3011
|
+
return cachedValue;
|
|
3012
|
+
} else {
|
|
3013
|
+
cache2.delete(cacheKey);
|
|
3014
|
+
if (onEviction) {
|
|
3015
|
+
onEviction(cacheKey, cachedValue);
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
if (onCacheMiss) {
|
|
3020
|
+
onCacheMiss(cacheKey);
|
|
3021
|
+
}
|
|
3022
|
+
try {
|
|
3023
|
+
const result = await Promise.resolve(node(state));
|
|
3024
|
+
cache2.set(cacheKey, result);
|
|
3025
|
+
return result;
|
|
3026
|
+
} catch (error) {
|
|
3027
|
+
if (cacheErrors && error instanceof Error) {
|
|
3028
|
+
const errorResult = { error: error.message };
|
|
3029
|
+
cache2.set(cacheKey, errorResult);
|
|
3030
|
+
}
|
|
3031
|
+
throw error;
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
},
|
|
3035
|
+
clear: () => cache2.clear(),
|
|
3036
|
+
size: () => cache2.size()
|
|
3037
|
+
};
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
// src/langgraph/middleware/rate-limiting.ts
|
|
3041
|
+
var TokenBucket = class {
|
|
3042
|
+
constructor(maxTokens, refillRate) {
|
|
3043
|
+
this.maxTokens = maxTokens;
|
|
3044
|
+
this.refillRate = refillRate;
|
|
3045
|
+
this.tokens = maxTokens;
|
|
3046
|
+
this.lastRefill = Date.now();
|
|
3047
|
+
}
|
|
3048
|
+
tokens;
|
|
3049
|
+
lastRefill;
|
|
3050
|
+
tryConsume() {
|
|
3051
|
+
this.refill();
|
|
3052
|
+
if (this.tokens >= 1) {
|
|
3053
|
+
this.tokens -= 1;
|
|
3054
|
+
return true;
|
|
3055
|
+
}
|
|
3056
|
+
return false;
|
|
3057
|
+
}
|
|
3058
|
+
refill() {
|
|
3059
|
+
const now = Date.now();
|
|
3060
|
+
const timePassed = now - this.lastRefill;
|
|
3061
|
+
const tokensToAdd = timePassed * this.refillRate;
|
|
3062
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);
|
|
3063
|
+
this.lastRefill = now;
|
|
3064
|
+
}
|
|
3065
|
+
reset() {
|
|
3066
|
+
this.tokens = this.maxTokens;
|
|
3067
|
+
this.lastRefill = Date.now();
|
|
3068
|
+
}
|
|
3069
|
+
};
|
|
3070
|
+
var SlidingWindow = class {
|
|
3071
|
+
constructor(maxRequests, windowMs) {
|
|
3072
|
+
this.maxRequests = maxRequests;
|
|
3073
|
+
this.windowMs = windowMs;
|
|
3074
|
+
}
|
|
3075
|
+
requests = [];
|
|
3076
|
+
tryConsume() {
|
|
3077
|
+
const now = Date.now();
|
|
3078
|
+
this.requests = this.requests.filter((timestamp) => now - timestamp < this.windowMs);
|
|
3079
|
+
if (this.requests.length < this.maxRequests) {
|
|
3080
|
+
this.requests.push(now);
|
|
3081
|
+
return true;
|
|
3082
|
+
}
|
|
3083
|
+
return false;
|
|
3084
|
+
}
|
|
3085
|
+
reset() {
|
|
3086
|
+
this.requests = [];
|
|
3087
|
+
}
|
|
3088
|
+
};
|
|
3089
|
+
var FixedWindow = class {
|
|
3090
|
+
constructor(maxRequests, windowMs) {
|
|
3091
|
+
this.maxRequests = maxRequests;
|
|
3092
|
+
this.windowMs = windowMs;
|
|
3093
|
+
this.windowStart = Date.now();
|
|
3094
|
+
}
|
|
3095
|
+
count = 0;
|
|
3096
|
+
windowStart;
|
|
3097
|
+
tryConsume() {
|
|
3098
|
+
const now = Date.now();
|
|
3099
|
+
if (now - this.windowStart >= this.windowMs) {
|
|
3100
|
+
this.count = 0;
|
|
3101
|
+
this.windowStart = now;
|
|
3102
|
+
}
|
|
3103
|
+
if (this.count < this.maxRequests) {
|
|
3104
|
+
this.count++;
|
|
3105
|
+
return true;
|
|
3106
|
+
}
|
|
3107
|
+
return false;
|
|
3108
|
+
}
|
|
3109
|
+
reset() {
|
|
3110
|
+
this.count = 0;
|
|
3111
|
+
this.windowStart = Date.now();
|
|
3112
|
+
}
|
|
3113
|
+
};
|
|
3114
|
+
function withRateLimit(node, options) {
|
|
3115
|
+
const {
|
|
3116
|
+
maxRequests,
|
|
3117
|
+
windowMs,
|
|
3118
|
+
strategy = "token-bucket",
|
|
3119
|
+
onRateLimitExceeded,
|
|
3120
|
+
onRateLimitReset,
|
|
3121
|
+
keyGenerator = () => "global"
|
|
3122
|
+
} = options;
|
|
3123
|
+
const limiters = /* @__PURE__ */ new Map();
|
|
3124
|
+
return async (state) => {
|
|
3125
|
+
const key = keyGenerator(state);
|
|
3126
|
+
if (!limiters.has(key)) {
|
|
3127
|
+
let limiter2;
|
|
3128
|
+
switch (strategy) {
|
|
3129
|
+
case "token-bucket":
|
|
3130
|
+
limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
|
|
3131
|
+
break;
|
|
3132
|
+
case "sliding-window":
|
|
3133
|
+
limiter2 = new SlidingWindow(maxRequests, windowMs);
|
|
3134
|
+
break;
|
|
3135
|
+
case "fixed-window":
|
|
3136
|
+
limiter2 = new FixedWindow(maxRequests, windowMs);
|
|
3137
|
+
break;
|
|
3138
|
+
default:
|
|
3139
|
+
throw new Error(`Unknown rate limit strategy: ${strategy}`);
|
|
3140
|
+
}
|
|
3141
|
+
limiters.set(key, limiter2);
|
|
3142
|
+
}
|
|
3143
|
+
const limiter = limiters.get(key);
|
|
3144
|
+
if (!limiter.tryConsume()) {
|
|
3145
|
+
if (onRateLimitExceeded) {
|
|
3146
|
+
onRateLimitExceeded(key);
|
|
3147
|
+
}
|
|
3148
|
+
throw new Error(`Rate limit exceeded for key: ${key}`);
|
|
3149
|
+
}
|
|
3150
|
+
return await Promise.resolve(node(state));
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
function createSharedRateLimiter(options) {
|
|
3154
|
+
const {
|
|
3155
|
+
maxRequests,
|
|
3156
|
+
windowMs,
|
|
3157
|
+
strategy = "token-bucket",
|
|
3158
|
+
onRateLimitExceeded,
|
|
3159
|
+
onRateLimitReset
|
|
3160
|
+
} = options;
|
|
3161
|
+
const limiters = /* @__PURE__ */ new Map();
|
|
3162
|
+
return {
|
|
3163
|
+
withRateLimit: (node, keyGenerator = (state) => "global") => {
|
|
3164
|
+
return async (state) => {
|
|
3165
|
+
const key = keyGenerator(state);
|
|
3166
|
+
if (!limiters.has(key)) {
|
|
3167
|
+
let limiter2;
|
|
3168
|
+
switch (strategy) {
|
|
3169
|
+
case "token-bucket":
|
|
3170
|
+
limiter2 = new TokenBucket(maxRequests, maxRequests / windowMs);
|
|
3171
|
+
break;
|
|
3172
|
+
case "sliding-window":
|
|
3173
|
+
limiter2 = new SlidingWindow(maxRequests, windowMs);
|
|
3174
|
+
break;
|
|
3175
|
+
case "fixed-window":
|
|
3176
|
+
limiter2 = new FixedWindow(maxRequests, windowMs);
|
|
3177
|
+
break;
|
|
3178
|
+
default:
|
|
3179
|
+
throw new Error(`Unknown rate limit strategy: ${strategy}`);
|
|
3180
|
+
}
|
|
3181
|
+
limiters.set(key, limiter2);
|
|
3182
|
+
}
|
|
3183
|
+
const limiter = limiters.get(key);
|
|
3184
|
+
if (!limiter.tryConsume()) {
|
|
3185
|
+
if (onRateLimitExceeded) {
|
|
3186
|
+
onRateLimitExceeded(key);
|
|
3187
|
+
}
|
|
3188
|
+
throw new Error(`Rate limit exceeded for key: ${key}`);
|
|
3189
|
+
}
|
|
3190
|
+
return await Promise.resolve(node(state));
|
|
3191
|
+
};
|
|
3192
|
+
},
|
|
3193
|
+
reset: (key) => {
|
|
3194
|
+
if (key) {
|
|
3195
|
+
const limiter = limiters.get(key);
|
|
3196
|
+
if (limiter) {
|
|
3197
|
+
limiter.reset();
|
|
3198
|
+
if (onRateLimitReset) {
|
|
3199
|
+
onRateLimitReset(key);
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
} else {
|
|
3203
|
+
limiters.forEach((limiter, k) => {
|
|
3204
|
+
limiter.reset();
|
|
3205
|
+
if (onRateLimitReset) {
|
|
3206
|
+
onRateLimitReset(k);
|
|
3207
|
+
}
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
};
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/langgraph/middleware/validation.ts
|
|
3215
|
+
function withValidation(node, options) {
|
|
3216
|
+
const {
|
|
3217
|
+
inputSchema,
|
|
3218
|
+
outputSchema,
|
|
3219
|
+
inputValidator,
|
|
3220
|
+
outputValidator,
|
|
3221
|
+
mode = "both",
|
|
3222
|
+
throwOnError = true,
|
|
3223
|
+
onValidationError,
|
|
3224
|
+
onValidationSuccess,
|
|
3225
|
+
stripUnknown = false
|
|
3226
|
+
} = options;
|
|
3227
|
+
return async (state) => {
|
|
3228
|
+
if (mode === "input" || mode === "both") {
|
|
3229
|
+
try {
|
|
3230
|
+
if (inputSchema) {
|
|
3231
|
+
const validated = inputSchema.parse(state);
|
|
3232
|
+
state = validated;
|
|
3233
|
+
}
|
|
3234
|
+
if (inputValidator) {
|
|
3235
|
+
const isValid = await Promise.resolve(inputValidator(state));
|
|
3236
|
+
if (!isValid) {
|
|
3237
|
+
throw new Error("Input validation failed: custom validator returned false");
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
if (onValidationSuccess) {
|
|
3241
|
+
onValidationSuccess(state, "input");
|
|
3242
|
+
}
|
|
3243
|
+
} catch (error) {
|
|
3244
|
+
if (onValidationError) {
|
|
3245
|
+
return onValidationError(error, state, "input");
|
|
3246
|
+
}
|
|
3247
|
+
if (throwOnError) {
|
|
3248
|
+
throw error;
|
|
3249
|
+
}
|
|
3250
|
+
return state;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
const result = await Promise.resolve(node(state));
|
|
3254
|
+
if (mode === "output" || mode === "both") {
|
|
3255
|
+
try {
|
|
3256
|
+
if (outputSchema) {
|
|
3257
|
+
const validated = outputSchema.parse(result);
|
|
3258
|
+
if (onValidationSuccess) {
|
|
3259
|
+
onValidationSuccess(validated, "output");
|
|
3260
|
+
}
|
|
3261
|
+
return validated;
|
|
3262
|
+
}
|
|
3263
|
+
if (outputValidator) {
|
|
3264
|
+
const isValid = await Promise.resolve(outputValidator(result));
|
|
3265
|
+
if (!isValid) {
|
|
3266
|
+
throw new Error("Output validation failed: custom validator returned false");
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
if (onValidationSuccess) {
|
|
3270
|
+
onValidationSuccess(result, "output");
|
|
3271
|
+
}
|
|
3272
|
+
} catch (error) {
|
|
3273
|
+
if (onValidationError) {
|
|
3274
|
+
return onValidationError(error, state, "output");
|
|
3275
|
+
}
|
|
3276
|
+
if (throwOnError) {
|
|
3277
|
+
throw error;
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
return result;
|
|
3282
|
+
};
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
// src/langgraph/middleware/concurrency.ts
|
|
3286
|
+
var ConcurrencyController = class {
|
|
3287
|
+
constructor(maxConcurrent, maxQueueSize, onQueued, onExecutionStart, onExecutionComplete, onQueueFull, queueTimeout) {
|
|
3288
|
+
this.maxConcurrent = maxConcurrent;
|
|
3289
|
+
this.maxQueueSize = maxQueueSize;
|
|
3290
|
+
this.onQueued = onQueued;
|
|
3291
|
+
this.onExecutionStart = onExecutionStart;
|
|
3292
|
+
this.onExecutionComplete = onExecutionComplete;
|
|
3293
|
+
this.onQueueFull = onQueueFull;
|
|
3294
|
+
this.queueTimeout = queueTimeout;
|
|
3295
|
+
}
|
|
3296
|
+
activeCount = 0;
|
|
3297
|
+
queue = [];
|
|
3298
|
+
async execute(state, priority, executor) {
|
|
3299
|
+
if (this.activeCount < this.maxConcurrent) {
|
|
3300
|
+
return this.executeTask(state, executor);
|
|
3301
|
+
}
|
|
3302
|
+
if (this.maxQueueSize > 0 && this.queue.length >= this.maxQueueSize) {
|
|
3303
|
+
if (this.onQueueFull) {
|
|
3304
|
+
this.onQueueFull(state);
|
|
3305
|
+
}
|
|
3306
|
+
throw new Error(`Queue is full (max size: ${this.maxQueueSize})`);
|
|
3307
|
+
}
|
|
3308
|
+
return new Promise((resolve, reject) => {
|
|
3309
|
+
const task = {
|
|
3310
|
+
state,
|
|
3311
|
+
priority,
|
|
3312
|
+
executor,
|
|
3313
|
+
resolve,
|
|
3314
|
+
reject,
|
|
3315
|
+
timestamp: Date.now()
|
|
3316
|
+
};
|
|
3317
|
+
this.insertByPriority(task);
|
|
3318
|
+
if (this.onQueued) {
|
|
3319
|
+
this.onQueued(this.queue.length, state);
|
|
3320
|
+
}
|
|
3321
|
+
if (this.queueTimeout && this.queueTimeout > 0) {
|
|
3322
|
+
setTimeout(() => {
|
|
3323
|
+
const index = this.queue.indexOf(task);
|
|
3324
|
+
if (index !== -1) {
|
|
3325
|
+
this.queue.splice(index, 1);
|
|
3326
|
+
reject(new Error(`Task timed out after ${this.queueTimeout}ms in queue`));
|
|
3327
|
+
}
|
|
3328
|
+
}, this.queueTimeout);
|
|
3329
|
+
}
|
|
3330
|
+
});
|
|
3331
|
+
}
|
|
3332
|
+
insertByPriority(task) {
|
|
3333
|
+
const priorityOrder = { high: 0, normal: 1, low: 2 };
|
|
3334
|
+
const taskPriorityValue = priorityOrder[task.priority];
|
|
3335
|
+
let insertIndex = this.queue.length;
|
|
3336
|
+
for (let i = 0; i < this.queue.length; i++) {
|
|
3337
|
+
const queuedPriorityValue = priorityOrder[this.queue[i].priority];
|
|
3338
|
+
if (taskPriorityValue < queuedPriorityValue) {
|
|
3339
|
+
insertIndex = i;
|
|
3340
|
+
break;
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
this.queue.splice(insertIndex, 0, task);
|
|
3344
|
+
}
|
|
3345
|
+
async executeTask(state, executor) {
|
|
3346
|
+
this.activeCount++;
|
|
3347
|
+
if (this.onExecutionStart) {
|
|
3348
|
+
this.onExecutionStart(this.activeCount, state);
|
|
3349
|
+
}
|
|
3350
|
+
try {
|
|
3351
|
+
const result = await executor(state);
|
|
3352
|
+
if (this.onExecutionComplete) {
|
|
3353
|
+
this.onExecutionComplete(this.activeCount - 1, state);
|
|
3354
|
+
}
|
|
3355
|
+
return result;
|
|
3356
|
+
} finally {
|
|
3357
|
+
this.activeCount--;
|
|
3358
|
+
this.processQueue();
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
processQueue() {
|
|
3362
|
+
if (this.queue.length === 0 || this.activeCount >= this.maxConcurrent) {
|
|
3363
|
+
return;
|
|
3364
|
+
}
|
|
3365
|
+
const task = this.queue.shift();
|
|
3366
|
+
if (task) {
|
|
3367
|
+
this.executeTask(task.state, task.executor).then(task.resolve).catch(task.reject);
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
getStats() {
|
|
3371
|
+
return {
|
|
3372
|
+
activeCount: this.activeCount,
|
|
3373
|
+
queueSize: this.queue.length
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
clear() {
|
|
3377
|
+
this.queue.forEach((task) => {
|
|
3378
|
+
task.reject(new Error("Queue cleared"));
|
|
3379
|
+
});
|
|
3380
|
+
this.queue = [];
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
function withConcurrency(node, options = {}) {
|
|
3384
|
+
const {
|
|
3385
|
+
maxConcurrent = 1,
|
|
3386
|
+
maxQueueSize = 0,
|
|
3387
|
+
priorityFn = () => "normal",
|
|
3388
|
+
onQueued,
|
|
3389
|
+
onExecutionStart,
|
|
3390
|
+
onExecutionComplete,
|
|
3391
|
+
onQueueFull,
|
|
3392
|
+
queueTimeout = 0
|
|
3393
|
+
} = options;
|
|
3394
|
+
const controller = new ConcurrencyController(
|
|
3395
|
+
maxConcurrent,
|
|
3396
|
+
maxQueueSize,
|
|
3397
|
+
onQueued,
|
|
3398
|
+
onExecutionStart,
|
|
3399
|
+
onExecutionComplete,
|
|
3400
|
+
onQueueFull,
|
|
3401
|
+
queueTimeout
|
|
3402
|
+
);
|
|
3403
|
+
return async (state) => {
|
|
3404
|
+
const priority = priorityFn(state);
|
|
3405
|
+
return controller.execute(state, priority, async (s) => await node(s));
|
|
3406
|
+
};
|
|
3407
|
+
}
|
|
3408
|
+
function createSharedConcurrencyController(options = {}) {
|
|
3409
|
+
const {
|
|
3410
|
+
maxConcurrent = 1,
|
|
3411
|
+
maxQueueSize = 0,
|
|
3412
|
+
priorityFn = () => "normal",
|
|
3413
|
+
onQueued,
|
|
3414
|
+
onExecutionStart,
|
|
3415
|
+
onExecutionComplete,
|
|
3416
|
+
onQueueFull,
|
|
3417
|
+
queueTimeout = 0
|
|
3418
|
+
} = options;
|
|
3419
|
+
const controller = new ConcurrencyController(
|
|
3420
|
+
maxConcurrent,
|
|
3421
|
+
maxQueueSize,
|
|
3422
|
+
onQueued,
|
|
3423
|
+
onExecutionStart,
|
|
3424
|
+
onExecutionComplete,
|
|
3425
|
+
onQueueFull,
|
|
3426
|
+
queueTimeout
|
|
3427
|
+
);
|
|
3428
|
+
return {
|
|
3429
|
+
withConcurrency: (node) => {
|
|
3430
|
+
return async (state) => {
|
|
3431
|
+
const priority = priorityFn(state);
|
|
3432
|
+
return controller.execute(state, priority, async (s) => await node(s));
|
|
3433
|
+
};
|
|
3434
|
+
},
|
|
3435
|
+
getStats: () => controller.getStats(),
|
|
3436
|
+
clear: () => controller.clear()
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3439
|
+
|
|
2857
3440
|
// src/langgraph/persistence/checkpointer.ts
|
|
2858
3441
|
var import_langgraph5 = require("@langchain/langgraph");
|
|
2859
3442
|
function createMemoryCheckpointer(options) {
|
|
@@ -4350,6 +4933,68 @@ var CircuitBreaker = class {
|
|
|
4350
4933
|
function createCircuitBreaker(options) {
|
|
4351
4934
|
return new CircuitBreaker(options);
|
|
4352
4935
|
}
|
|
4936
|
+
|
|
4937
|
+
// src/prompt-loader/index.ts
|
|
4938
|
+
var import_fs = require("fs");
|
|
4939
|
+
var import_path = require("path");
|
|
4940
|
+
var MAX_VARIABLE_LENGTH = 500;
|
|
4941
|
+
function sanitizeValue(value) {
|
|
4942
|
+
if (value === void 0 || value === null) return "";
|
|
4943
|
+
let sanitized = String(value);
|
|
4944
|
+
sanitized = sanitized.replace(/^#+\s*/gm, "");
|
|
4945
|
+
sanitized = sanitized.replace(/[\r\n]+/g, " ");
|
|
4946
|
+
sanitized = sanitized.trim().replace(/\s+/g, " ");
|
|
4947
|
+
if (sanitized.length > MAX_VARIABLE_LENGTH) {
|
|
4948
|
+
sanitized = sanitized.substring(0, MAX_VARIABLE_LENGTH) + "...";
|
|
4949
|
+
}
|
|
4950
|
+
return sanitized;
|
|
4951
|
+
}
|
|
4952
|
+
function renderTemplate(template, options) {
|
|
4953
|
+
let rawVariables;
|
|
4954
|
+
let sanitizedVariables;
|
|
4955
|
+
if ("trustedVariables" in options || "untrustedVariables" in options) {
|
|
4956
|
+
const opts = options;
|
|
4957
|
+
rawVariables = {
|
|
4958
|
+
...opts.trustedVariables,
|
|
4959
|
+
...opts.untrustedVariables
|
|
4960
|
+
};
|
|
4961
|
+
const sanitizedUntrusted = {};
|
|
4962
|
+
if (opts.untrustedVariables) {
|
|
4963
|
+
for (const [key, value] of Object.entries(opts.untrustedVariables)) {
|
|
4964
|
+
sanitizedUntrusted[key] = sanitizeValue(value);
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
sanitizedVariables = {
|
|
4968
|
+
...opts.trustedVariables,
|
|
4969
|
+
...sanitizedUntrusted
|
|
4970
|
+
};
|
|
4971
|
+
} else {
|
|
4972
|
+
rawVariables = options;
|
|
4973
|
+
sanitizedVariables = options;
|
|
4974
|
+
}
|
|
4975
|
+
let result = template;
|
|
4976
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, varName, content) => {
|
|
4977
|
+
return rawVariables[varName] ? content : "";
|
|
4978
|
+
});
|
|
4979
|
+
result = result.replace(/\{\{(\w+)\}\}/g, (_, varName) => {
|
|
4980
|
+
const value = sanitizedVariables[varName];
|
|
4981
|
+
if (value === void 0 || value === null) return "";
|
|
4982
|
+
return String(value);
|
|
4983
|
+
});
|
|
4984
|
+
return result;
|
|
4985
|
+
}
|
|
4986
|
+
function loadPrompt(promptName, options = {}, promptsDir) {
|
|
4987
|
+
const baseDir = promptsDir || (0, import_path.join)(process.cwd(), "prompts");
|
|
4988
|
+
const promptPath = (0, import_path.join)(baseDir, `${promptName}.md`);
|
|
4989
|
+
try {
|
|
4990
|
+
const template = (0, import_fs.readFileSync)(promptPath, "utf-8");
|
|
4991
|
+
return renderTemplate(template, options);
|
|
4992
|
+
} catch (error) {
|
|
4993
|
+
throw new Error(
|
|
4994
|
+
`Failed to load prompt "${promptName}" from ${promptPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
4995
|
+
);
|
|
4996
|
+
}
|
|
4997
|
+
}
|
|
4353
4998
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4354
4999
|
0 && (module.exports = {
|
|
4355
5000
|
AgentError,
|
|
@@ -4413,6 +5058,9 @@ function createCircuitBreaker(options) {
|
|
|
4413
5058
|
createProgressTracker,
|
|
4414
5059
|
createSSEFormatter,
|
|
4415
5060
|
createSequentialWorkflow,
|
|
5061
|
+
createSharedCache,
|
|
5062
|
+
createSharedConcurrencyController,
|
|
5063
|
+
createSharedRateLimiter,
|
|
4416
5064
|
createSqliteCheckpointer,
|
|
4417
5065
|
createStateAnnotation,
|
|
4418
5066
|
createSubgraph,
|
|
@@ -4443,6 +5091,7 @@ function createCircuitBreaker(options) {
|
|
|
4443
5091
|
isHumanRequestInterrupt,
|
|
4444
5092
|
isMemoryCheckpointer,
|
|
4445
5093
|
isTracingEnabled,
|
|
5094
|
+
loadPrompt,
|
|
4446
5095
|
map,
|
|
4447
5096
|
merge,
|
|
4448
5097
|
mergeState,
|
|
@@ -4451,8 +5100,10 @@ function createCircuitBreaker(options) {
|
|
|
4451
5100
|
presets,
|
|
4452
5101
|
production,
|
|
4453
5102
|
reduce,
|
|
5103
|
+
renderTemplate,
|
|
4454
5104
|
retry,
|
|
4455
5105
|
safeValidateSchemaDescriptions,
|
|
5106
|
+
sanitizeValue,
|
|
4456
5107
|
sendMessage,
|
|
4457
5108
|
sequential,
|
|
4458
5109
|
sequentialBuilder,
|
|
@@ -4468,9 +5119,14 @@ function createCircuitBreaker(options) {
|
|
|
4468
5119
|
validateTool,
|
|
4469
5120
|
validateToolMetadata,
|
|
4470
5121
|
validateToolName,
|
|
5122
|
+
withCache,
|
|
5123
|
+
withConcurrency,
|
|
4471
5124
|
withErrorHandler,
|
|
5125
|
+
withLogging,
|
|
4472
5126
|
withMetrics,
|
|
5127
|
+
withRateLimit,
|
|
4473
5128
|
withRetry,
|
|
4474
5129
|
withTimeout,
|
|
4475
|
-
withTracing
|
|
5130
|
+
withTracing,
|
|
5131
|
+
withValidation
|
|
4476
5132
|
});
|