@agentforge/core 0.16.51 → 0.16.53
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 +360 -211
- package/dist/index.d.cts +21 -87
- package/dist/index.d.ts +21 -87
- package/dist/index.js +360 -211
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1351,7 +1351,7 @@ function toError(error) {
|
|
|
1351
1351
|
}
|
|
1352
1352
|
return new Error(String(error));
|
|
1353
1353
|
}
|
|
1354
|
-
function resolveExecutionMethod(tool,
|
|
1354
|
+
function resolveExecutionMethod(tool, logger7) {
|
|
1355
1355
|
const executeFn = tool.invoke || tool.execute;
|
|
1356
1356
|
if (!executeFn) {
|
|
1357
1357
|
throw new Error(
|
|
@@ -1359,14 +1359,14 @@ function resolveExecutionMethod(tool, logger6) {
|
|
|
1359
1359
|
);
|
|
1360
1360
|
}
|
|
1361
1361
|
if (!tool.invoke && tool.execute) {
|
|
1362
|
-
|
|
1362
|
+
logger7.warn(
|
|
1363
1363
|
`Tool "${tool.metadata?.name ?? tool.name ?? "unknown"}" only implements execute() which is deprecated. Please update to implement invoke() as the primary method. execute() will be removed in v1.0.0.`
|
|
1364
1364
|
);
|
|
1365
1365
|
}
|
|
1366
1366
|
return executeFn;
|
|
1367
1367
|
}
|
|
1368
|
-
async function executeWithRetry(tool, input, policy,
|
|
1369
|
-
const executeFn = resolveExecutionMethod(tool,
|
|
1368
|
+
async function executeWithRetry(tool, input, policy, logger7) {
|
|
1369
|
+
const executeFn = resolveExecutionMethod(tool, logger7);
|
|
1370
1370
|
if (!policy) {
|
|
1371
1371
|
return await executeFn.call(tool, input);
|
|
1372
1372
|
}
|
|
@@ -1645,7 +1645,7 @@ async function performManagedCleanup({
|
|
|
1645
1645
|
function ensureManagedBeforeExitHandler({
|
|
1646
1646
|
autoCleanup,
|
|
1647
1647
|
cleanup,
|
|
1648
|
-
logger:
|
|
1648
|
+
logger: logger7,
|
|
1649
1649
|
name,
|
|
1650
1650
|
state
|
|
1651
1651
|
}) {
|
|
@@ -1654,7 +1654,7 @@ function ensureManagedBeforeExitHandler({
|
|
|
1654
1654
|
}
|
|
1655
1655
|
state.beforeExitHandler = () => {
|
|
1656
1656
|
cleanup().catch(
|
|
1657
|
-
(err) =>
|
|
1657
|
+
(err) => logger7.error("Cleanup failed", {
|
|
1658
1658
|
toolName: name,
|
|
1659
1659
|
error: getErrorMessage(err),
|
|
1660
1660
|
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
@@ -2107,8 +2107,10 @@ function createToolSimulator(config) {
|
|
|
2107
2107
|
};
|
|
2108
2108
|
}
|
|
2109
2109
|
|
|
2110
|
-
// src/langgraph/state.ts
|
|
2110
|
+
// src/langgraph/state-annotation.ts
|
|
2111
2111
|
var import_langgraph = require("@langchain/langgraph");
|
|
2112
|
+
|
|
2113
|
+
// src/langgraph/state-shared.ts
|
|
2112
2114
|
function entriesOf(value) {
|
|
2113
2115
|
return Object.entries(value);
|
|
2114
2116
|
}
|
|
@@ -2127,6 +2129,8 @@ function setStateValue(target, key, value) {
|
|
|
2127
2129
|
function setStateDefinitionValue(target, key, value) {
|
|
2128
2130
|
target[key] = value;
|
|
2129
2131
|
}
|
|
2132
|
+
|
|
2133
|
+
// src/langgraph/state-annotation.ts
|
|
2130
2134
|
function createChannel(channelConfig) {
|
|
2131
2135
|
if (channelConfig.reducer) {
|
|
2132
2136
|
return (0, import_langgraph.Annotation)({
|
|
@@ -2153,6 +2157,8 @@ function createStateAnnotation(config) {
|
|
|
2153
2157
|
}
|
|
2154
2158
|
return import_langgraph.Annotation.Root(stateDefinition);
|
|
2155
2159
|
}
|
|
2160
|
+
|
|
2161
|
+
// src/langgraph/state-validation.ts
|
|
2156
2162
|
function validateState(state, config) {
|
|
2157
2163
|
const validated = {};
|
|
2158
2164
|
for (const [key, channelConfig] of entriesOf(config)) {
|
|
@@ -2170,6 +2176,8 @@ function validateState(state, config) {
|
|
|
2170
2176
|
}
|
|
2171
2177
|
return validated;
|
|
2172
2178
|
}
|
|
2179
|
+
|
|
2180
|
+
// src/langgraph/state-merge.ts
|
|
2173
2181
|
function mergeState(currentState, update, config) {
|
|
2174
2182
|
const merged = { ...currentState };
|
|
2175
2183
|
for (const key of keysOf(update)) {
|
|
@@ -2617,14 +2625,14 @@ var withLogging = (options) => {
|
|
|
2617
2625
|
onComplete,
|
|
2618
2626
|
onError
|
|
2619
2627
|
} = options;
|
|
2620
|
-
const
|
|
2628
|
+
const logger7 = providedLogger || createLogger(name, { level });
|
|
2621
2629
|
return (node) => {
|
|
2622
2630
|
return async (state) => {
|
|
2623
2631
|
const startTime = Date.now();
|
|
2624
2632
|
try {
|
|
2625
2633
|
if (logInput) {
|
|
2626
2634
|
const data = extractData ? extractData(state) : { state };
|
|
2627
|
-
|
|
2635
|
+
logger7.info("Node execution started", data);
|
|
2628
2636
|
}
|
|
2629
2637
|
if (onStart) {
|
|
2630
2638
|
onStart(state);
|
|
@@ -2634,9 +2642,9 @@ var withLogging = (options) => {
|
|
|
2634
2642
|
if (logOutput) {
|
|
2635
2643
|
const data = extractData ? extractData(result) : { result };
|
|
2636
2644
|
if (logDuration) {
|
|
2637
|
-
|
|
2645
|
+
logger7.info(`Node execution completed (${duration}ms)`, data);
|
|
2638
2646
|
} else {
|
|
2639
|
-
|
|
2647
|
+
logger7.info("Node execution completed", data);
|
|
2640
2648
|
}
|
|
2641
2649
|
}
|
|
2642
2650
|
if (onComplete) {
|
|
@@ -2647,7 +2655,7 @@ var withLogging = (options) => {
|
|
|
2647
2655
|
const duration = Date.now() - startTime;
|
|
2648
2656
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2649
2657
|
if (logErrors) {
|
|
2650
|
-
|
|
2658
|
+
logger7.error(`Node execution failed (${duration}ms)`, {
|
|
2651
2659
|
error: err.message,
|
|
2652
2660
|
...err.stack ? { stack: err.stack } : {}
|
|
2653
2661
|
});
|
|
@@ -2769,7 +2777,7 @@ function withLogging2(options) {
|
|
|
2769
2777
|
function production(node, options) {
|
|
2770
2778
|
const {
|
|
2771
2779
|
nodeName,
|
|
2772
|
-
logger:
|
|
2780
|
+
logger: logger7,
|
|
2773
2781
|
enableMetrics = true,
|
|
2774
2782
|
enableTracing = true,
|
|
2775
2783
|
enableRetry = true,
|
|
@@ -2777,7 +2785,7 @@ function production(node, options) {
|
|
|
2777
2785
|
retryOptions = {},
|
|
2778
2786
|
errorOptions = {}
|
|
2779
2787
|
} = options;
|
|
2780
|
-
const actualLogger =
|
|
2788
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2781
2789
|
const middleware = [
|
|
2782
2790
|
withLogging2({
|
|
2783
2791
|
logger: actualLogger,
|
|
@@ -2832,8 +2840,8 @@ function production(node, options) {
|
|
|
2832
2840
|
|
|
2833
2841
|
// src/langgraph/middleware/preset-development.ts
|
|
2834
2842
|
function development(node, options) {
|
|
2835
|
-
const { nodeName, verbose = true, logger:
|
|
2836
|
-
const actualLogger =
|
|
2843
|
+
const { nodeName, verbose = true, logger: logger7 } = options;
|
|
2844
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2837
2845
|
return withLogging2({
|
|
2838
2846
|
logger: actualLogger,
|
|
2839
2847
|
name: nodeName,
|
|
@@ -4240,37 +4248,9 @@ function createMessage(type, data, error) {
|
|
|
4240
4248
|
return { type, data, error };
|
|
4241
4249
|
}
|
|
4242
4250
|
|
|
4243
|
-
// src/resources/pool.ts
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
this.options = options;
|
|
4247
|
-
const poolConfig = options.pool || {};
|
|
4248
|
-
const min = poolConfig.min || 0;
|
|
4249
|
-
if (min > 0) {
|
|
4250
|
-
this.initialize(min).catch((error) => {
|
|
4251
|
-
console.error("Failed to initialize pool:", error);
|
|
4252
|
-
});
|
|
4253
|
-
}
|
|
4254
|
-
const evictionInterval = poolConfig.evictionInterval || 6e4;
|
|
4255
|
-
this.evictionTimer = setInterval(() => {
|
|
4256
|
-
this.evictIdleConnections().catch((error) => {
|
|
4257
|
-
console.error("Failed to evict idle connections:", error);
|
|
4258
|
-
});
|
|
4259
|
-
}, evictionInterval);
|
|
4260
|
-
const healthCheck = options.healthCheck || {};
|
|
4261
|
-
if (healthCheck.enabled) {
|
|
4262
|
-
const interval = healthCheck.interval || 3e4;
|
|
4263
|
-
this.healthCheckTimer = setInterval(() => {
|
|
4264
|
-
this.performHealthChecks().catch((error) => {
|
|
4265
|
-
console.error("Health check failed:", error);
|
|
4266
|
-
options.onHealthCheckFail?.(error);
|
|
4267
|
-
});
|
|
4268
|
-
}, interval);
|
|
4269
|
-
}
|
|
4270
|
-
}
|
|
4271
|
-
connections = [];
|
|
4272
|
-
pending = [];
|
|
4273
|
-
stats = {
|
|
4251
|
+
// src/resources/pool-runtime.ts
|
|
4252
|
+
function createInitialPoolStats() {
|
|
4253
|
+
return {
|
|
4274
4254
|
size: 0,
|
|
4275
4255
|
available: 0,
|
|
4276
4256
|
pending: 0,
|
|
@@ -4280,178 +4260,347 @@ var ConnectionPool = class {
|
|
|
4280
4260
|
healthChecksPassed: 0,
|
|
4281
4261
|
healthChecksFailed: 0
|
|
4282
4262
|
};
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
async
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
this.stats.available++;
|
|
4301
|
-
return connection;
|
|
4302
|
-
}
|
|
4303
|
-
async destroyConnection(pooled) {
|
|
4304
|
-
const index = this.connections.indexOf(pooled);
|
|
4305
|
-
if (index !== -1) {
|
|
4306
|
-
this.connections.splice(index, 1);
|
|
4307
|
-
}
|
|
4308
|
-
if (this.options.destroyer) {
|
|
4309
|
-
await this.options.destroyer(pooled.connection);
|
|
4310
|
-
}
|
|
4311
|
-
this.options.onDestroy?.(pooled.connection);
|
|
4312
|
-
this.stats.destroyed++;
|
|
4313
|
-
this.stats.size--;
|
|
4314
|
-
if (!pooled.inUse) {
|
|
4315
|
-
this.stats.available--;
|
|
4263
|
+
}
|
|
4264
|
+
async function initializeConnections(runtime, count) {
|
|
4265
|
+
runtime.creating += count;
|
|
4266
|
+
const promises = Array.from({ length: count }, async () => {
|
|
4267
|
+
try {
|
|
4268
|
+
const connection = await createConnection(runtime);
|
|
4269
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4270
|
+
if (!pooled) {
|
|
4271
|
+
throw new Error("Newly created connection not found in pool");
|
|
4272
|
+
}
|
|
4273
|
+
if (runtime.draining) {
|
|
4274
|
+
await destroyConnection(runtime, pooled);
|
|
4275
|
+
return;
|
|
4276
|
+
}
|
|
4277
|
+
assignConnectionToPendingAcquire(runtime, connection);
|
|
4278
|
+
} finally {
|
|
4279
|
+
runtime.creating--;
|
|
4316
4280
|
}
|
|
4281
|
+
});
|
|
4282
|
+
await Promise.all(promises);
|
|
4283
|
+
}
|
|
4284
|
+
function assignConnectionToPendingAcquire(runtime, connection) {
|
|
4285
|
+
const pending = runtime.pending.shift();
|
|
4286
|
+
if (!pending) {
|
|
4287
|
+
return;
|
|
4317
4288
|
}
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4289
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4290
|
+
if (!pooled) {
|
|
4291
|
+
runtime.pending.unshift(pending);
|
|
4292
|
+
return;
|
|
4293
|
+
}
|
|
4294
|
+
clearTimeout(pending.timeout);
|
|
4295
|
+
runtime.stats.pending--;
|
|
4296
|
+
pooled.inUse = true;
|
|
4297
|
+
pooled.lastUsedAt = Date.now();
|
|
4298
|
+
runtime.stats.available--;
|
|
4299
|
+
runtime.stats.acquired++;
|
|
4300
|
+
runtime.options.onAcquire?.(connection);
|
|
4301
|
+
pending.resolve(connection);
|
|
4302
|
+
}
|
|
4303
|
+
async function createConnection(runtime) {
|
|
4304
|
+
const connection = await runtime.options.factory();
|
|
4305
|
+
const now = Date.now();
|
|
4306
|
+
runtime.connections.push({
|
|
4307
|
+
connection,
|
|
4308
|
+
createdAt: now,
|
|
4309
|
+
lastUsedAt: now,
|
|
4310
|
+
inUse: false
|
|
4311
|
+
});
|
|
4312
|
+
runtime.stats.created++;
|
|
4313
|
+
runtime.stats.size++;
|
|
4314
|
+
runtime.stats.available++;
|
|
4315
|
+
return connection;
|
|
4316
|
+
}
|
|
4317
|
+
async function destroyConnection(runtime, pooled) {
|
|
4318
|
+
const index = runtime.connections.indexOf(pooled);
|
|
4319
|
+
if (index !== -1) {
|
|
4320
|
+
runtime.connections.splice(index, 1);
|
|
4321
|
+
}
|
|
4322
|
+
if (runtime.options.destroyer) {
|
|
4323
|
+
await runtime.options.destroyer(pooled.connection);
|
|
4324
|
+
}
|
|
4325
|
+
runtime.options.onDestroy?.(pooled.connection);
|
|
4326
|
+
runtime.stats.destroyed++;
|
|
4327
|
+
runtime.stats.size--;
|
|
4328
|
+
if (pooled.inUse) {
|
|
4329
|
+
runtime.stats.acquired--;
|
|
4330
|
+
} else {
|
|
4331
|
+
runtime.stats.available--;
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
function getPoolConfig(runtime) {
|
|
4335
|
+
return runtime.options.pool || {};
|
|
4336
|
+
}
|
|
4337
|
+
function getHealthCheckConfig(runtime) {
|
|
4338
|
+
return runtime.options.healthCheck || {};
|
|
4339
|
+
}
|
|
4340
|
+
function clonePoolStats(runtime) {
|
|
4341
|
+
return { ...runtime.stats };
|
|
4342
|
+
}
|
|
4343
|
+
|
|
4344
|
+
// src/resources/pool-acquisition.ts
|
|
4345
|
+
async function acquireConnection(runtime) {
|
|
4346
|
+
if (runtime.draining) {
|
|
4347
|
+
throw new Error("Pool is draining");
|
|
4348
|
+
}
|
|
4349
|
+
const available = runtime.connections.find((connection) => !connection.inUse);
|
|
4350
|
+
if (available) {
|
|
4351
|
+
available.inUse = true;
|
|
4352
|
+
available.lastUsedAt = Date.now();
|
|
4353
|
+
runtime.stats.available--;
|
|
4354
|
+
runtime.stats.acquired++;
|
|
4355
|
+
runtime.options.onAcquire?.(available.connection);
|
|
4356
|
+
return available.connection;
|
|
4357
|
+
}
|
|
4358
|
+
const poolConfig = getPoolConfig(runtime);
|
|
4359
|
+
const max = poolConfig.max || 10;
|
|
4360
|
+
if (runtime.connections.length + runtime.creating < max) {
|
|
4361
|
+
runtime.creating++;
|
|
4362
|
+
try {
|
|
4363
|
+
const connection = await createConnection(runtime);
|
|
4364
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4365
|
+
if (!pooled) {
|
|
4366
|
+
throw new Error("Newly created connection not found in pool");
|
|
4367
|
+
}
|
|
4368
|
+
if (runtime.draining) {
|
|
4369
|
+
await destroyConnection(runtime, pooled);
|
|
4370
|
+
throw new Error("Pool is draining");
|
|
4371
|
+
}
|
|
4336
4372
|
pooled.inUse = true;
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4373
|
+
pooled.lastUsedAt = Date.now();
|
|
4374
|
+
runtime.stats.available--;
|
|
4375
|
+
runtime.stats.acquired++;
|
|
4376
|
+
runtime.options.onAcquire?.(connection);
|
|
4340
4377
|
return connection;
|
|
4378
|
+
} finally {
|
|
4379
|
+
runtime.creating--;
|
|
4341
4380
|
}
|
|
4342
|
-
return new Promise((resolve, reject) => {
|
|
4343
|
-
const timeout2 = poolConfig.acquireTimeout || 3e4;
|
|
4344
|
-
const timer = setTimeout(() => {
|
|
4345
|
-
const index = this.pending.findIndex((p) => p.resolve === resolve);
|
|
4346
|
-
if (index !== -1) {
|
|
4347
|
-
this.pending.splice(index, 1);
|
|
4348
|
-
this.stats.pending--;
|
|
4349
|
-
}
|
|
4350
|
-
reject(new Error("Acquire timeout"));
|
|
4351
|
-
}, timeout2);
|
|
4352
|
-
this.pending.push({ resolve, reject, timeout: timer });
|
|
4353
|
-
this.stats.pending++;
|
|
4354
|
-
});
|
|
4355
4381
|
}
|
|
4356
|
-
|
|
4357
|
-
const
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4382
|
+
return new Promise((resolve, reject) => {
|
|
4383
|
+
const timeout2 = poolConfig.acquireTimeout || 3e4;
|
|
4384
|
+
const timer = setTimeout(() => {
|
|
4385
|
+
const index = runtime.pending.findIndex((pending) => pending.resolve === resolve);
|
|
4386
|
+
if (index !== -1) {
|
|
4387
|
+
runtime.pending.splice(index, 1);
|
|
4388
|
+
runtime.stats.pending--;
|
|
4389
|
+
}
|
|
4390
|
+
reject(new Error("Acquire timeout"));
|
|
4391
|
+
}, timeout2);
|
|
4392
|
+
runtime.pending.push({ resolve, reject, timeout: timer });
|
|
4393
|
+
runtime.stats.pending++;
|
|
4394
|
+
});
|
|
4395
|
+
}
|
|
4396
|
+
async function releaseConnection(runtime, connection) {
|
|
4397
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4398
|
+
if (!pooled) {
|
|
4399
|
+
throw new Error("Connection not found in pool");
|
|
4400
|
+
}
|
|
4401
|
+
if (!pooled.inUse) {
|
|
4402
|
+
throw new Error("Connection is not in use");
|
|
4403
|
+
}
|
|
4404
|
+
pooled.inUse = false;
|
|
4405
|
+
pooled.lastUsedAt = Date.now();
|
|
4406
|
+
runtime.stats.available++;
|
|
4407
|
+
runtime.stats.acquired--;
|
|
4408
|
+
runtime.options.onRelease?.(connection);
|
|
4409
|
+
const pending = runtime.pending.shift();
|
|
4410
|
+
if (!pending) {
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4413
|
+
clearTimeout(pending.timeout);
|
|
4414
|
+
runtime.stats.pending--;
|
|
4415
|
+
pooled.inUse = true;
|
|
4416
|
+
pooled.lastUsedAt = Date.now();
|
|
4417
|
+
runtime.stats.available--;
|
|
4418
|
+
runtime.stats.acquired++;
|
|
4419
|
+
runtime.options.onAcquire?.(connection);
|
|
4420
|
+
pending.resolve(connection);
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4423
|
+
// src/resources/pool-eviction.ts
|
|
4424
|
+
function selectIdleConnectionsForEviction(runtime, idleTimeout, min, now) {
|
|
4425
|
+
const idleConnections = runtime.connections.filter(
|
|
4426
|
+
(connection) => !connection.inUse && now - connection.lastUsedAt > idleTimeout
|
|
4427
|
+
);
|
|
4428
|
+
const evictableCount = Math.max(0, runtime.connections.length - min);
|
|
4429
|
+
return idleConnections.slice(0, evictableCount);
|
|
4430
|
+
}
|
|
4431
|
+
async function evictIdleConnections(runtime) {
|
|
4432
|
+
const poolConfig = getPoolConfig(runtime);
|
|
4433
|
+
const idleTimeout = poolConfig.idleTimeout || 6e4;
|
|
4434
|
+
const min = poolConfig.min || 0;
|
|
4435
|
+
const now = Date.now();
|
|
4436
|
+
const toEvict = selectIdleConnectionsForEviction(runtime, idleTimeout, min, now);
|
|
4437
|
+
for (const pooled of toEvict) {
|
|
4438
|
+
if (!runtime.connections.includes(pooled)) {
|
|
4439
|
+
continue;
|
|
4440
|
+
}
|
|
4441
|
+
if (pooled.inUse) {
|
|
4442
|
+
continue;
|
|
4443
|
+
}
|
|
4444
|
+
if (runtime.connections.length <= min) {
|
|
4445
|
+
break;
|
|
4446
|
+
}
|
|
4447
|
+
if (Date.now() - pooled.lastUsedAt <= idleTimeout) {
|
|
4448
|
+
continue;
|
|
4378
4449
|
}
|
|
4450
|
+
await destroyConnection(runtime, pooled);
|
|
4379
4451
|
}
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4452
|
+
}
|
|
4453
|
+
|
|
4454
|
+
// src/resources/pool-health.ts
|
|
4455
|
+
async function runHealthCheckWithTimeout(runtime, connection, timeout2) {
|
|
4456
|
+
let timer;
|
|
4457
|
+
try {
|
|
4458
|
+
return await Promise.race([
|
|
4459
|
+
runtime.options.validator(connection),
|
|
4460
|
+
new Promise((_, reject) => {
|
|
4461
|
+
timer = setTimeout(() => reject(new Error("Health check timeout")), timeout2);
|
|
4462
|
+
})
|
|
4463
|
+
]);
|
|
4464
|
+
} finally {
|
|
4465
|
+
if (timer) {
|
|
4466
|
+
clearTimeout(timer);
|
|
4390
4467
|
}
|
|
4391
4468
|
}
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4469
|
+
}
|
|
4470
|
+
async function performHealthChecks(runtime) {
|
|
4471
|
+
if (!runtime.options.validator) {
|
|
4472
|
+
return;
|
|
4473
|
+
}
|
|
4474
|
+
const healthCheck = getHealthCheckConfig(runtime);
|
|
4475
|
+
const timeout2 = healthCheck.timeout || 5e3;
|
|
4476
|
+
const retries = healthCheck.retries || 1;
|
|
4477
|
+
for (const pooled of [...runtime.connections]) {
|
|
4478
|
+
if (pooled.inUse) {
|
|
4479
|
+
continue;
|
|
4395
4480
|
}
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
let healthy = false;
|
|
4404
|
-
for (let i = 0; i < retries; i++) {
|
|
4405
|
-
try {
|
|
4406
|
-
const result = await Promise.race([
|
|
4407
|
-
this.options.validator(pooled.connection),
|
|
4408
|
-
new Promise(
|
|
4409
|
-
(_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout2)
|
|
4410
|
-
)
|
|
4411
|
-
]);
|
|
4412
|
-
if (result) {
|
|
4413
|
-
healthy = true;
|
|
4414
|
-
break;
|
|
4415
|
-
}
|
|
4416
|
-
} catch (error) {
|
|
4481
|
+
let healthy = false;
|
|
4482
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
4483
|
+
try {
|
|
4484
|
+
const result = await runHealthCheckWithTimeout(runtime, pooled.connection, timeout2);
|
|
4485
|
+
if (result) {
|
|
4486
|
+
healthy = true;
|
|
4487
|
+
break;
|
|
4417
4488
|
}
|
|
4418
|
-
}
|
|
4419
|
-
if (healthy) {
|
|
4420
|
-
this.stats.healthChecksPassed++;
|
|
4421
|
-
} else {
|
|
4422
|
-
this.stats.healthChecksFailed++;
|
|
4423
|
-
await this.destroyConnection(pooled);
|
|
4489
|
+
} catch {
|
|
4424
4490
|
}
|
|
4425
4491
|
}
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
for (const pending of this.pending) {
|
|
4430
|
-
clearTimeout(pending.timeout);
|
|
4431
|
-
pending.reject(new Error("Pool is draining"));
|
|
4492
|
+
if (healthy) {
|
|
4493
|
+
runtime.stats.healthChecksPassed++;
|
|
4494
|
+
continue;
|
|
4432
4495
|
}
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
while (this.connections.some((c) => c.inUse)) {
|
|
4436
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4496
|
+
if (!runtime.connections.includes(pooled) || pooled.inUse) {
|
|
4497
|
+
continue;
|
|
4437
4498
|
}
|
|
4499
|
+
runtime.stats.healthChecksFailed++;
|
|
4500
|
+
await destroyConnection(runtime, pooled);
|
|
4438
4501
|
}
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4502
|
+
}
|
|
4503
|
+
|
|
4504
|
+
// src/resources/pool-lifecycle.ts
|
|
4505
|
+
function rejectPendingAcquisitions(runtime, message) {
|
|
4506
|
+
for (const pending of runtime.pending) {
|
|
4507
|
+
clearTimeout(pending.timeout);
|
|
4508
|
+
pending.reject(new Error(message));
|
|
4509
|
+
}
|
|
4510
|
+
runtime.pending = [];
|
|
4511
|
+
runtime.stats.pending = 0;
|
|
4512
|
+
}
|
|
4513
|
+
async function drainPool(runtime) {
|
|
4514
|
+
runtime.draining = true;
|
|
4515
|
+
rejectPendingAcquisitions(runtime, "Pool is draining");
|
|
4516
|
+
while (runtime.connections.some((connection) => connection.inUse)) {
|
|
4517
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
async function clearPool(runtime) {
|
|
4521
|
+
runtime.draining = true;
|
|
4522
|
+
rejectPendingAcquisitions(runtime, "Pool is draining");
|
|
4523
|
+
if (runtime.evictionTimer) {
|
|
4524
|
+
clearInterval(runtime.evictionTimer);
|
|
4525
|
+
runtime.evictionTimer = void 0;
|
|
4526
|
+
}
|
|
4527
|
+
if (runtime.healthCheckTimer) {
|
|
4528
|
+
clearInterval(runtime.healthCheckTimer);
|
|
4529
|
+
runtime.healthCheckTimer = void 0;
|
|
4530
|
+
}
|
|
4531
|
+
const connections = [...runtime.connections];
|
|
4532
|
+
for (const pooled of connections) {
|
|
4533
|
+
await destroyConnection(runtime, pooled);
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
// src/resources/pool.ts
|
|
4538
|
+
var logger4 = createLogger("agentforge:core:resources:pool");
|
|
4539
|
+
function toErrorPayload(error) {
|
|
4540
|
+
if (error instanceof Error) {
|
|
4541
|
+
return {
|
|
4542
|
+
error: error.message,
|
|
4543
|
+
stack: error.stack
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
return { error: String(error) };
|
|
4547
|
+
}
|
|
4548
|
+
function toError3(error) {
|
|
4549
|
+
if (error instanceof Error) {
|
|
4550
|
+
return error;
|
|
4551
|
+
}
|
|
4552
|
+
return new Error(String(error));
|
|
4553
|
+
}
|
|
4554
|
+
var ConnectionPool = class {
|
|
4555
|
+
runtime;
|
|
4556
|
+
constructor(options) {
|
|
4557
|
+
this.runtime = {
|
|
4558
|
+
connections: [],
|
|
4559
|
+
pending: [],
|
|
4560
|
+
stats: createInitialPoolStats(),
|
|
4561
|
+
draining: false,
|
|
4562
|
+
creating: 0,
|
|
4563
|
+
options
|
|
4564
|
+
};
|
|
4565
|
+
const poolConfig = getPoolConfig(this.runtime);
|
|
4566
|
+
const min = poolConfig.min || 0;
|
|
4567
|
+
if (min > 0) {
|
|
4568
|
+
initializeConnections(this.runtime, min).catch((error) => {
|
|
4569
|
+
logger4.error("Failed to initialize pool", toErrorPayload(error));
|
|
4570
|
+
});
|
|
4447
4571
|
}
|
|
4448
|
-
const
|
|
4449
|
-
|
|
4450
|
-
|
|
4572
|
+
const evictionInterval = poolConfig.evictionInterval || 6e4;
|
|
4573
|
+
this.runtime.evictionTimer = setInterval(() => {
|
|
4574
|
+
evictIdleConnections(this.runtime).catch((error) => {
|
|
4575
|
+
logger4.error("Failed to evict idle connections", toErrorPayload(error));
|
|
4576
|
+
});
|
|
4577
|
+
}, evictionInterval);
|
|
4578
|
+
const healthCheck = getHealthCheckConfig(this.runtime);
|
|
4579
|
+
if (healthCheck.enabled) {
|
|
4580
|
+
const interval = healthCheck.interval || 3e4;
|
|
4581
|
+
this.runtime.healthCheckTimer = setInterval(() => {
|
|
4582
|
+
performHealthChecks(this.runtime).catch((error) => {
|
|
4583
|
+
const normalizedError = toError3(error);
|
|
4584
|
+
logger4.error("Health check failed", toErrorPayload(normalizedError));
|
|
4585
|
+
options.onHealthCheckFail?.(normalizedError);
|
|
4586
|
+
});
|
|
4587
|
+
}, interval);
|
|
4451
4588
|
}
|
|
4452
4589
|
}
|
|
4590
|
+
async acquire() {
|
|
4591
|
+
return acquireConnection(this.runtime);
|
|
4592
|
+
}
|
|
4593
|
+
async release(connection) {
|
|
4594
|
+
return releaseConnection(this.runtime, connection);
|
|
4595
|
+
}
|
|
4596
|
+
async drain() {
|
|
4597
|
+
return drainPool(this.runtime);
|
|
4598
|
+
}
|
|
4599
|
+
async clear() {
|
|
4600
|
+
return clearPool(this.runtime);
|
|
4601
|
+
}
|
|
4453
4602
|
getStats() {
|
|
4454
|
-
return
|
|
4603
|
+
return clonePoolStats(this.runtime);
|
|
4455
4604
|
}
|
|
4456
4605
|
};
|
|
4457
4606
|
function createConnectionPool(options) {
|
|
@@ -4984,7 +5133,7 @@ function createCircuitBreaker(options) {
|
|
|
4984
5133
|
}
|
|
4985
5134
|
|
|
4986
5135
|
// src/monitoring/health.ts
|
|
4987
|
-
var
|
|
5136
|
+
var logger5 = createLogger("agentforge:core:monitoring:health", { level: "info" /* INFO */ });
|
|
4988
5137
|
var HealthChecker = class {
|
|
4989
5138
|
constructor(options) {
|
|
4990
5139
|
this.options = options;
|
|
@@ -5000,14 +5149,14 @@ var HealthChecker = class {
|
|
|
5000
5149
|
this.running = true;
|
|
5001
5150
|
const interval = this.options.interval || 3e4;
|
|
5002
5151
|
this.runChecks().catch((error) => {
|
|
5003
|
-
|
|
5152
|
+
logger5.error("Initial health check failed", {
|
|
5004
5153
|
error: error instanceof Error ? error.message : String(error),
|
|
5005
5154
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5006
5155
|
});
|
|
5007
5156
|
});
|
|
5008
5157
|
this.checkTimer = setInterval(() => {
|
|
5009
5158
|
this.runChecks().catch((error) => {
|
|
5010
|
-
|
|
5159
|
+
logger5.error("Health check failed", {
|
|
5011
5160
|
error: error instanceof Error ? error.message : String(error),
|
|
5012
5161
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5013
5162
|
});
|
|
@@ -5217,7 +5366,7 @@ function createProfiler(options) {
|
|
|
5217
5366
|
}
|
|
5218
5367
|
|
|
5219
5368
|
// src/monitoring/alerts.ts
|
|
5220
|
-
var
|
|
5369
|
+
var logger6 = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5221
5370
|
function toAlertSummary(alert) {
|
|
5222
5371
|
return {
|
|
5223
5372
|
name: alert.name,
|
|
@@ -5269,7 +5418,7 @@ var AlertManager = class {
|
|
|
5269
5418
|
const currentMetrics = metrics();
|
|
5270
5419
|
this.checkRules(currentMetrics);
|
|
5271
5420
|
} catch (error) {
|
|
5272
|
-
|
|
5421
|
+
logger6.error("Metrics collection failed", toMetricsProviderErrorPayload(error));
|
|
5273
5422
|
}
|
|
5274
5423
|
}, interval);
|
|
5275
5424
|
}
|
|
@@ -5295,9 +5444,9 @@ var AlertManager = class {
|
|
|
5295
5444
|
try {
|
|
5296
5445
|
await this.options.onAlert?.(fullAlert);
|
|
5297
5446
|
} catch (error) {
|
|
5298
|
-
|
|
5447
|
+
logger6.error("Alert callback failed", toAlertCallbackErrorPayload(error));
|
|
5299
5448
|
}
|
|
5300
|
-
|
|
5449
|
+
logger6.warn("Alert triggered", {
|
|
5301
5450
|
name: alert.name,
|
|
5302
5451
|
severity: alert.severity,
|
|
5303
5452
|
message: alert.message,
|
|
@@ -5317,11 +5466,11 @@ var AlertManager = class {
|
|
|
5317
5466
|
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5318
5467
|
data: { metrics }
|
|
5319
5468
|
}).catch((error) => {
|
|
5320
|
-
|
|
5469
|
+
logger6.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5321
5470
|
});
|
|
5322
5471
|
}
|
|
5323
5472
|
} catch (error) {
|
|
5324
|
-
|
|
5473
|
+
logger6.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5325
5474
|
}
|
|
5326
5475
|
}
|
|
5327
5476
|
}
|
|
@@ -5343,28 +5492,28 @@ var AlertManager = class {
|
|
|
5343
5492
|
}
|
|
5344
5493
|
switch (channel.type) {
|
|
5345
5494
|
case "email":
|
|
5346
|
-
|
|
5495
|
+
logger6.info("Alert sent to email", {
|
|
5347
5496
|
channel: channelName,
|
|
5348
5497
|
to: channel.config.to,
|
|
5349
5498
|
alert: toAlertSummary(alert)
|
|
5350
5499
|
});
|
|
5351
5500
|
break;
|
|
5352
5501
|
case "slack":
|
|
5353
|
-
|
|
5502
|
+
logger6.info("Alert sent to Slack", {
|
|
5354
5503
|
channel: channelName,
|
|
5355
5504
|
webhookUrl: channel.config.webhookUrl,
|
|
5356
5505
|
alert: toAlertSummary(alert)
|
|
5357
5506
|
});
|
|
5358
5507
|
break;
|
|
5359
5508
|
case "webhook":
|
|
5360
|
-
|
|
5509
|
+
logger6.info("Alert sent to webhook", {
|
|
5361
5510
|
channel: channelName,
|
|
5362
5511
|
url: channel.config.url,
|
|
5363
5512
|
alert: toAlertSummary(alert)
|
|
5364
5513
|
});
|
|
5365
5514
|
break;
|
|
5366
5515
|
default:
|
|
5367
|
-
|
|
5516
|
+
logger6.info("Alert sent", {
|
|
5368
5517
|
channel: channelName,
|
|
5369
5518
|
channelType: channel.type,
|
|
5370
5519
|
alert: toAlertSummary(alert)
|