@agentforge/core 0.16.52 → 0.16.54
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 +351 -210
- package/dist/index.d.cts +6 -15
- package/dist/index.d.ts +6 -15
- package/dist/index.js +351 -210
- 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 } : {}
|
|
@@ -2625,14 +2625,14 @@ var withLogging = (options) => {
|
|
|
2625
2625
|
onComplete,
|
|
2626
2626
|
onError
|
|
2627
2627
|
} = options;
|
|
2628
|
-
const
|
|
2628
|
+
const logger7 = providedLogger || createLogger(name, { level });
|
|
2629
2629
|
return (node) => {
|
|
2630
2630
|
return async (state) => {
|
|
2631
2631
|
const startTime = Date.now();
|
|
2632
2632
|
try {
|
|
2633
2633
|
if (logInput) {
|
|
2634
2634
|
const data = extractData ? extractData(state) : { state };
|
|
2635
|
-
|
|
2635
|
+
logger7.info("Node execution started", data);
|
|
2636
2636
|
}
|
|
2637
2637
|
if (onStart) {
|
|
2638
2638
|
onStart(state);
|
|
@@ -2642,9 +2642,9 @@ var withLogging = (options) => {
|
|
|
2642
2642
|
if (logOutput) {
|
|
2643
2643
|
const data = extractData ? extractData(result) : { result };
|
|
2644
2644
|
if (logDuration) {
|
|
2645
|
-
|
|
2645
|
+
logger7.info(`Node execution completed (${duration}ms)`, data);
|
|
2646
2646
|
} else {
|
|
2647
|
-
|
|
2647
|
+
logger7.info("Node execution completed", data);
|
|
2648
2648
|
}
|
|
2649
2649
|
}
|
|
2650
2650
|
if (onComplete) {
|
|
@@ -2655,7 +2655,7 @@ var withLogging = (options) => {
|
|
|
2655
2655
|
const duration = Date.now() - startTime;
|
|
2656
2656
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2657
2657
|
if (logErrors) {
|
|
2658
|
-
|
|
2658
|
+
logger7.error(`Node execution failed (${duration}ms)`, {
|
|
2659
2659
|
error: err.message,
|
|
2660
2660
|
...err.stack ? { stack: err.stack } : {}
|
|
2661
2661
|
});
|
|
@@ -2777,7 +2777,7 @@ function withLogging2(options) {
|
|
|
2777
2777
|
function production(node, options) {
|
|
2778
2778
|
const {
|
|
2779
2779
|
nodeName,
|
|
2780
|
-
logger:
|
|
2780
|
+
logger: logger7,
|
|
2781
2781
|
enableMetrics = true,
|
|
2782
2782
|
enableTracing = true,
|
|
2783
2783
|
enableRetry = true,
|
|
@@ -2785,7 +2785,7 @@ function production(node, options) {
|
|
|
2785
2785
|
retryOptions = {},
|
|
2786
2786
|
errorOptions = {}
|
|
2787
2787
|
} = options;
|
|
2788
|
-
const actualLogger =
|
|
2788
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2789
2789
|
const middleware = [
|
|
2790
2790
|
withLogging2({
|
|
2791
2791
|
logger: actualLogger,
|
|
@@ -2840,8 +2840,8 @@ function production(node, options) {
|
|
|
2840
2840
|
|
|
2841
2841
|
// src/langgraph/middleware/preset-development.ts
|
|
2842
2842
|
function development(node, options) {
|
|
2843
|
-
const { nodeName, verbose = true, logger:
|
|
2844
|
-
const actualLogger =
|
|
2843
|
+
const { nodeName, verbose = true, logger: logger7 } = options;
|
|
2844
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2845
2845
|
return withLogging2({
|
|
2846
2846
|
logger: actualLogger,
|
|
2847
2847
|
name: nodeName,
|
|
@@ -4248,37 +4248,9 @@ function createMessage(type, data, error) {
|
|
|
4248
4248
|
return { type, data, error };
|
|
4249
4249
|
}
|
|
4250
4250
|
|
|
4251
|
-
// src/resources/pool.ts
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
this.options = options;
|
|
4255
|
-
const poolConfig = options.pool || {};
|
|
4256
|
-
const min = poolConfig.min || 0;
|
|
4257
|
-
if (min > 0) {
|
|
4258
|
-
this.initialize(min).catch((error) => {
|
|
4259
|
-
console.error("Failed to initialize pool:", error);
|
|
4260
|
-
});
|
|
4261
|
-
}
|
|
4262
|
-
const evictionInterval = poolConfig.evictionInterval || 6e4;
|
|
4263
|
-
this.evictionTimer = setInterval(() => {
|
|
4264
|
-
this.evictIdleConnections().catch((error) => {
|
|
4265
|
-
console.error("Failed to evict idle connections:", error);
|
|
4266
|
-
});
|
|
4267
|
-
}, evictionInterval);
|
|
4268
|
-
const healthCheck = options.healthCheck || {};
|
|
4269
|
-
if (healthCheck.enabled) {
|
|
4270
|
-
const interval = healthCheck.interval || 3e4;
|
|
4271
|
-
this.healthCheckTimer = setInterval(() => {
|
|
4272
|
-
this.performHealthChecks().catch((error) => {
|
|
4273
|
-
console.error("Health check failed:", error);
|
|
4274
|
-
options.onHealthCheckFail?.(error);
|
|
4275
|
-
});
|
|
4276
|
-
}, interval);
|
|
4277
|
-
}
|
|
4278
|
-
}
|
|
4279
|
-
connections = [];
|
|
4280
|
-
pending = [];
|
|
4281
|
-
stats = {
|
|
4251
|
+
// src/resources/pool-runtime.ts
|
|
4252
|
+
function createInitialPoolStats() {
|
|
4253
|
+
return {
|
|
4282
4254
|
size: 0,
|
|
4283
4255
|
available: 0,
|
|
4284
4256
|
pending: 0,
|
|
@@ -4288,178 +4260,347 @@ var ConnectionPool = class {
|
|
|
4288
4260
|
healthChecksPassed: 0,
|
|
4289
4261
|
healthChecksFailed: 0
|
|
4290
4262
|
};
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
async
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
this.stats.available++;
|
|
4309
|
-
return connection;
|
|
4310
|
-
}
|
|
4311
|
-
async destroyConnection(pooled) {
|
|
4312
|
-
const index = this.connections.indexOf(pooled);
|
|
4313
|
-
if (index !== -1) {
|
|
4314
|
-
this.connections.splice(index, 1);
|
|
4315
|
-
}
|
|
4316
|
-
if (this.options.destroyer) {
|
|
4317
|
-
await this.options.destroyer(pooled.connection);
|
|
4318
|
-
}
|
|
4319
|
-
this.options.onDestroy?.(pooled.connection);
|
|
4320
|
-
this.stats.destroyed++;
|
|
4321
|
-
this.stats.size--;
|
|
4322
|
-
if (!pooled.inUse) {
|
|
4323
|
-
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--;
|
|
4324
4280
|
}
|
|
4281
|
+
});
|
|
4282
|
+
await Promise.all(promises);
|
|
4283
|
+
}
|
|
4284
|
+
function assignConnectionToPendingAcquire(runtime, connection) {
|
|
4285
|
+
const pending = runtime.pending.shift();
|
|
4286
|
+
if (!pending) {
|
|
4287
|
+
return;
|
|
4325
4288
|
}
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
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
|
+
}
|
|
4344
4372
|
pooled.inUse = true;
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4373
|
+
pooled.lastUsedAt = Date.now();
|
|
4374
|
+
runtime.stats.available--;
|
|
4375
|
+
runtime.stats.acquired++;
|
|
4376
|
+
runtime.options.onAcquire?.(connection);
|
|
4348
4377
|
return connection;
|
|
4378
|
+
} finally {
|
|
4379
|
+
runtime.creating--;
|
|
4349
4380
|
}
|
|
4350
|
-
return new Promise((resolve, reject) => {
|
|
4351
|
-
const timeout2 = poolConfig.acquireTimeout || 3e4;
|
|
4352
|
-
const timer = setTimeout(() => {
|
|
4353
|
-
const index = this.pending.findIndex((p) => p.resolve === resolve);
|
|
4354
|
-
if (index !== -1) {
|
|
4355
|
-
this.pending.splice(index, 1);
|
|
4356
|
-
this.stats.pending--;
|
|
4357
|
-
}
|
|
4358
|
-
reject(new Error("Acquire timeout"));
|
|
4359
|
-
}, timeout2);
|
|
4360
|
-
this.pending.push({ resolve, reject, timeout: timer });
|
|
4361
|
-
this.stats.pending++;
|
|
4362
|
-
});
|
|
4363
4381
|
}
|
|
4364
|
-
|
|
4365
|
-
const
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
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;
|
|
4386
4449
|
}
|
|
4450
|
+
await destroyConnection(runtime, pooled);
|
|
4387
4451
|
}
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
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);
|
|
4398
4467
|
}
|
|
4399
4468
|
}
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
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;
|
|
4403
4480
|
}
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
let healthy = false;
|
|
4412
|
-
for (let i = 0; i < retries; i++) {
|
|
4413
|
-
try {
|
|
4414
|
-
const result = await Promise.race([
|
|
4415
|
-
this.options.validator(pooled.connection),
|
|
4416
|
-
new Promise(
|
|
4417
|
-
(_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout2)
|
|
4418
|
-
)
|
|
4419
|
-
]);
|
|
4420
|
-
if (result) {
|
|
4421
|
-
healthy = true;
|
|
4422
|
-
break;
|
|
4423
|
-
}
|
|
4424
|
-
} 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;
|
|
4425
4488
|
}
|
|
4426
|
-
}
|
|
4427
|
-
if (healthy) {
|
|
4428
|
-
this.stats.healthChecksPassed++;
|
|
4429
|
-
} else {
|
|
4430
|
-
this.stats.healthChecksFailed++;
|
|
4431
|
-
await this.destroyConnection(pooled);
|
|
4489
|
+
} catch {
|
|
4432
4490
|
}
|
|
4433
4491
|
}
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
for (const pending of this.pending) {
|
|
4438
|
-
clearTimeout(pending.timeout);
|
|
4439
|
-
pending.reject(new Error("Pool is draining"));
|
|
4492
|
+
if (healthy) {
|
|
4493
|
+
runtime.stats.healthChecksPassed++;
|
|
4494
|
+
continue;
|
|
4440
4495
|
}
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
while (this.connections.some((c) => c.inUse)) {
|
|
4444
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4496
|
+
if (!runtime.connections.includes(pooled) || pooled.inUse) {
|
|
4497
|
+
continue;
|
|
4445
4498
|
}
|
|
4499
|
+
runtime.stats.healthChecksFailed++;
|
|
4500
|
+
await destroyConnection(runtime, pooled);
|
|
4446
4501
|
}
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
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
|
+
});
|
|
4455
4571
|
}
|
|
4456
|
-
const
|
|
4457
|
-
|
|
4458
|
-
|
|
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);
|
|
4459
4588
|
}
|
|
4460
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
|
+
}
|
|
4461
4602
|
getStats() {
|
|
4462
|
-
return
|
|
4603
|
+
return clonePoolStats(this.runtime);
|
|
4463
4604
|
}
|
|
4464
4605
|
};
|
|
4465
4606
|
function createConnectionPool(options) {
|
|
@@ -4992,7 +5133,7 @@ function createCircuitBreaker(options) {
|
|
|
4992
5133
|
}
|
|
4993
5134
|
|
|
4994
5135
|
// src/monitoring/health.ts
|
|
4995
|
-
var
|
|
5136
|
+
var logger5 = createLogger("agentforge:core:monitoring:health", { level: "info" /* INFO */ });
|
|
4996
5137
|
var HealthChecker = class {
|
|
4997
5138
|
constructor(options) {
|
|
4998
5139
|
this.options = options;
|
|
@@ -5008,14 +5149,14 @@ var HealthChecker = class {
|
|
|
5008
5149
|
this.running = true;
|
|
5009
5150
|
const interval = this.options.interval || 3e4;
|
|
5010
5151
|
this.runChecks().catch((error) => {
|
|
5011
|
-
|
|
5152
|
+
logger5.error("Initial health check failed", {
|
|
5012
5153
|
error: error instanceof Error ? error.message : String(error),
|
|
5013
5154
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5014
5155
|
});
|
|
5015
5156
|
});
|
|
5016
5157
|
this.checkTimer = setInterval(() => {
|
|
5017
5158
|
this.runChecks().catch((error) => {
|
|
5018
|
-
|
|
5159
|
+
logger5.error("Health check failed", {
|
|
5019
5160
|
error: error instanceof Error ? error.message : String(error),
|
|
5020
5161
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5021
5162
|
});
|
|
@@ -5225,7 +5366,7 @@ function createProfiler(options) {
|
|
|
5225
5366
|
}
|
|
5226
5367
|
|
|
5227
5368
|
// src/monitoring/alerts.ts
|
|
5228
|
-
var
|
|
5369
|
+
var logger6 = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5229
5370
|
function toAlertSummary(alert) {
|
|
5230
5371
|
return {
|
|
5231
5372
|
name: alert.name,
|
|
@@ -5277,7 +5418,7 @@ var AlertManager = class {
|
|
|
5277
5418
|
const currentMetrics = metrics();
|
|
5278
5419
|
this.checkRules(currentMetrics);
|
|
5279
5420
|
} catch (error) {
|
|
5280
|
-
|
|
5421
|
+
logger6.error("Metrics collection failed", toMetricsProviderErrorPayload(error));
|
|
5281
5422
|
}
|
|
5282
5423
|
}, interval);
|
|
5283
5424
|
}
|
|
@@ -5303,9 +5444,9 @@ var AlertManager = class {
|
|
|
5303
5444
|
try {
|
|
5304
5445
|
await this.options.onAlert?.(fullAlert);
|
|
5305
5446
|
} catch (error) {
|
|
5306
|
-
|
|
5447
|
+
logger6.error("Alert callback failed", toAlertCallbackErrorPayload(error));
|
|
5307
5448
|
}
|
|
5308
|
-
|
|
5449
|
+
logger6.warn("Alert triggered", {
|
|
5309
5450
|
name: alert.name,
|
|
5310
5451
|
severity: alert.severity,
|
|
5311
5452
|
message: alert.message,
|
|
@@ -5325,11 +5466,11 @@ var AlertManager = class {
|
|
|
5325
5466
|
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5326
5467
|
data: { metrics }
|
|
5327
5468
|
}).catch((error) => {
|
|
5328
|
-
|
|
5469
|
+
logger6.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5329
5470
|
});
|
|
5330
5471
|
}
|
|
5331
5472
|
} catch (error) {
|
|
5332
|
-
|
|
5473
|
+
logger6.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5333
5474
|
}
|
|
5334
5475
|
}
|
|
5335
5476
|
}
|
|
@@ -5351,28 +5492,28 @@ var AlertManager = class {
|
|
|
5351
5492
|
}
|
|
5352
5493
|
switch (channel.type) {
|
|
5353
5494
|
case "email":
|
|
5354
|
-
|
|
5495
|
+
logger6.info("Alert sent to email", {
|
|
5355
5496
|
channel: channelName,
|
|
5356
5497
|
to: channel.config.to,
|
|
5357
5498
|
alert: toAlertSummary(alert)
|
|
5358
5499
|
});
|
|
5359
5500
|
break;
|
|
5360
5501
|
case "slack":
|
|
5361
|
-
|
|
5502
|
+
logger6.info("Alert sent to Slack", {
|
|
5362
5503
|
channel: channelName,
|
|
5363
5504
|
webhookUrl: channel.config.webhookUrl,
|
|
5364
5505
|
alert: toAlertSummary(alert)
|
|
5365
5506
|
});
|
|
5366
5507
|
break;
|
|
5367
5508
|
case "webhook":
|
|
5368
|
-
|
|
5509
|
+
logger6.info("Alert sent to webhook", {
|
|
5369
5510
|
channel: channelName,
|
|
5370
5511
|
url: channel.config.url,
|
|
5371
5512
|
alert: toAlertSummary(alert)
|
|
5372
5513
|
});
|
|
5373
5514
|
break;
|
|
5374
5515
|
default:
|
|
5375
|
-
|
|
5516
|
+
logger6.info("Alert sent", {
|
|
5376
5517
|
channel: channelName,
|
|
5377
5518
|
channelType: channel.type,
|
|
5378
5519
|
alert: toAlertSummary(alert)
|