@agentforge/core 0.16.52 → 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 +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.js
CHANGED
|
@@ -1176,7 +1176,7 @@ function toError(error) {
|
|
|
1176
1176
|
}
|
|
1177
1177
|
return new Error(String(error));
|
|
1178
1178
|
}
|
|
1179
|
-
function resolveExecutionMethod(tool,
|
|
1179
|
+
function resolveExecutionMethod(tool, logger7) {
|
|
1180
1180
|
const executeFn = tool.invoke || tool.execute;
|
|
1181
1181
|
if (!executeFn) {
|
|
1182
1182
|
throw new Error(
|
|
@@ -1184,14 +1184,14 @@ function resolveExecutionMethod(tool, logger6) {
|
|
|
1184
1184
|
);
|
|
1185
1185
|
}
|
|
1186
1186
|
if (!tool.invoke && tool.execute) {
|
|
1187
|
-
|
|
1187
|
+
logger7.warn(
|
|
1188
1188
|
`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.`
|
|
1189
1189
|
);
|
|
1190
1190
|
}
|
|
1191
1191
|
return executeFn;
|
|
1192
1192
|
}
|
|
1193
|
-
async function executeWithRetry(tool, input, policy,
|
|
1194
|
-
const executeFn = resolveExecutionMethod(tool,
|
|
1193
|
+
async function executeWithRetry(tool, input, policy, logger7) {
|
|
1194
|
+
const executeFn = resolveExecutionMethod(tool, logger7);
|
|
1195
1195
|
if (!policy) {
|
|
1196
1196
|
return await executeFn.call(tool, input);
|
|
1197
1197
|
}
|
|
@@ -1470,7 +1470,7 @@ async function performManagedCleanup({
|
|
|
1470
1470
|
function ensureManagedBeforeExitHandler({
|
|
1471
1471
|
autoCleanup,
|
|
1472
1472
|
cleanup,
|
|
1473
|
-
logger:
|
|
1473
|
+
logger: logger7,
|
|
1474
1474
|
name,
|
|
1475
1475
|
state
|
|
1476
1476
|
}) {
|
|
@@ -1479,7 +1479,7 @@ function ensureManagedBeforeExitHandler({
|
|
|
1479
1479
|
}
|
|
1480
1480
|
state.beforeExitHandler = () => {
|
|
1481
1481
|
cleanup().catch(
|
|
1482
|
-
(err) =>
|
|
1482
|
+
(err) => logger7.error("Cleanup failed", {
|
|
1483
1483
|
toolName: name,
|
|
1484
1484
|
error: getErrorMessage(err),
|
|
1485
1485
|
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
@@ -2450,14 +2450,14 @@ var withLogging = (options) => {
|
|
|
2450
2450
|
onComplete,
|
|
2451
2451
|
onError
|
|
2452
2452
|
} = options;
|
|
2453
|
-
const
|
|
2453
|
+
const logger7 = providedLogger || createLogger(name, { level });
|
|
2454
2454
|
return (node) => {
|
|
2455
2455
|
return async (state) => {
|
|
2456
2456
|
const startTime = Date.now();
|
|
2457
2457
|
try {
|
|
2458
2458
|
if (logInput) {
|
|
2459
2459
|
const data = extractData ? extractData(state) : { state };
|
|
2460
|
-
|
|
2460
|
+
logger7.info("Node execution started", data);
|
|
2461
2461
|
}
|
|
2462
2462
|
if (onStart) {
|
|
2463
2463
|
onStart(state);
|
|
@@ -2467,9 +2467,9 @@ var withLogging = (options) => {
|
|
|
2467
2467
|
if (logOutput) {
|
|
2468
2468
|
const data = extractData ? extractData(result) : { result };
|
|
2469
2469
|
if (logDuration) {
|
|
2470
|
-
|
|
2470
|
+
logger7.info(`Node execution completed (${duration}ms)`, data);
|
|
2471
2471
|
} else {
|
|
2472
|
-
|
|
2472
|
+
logger7.info("Node execution completed", data);
|
|
2473
2473
|
}
|
|
2474
2474
|
}
|
|
2475
2475
|
if (onComplete) {
|
|
@@ -2480,7 +2480,7 @@ var withLogging = (options) => {
|
|
|
2480
2480
|
const duration = Date.now() - startTime;
|
|
2481
2481
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2482
2482
|
if (logErrors) {
|
|
2483
|
-
|
|
2483
|
+
logger7.error(`Node execution failed (${duration}ms)`, {
|
|
2484
2484
|
error: err.message,
|
|
2485
2485
|
...err.stack ? { stack: err.stack } : {}
|
|
2486
2486
|
});
|
|
@@ -2602,7 +2602,7 @@ function withLogging2(options) {
|
|
|
2602
2602
|
function production(node, options) {
|
|
2603
2603
|
const {
|
|
2604
2604
|
nodeName,
|
|
2605
|
-
logger:
|
|
2605
|
+
logger: logger7,
|
|
2606
2606
|
enableMetrics = true,
|
|
2607
2607
|
enableTracing = true,
|
|
2608
2608
|
enableRetry = true,
|
|
@@ -2610,7 +2610,7 @@ function production(node, options) {
|
|
|
2610
2610
|
retryOptions = {},
|
|
2611
2611
|
errorOptions = {}
|
|
2612
2612
|
} = options;
|
|
2613
|
-
const actualLogger =
|
|
2613
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2614
2614
|
const middleware = [
|
|
2615
2615
|
withLogging2({
|
|
2616
2616
|
logger: actualLogger,
|
|
@@ -2665,8 +2665,8 @@ function production(node, options) {
|
|
|
2665
2665
|
|
|
2666
2666
|
// src/langgraph/middleware/preset-development.ts
|
|
2667
2667
|
function development(node, options) {
|
|
2668
|
-
const { nodeName, verbose = true, logger:
|
|
2669
|
-
const actualLogger =
|
|
2668
|
+
const { nodeName, verbose = true, logger: logger7 } = options;
|
|
2669
|
+
const actualLogger = logger7 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2670
2670
|
return withLogging2({
|
|
2671
2671
|
logger: actualLogger,
|
|
2672
2672
|
name: nodeName,
|
|
@@ -4073,37 +4073,9 @@ function createMessage(type, data, error) {
|
|
|
4073
4073
|
return { type, data, error };
|
|
4074
4074
|
}
|
|
4075
4075
|
|
|
4076
|
-
// src/resources/pool.ts
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
this.options = options;
|
|
4080
|
-
const poolConfig = options.pool || {};
|
|
4081
|
-
const min = poolConfig.min || 0;
|
|
4082
|
-
if (min > 0) {
|
|
4083
|
-
this.initialize(min).catch((error) => {
|
|
4084
|
-
console.error("Failed to initialize pool:", error);
|
|
4085
|
-
});
|
|
4086
|
-
}
|
|
4087
|
-
const evictionInterval = poolConfig.evictionInterval || 6e4;
|
|
4088
|
-
this.evictionTimer = setInterval(() => {
|
|
4089
|
-
this.evictIdleConnections().catch((error) => {
|
|
4090
|
-
console.error("Failed to evict idle connections:", error);
|
|
4091
|
-
});
|
|
4092
|
-
}, evictionInterval);
|
|
4093
|
-
const healthCheck = options.healthCheck || {};
|
|
4094
|
-
if (healthCheck.enabled) {
|
|
4095
|
-
const interval = healthCheck.interval || 3e4;
|
|
4096
|
-
this.healthCheckTimer = setInterval(() => {
|
|
4097
|
-
this.performHealthChecks().catch((error) => {
|
|
4098
|
-
console.error("Health check failed:", error);
|
|
4099
|
-
options.onHealthCheckFail?.(error);
|
|
4100
|
-
});
|
|
4101
|
-
}, interval);
|
|
4102
|
-
}
|
|
4103
|
-
}
|
|
4104
|
-
connections = [];
|
|
4105
|
-
pending = [];
|
|
4106
|
-
stats = {
|
|
4076
|
+
// src/resources/pool-runtime.ts
|
|
4077
|
+
function createInitialPoolStats() {
|
|
4078
|
+
return {
|
|
4107
4079
|
size: 0,
|
|
4108
4080
|
available: 0,
|
|
4109
4081
|
pending: 0,
|
|
@@ -4113,178 +4085,347 @@ var ConnectionPool = class {
|
|
|
4113
4085
|
healthChecksPassed: 0,
|
|
4114
4086
|
healthChecksFailed: 0
|
|
4115
4087
|
};
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
async
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
this.stats.available++;
|
|
4134
|
-
return connection;
|
|
4135
|
-
}
|
|
4136
|
-
async destroyConnection(pooled) {
|
|
4137
|
-
const index = this.connections.indexOf(pooled);
|
|
4138
|
-
if (index !== -1) {
|
|
4139
|
-
this.connections.splice(index, 1);
|
|
4140
|
-
}
|
|
4141
|
-
if (this.options.destroyer) {
|
|
4142
|
-
await this.options.destroyer(pooled.connection);
|
|
4143
|
-
}
|
|
4144
|
-
this.options.onDestroy?.(pooled.connection);
|
|
4145
|
-
this.stats.destroyed++;
|
|
4146
|
-
this.stats.size--;
|
|
4147
|
-
if (!pooled.inUse) {
|
|
4148
|
-
this.stats.available--;
|
|
4088
|
+
}
|
|
4089
|
+
async function initializeConnections(runtime, count) {
|
|
4090
|
+
runtime.creating += count;
|
|
4091
|
+
const promises = Array.from({ length: count }, async () => {
|
|
4092
|
+
try {
|
|
4093
|
+
const connection = await createConnection(runtime);
|
|
4094
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4095
|
+
if (!pooled) {
|
|
4096
|
+
throw new Error("Newly created connection not found in pool");
|
|
4097
|
+
}
|
|
4098
|
+
if (runtime.draining) {
|
|
4099
|
+
await destroyConnection(runtime, pooled);
|
|
4100
|
+
return;
|
|
4101
|
+
}
|
|
4102
|
+
assignConnectionToPendingAcquire(runtime, connection);
|
|
4103
|
+
} finally {
|
|
4104
|
+
runtime.creating--;
|
|
4149
4105
|
}
|
|
4106
|
+
});
|
|
4107
|
+
await Promise.all(promises);
|
|
4108
|
+
}
|
|
4109
|
+
function assignConnectionToPendingAcquire(runtime, connection) {
|
|
4110
|
+
const pending = runtime.pending.shift();
|
|
4111
|
+
if (!pending) {
|
|
4112
|
+
return;
|
|
4150
4113
|
}
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4114
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4115
|
+
if (!pooled) {
|
|
4116
|
+
runtime.pending.unshift(pending);
|
|
4117
|
+
return;
|
|
4118
|
+
}
|
|
4119
|
+
clearTimeout(pending.timeout);
|
|
4120
|
+
runtime.stats.pending--;
|
|
4121
|
+
pooled.inUse = true;
|
|
4122
|
+
pooled.lastUsedAt = Date.now();
|
|
4123
|
+
runtime.stats.available--;
|
|
4124
|
+
runtime.stats.acquired++;
|
|
4125
|
+
runtime.options.onAcquire?.(connection);
|
|
4126
|
+
pending.resolve(connection);
|
|
4127
|
+
}
|
|
4128
|
+
async function createConnection(runtime) {
|
|
4129
|
+
const connection = await runtime.options.factory();
|
|
4130
|
+
const now = Date.now();
|
|
4131
|
+
runtime.connections.push({
|
|
4132
|
+
connection,
|
|
4133
|
+
createdAt: now,
|
|
4134
|
+
lastUsedAt: now,
|
|
4135
|
+
inUse: false
|
|
4136
|
+
});
|
|
4137
|
+
runtime.stats.created++;
|
|
4138
|
+
runtime.stats.size++;
|
|
4139
|
+
runtime.stats.available++;
|
|
4140
|
+
return connection;
|
|
4141
|
+
}
|
|
4142
|
+
async function destroyConnection(runtime, pooled) {
|
|
4143
|
+
const index = runtime.connections.indexOf(pooled);
|
|
4144
|
+
if (index !== -1) {
|
|
4145
|
+
runtime.connections.splice(index, 1);
|
|
4146
|
+
}
|
|
4147
|
+
if (runtime.options.destroyer) {
|
|
4148
|
+
await runtime.options.destroyer(pooled.connection);
|
|
4149
|
+
}
|
|
4150
|
+
runtime.options.onDestroy?.(pooled.connection);
|
|
4151
|
+
runtime.stats.destroyed++;
|
|
4152
|
+
runtime.stats.size--;
|
|
4153
|
+
if (pooled.inUse) {
|
|
4154
|
+
runtime.stats.acquired--;
|
|
4155
|
+
} else {
|
|
4156
|
+
runtime.stats.available--;
|
|
4157
|
+
}
|
|
4158
|
+
}
|
|
4159
|
+
function getPoolConfig(runtime) {
|
|
4160
|
+
return runtime.options.pool || {};
|
|
4161
|
+
}
|
|
4162
|
+
function getHealthCheckConfig(runtime) {
|
|
4163
|
+
return runtime.options.healthCheck || {};
|
|
4164
|
+
}
|
|
4165
|
+
function clonePoolStats(runtime) {
|
|
4166
|
+
return { ...runtime.stats };
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
// src/resources/pool-acquisition.ts
|
|
4170
|
+
async function acquireConnection(runtime) {
|
|
4171
|
+
if (runtime.draining) {
|
|
4172
|
+
throw new Error("Pool is draining");
|
|
4173
|
+
}
|
|
4174
|
+
const available = runtime.connections.find((connection) => !connection.inUse);
|
|
4175
|
+
if (available) {
|
|
4176
|
+
available.inUse = true;
|
|
4177
|
+
available.lastUsedAt = Date.now();
|
|
4178
|
+
runtime.stats.available--;
|
|
4179
|
+
runtime.stats.acquired++;
|
|
4180
|
+
runtime.options.onAcquire?.(available.connection);
|
|
4181
|
+
return available.connection;
|
|
4182
|
+
}
|
|
4183
|
+
const poolConfig = getPoolConfig(runtime);
|
|
4184
|
+
const max = poolConfig.max || 10;
|
|
4185
|
+
if (runtime.connections.length + runtime.creating < max) {
|
|
4186
|
+
runtime.creating++;
|
|
4187
|
+
try {
|
|
4188
|
+
const connection = await createConnection(runtime);
|
|
4189
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4190
|
+
if (!pooled) {
|
|
4191
|
+
throw new Error("Newly created connection not found in pool");
|
|
4192
|
+
}
|
|
4193
|
+
if (runtime.draining) {
|
|
4194
|
+
await destroyConnection(runtime, pooled);
|
|
4195
|
+
throw new Error("Pool is draining");
|
|
4196
|
+
}
|
|
4169
4197
|
pooled.inUse = true;
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4198
|
+
pooled.lastUsedAt = Date.now();
|
|
4199
|
+
runtime.stats.available--;
|
|
4200
|
+
runtime.stats.acquired++;
|
|
4201
|
+
runtime.options.onAcquire?.(connection);
|
|
4173
4202
|
return connection;
|
|
4203
|
+
} finally {
|
|
4204
|
+
runtime.creating--;
|
|
4174
4205
|
}
|
|
4175
|
-
return new Promise((resolve, reject) => {
|
|
4176
|
-
const timeout2 = poolConfig.acquireTimeout || 3e4;
|
|
4177
|
-
const timer = setTimeout(() => {
|
|
4178
|
-
const index = this.pending.findIndex((p) => p.resolve === resolve);
|
|
4179
|
-
if (index !== -1) {
|
|
4180
|
-
this.pending.splice(index, 1);
|
|
4181
|
-
this.stats.pending--;
|
|
4182
|
-
}
|
|
4183
|
-
reject(new Error("Acquire timeout"));
|
|
4184
|
-
}, timeout2);
|
|
4185
|
-
this.pending.push({ resolve, reject, timeout: timer });
|
|
4186
|
-
this.stats.pending++;
|
|
4187
|
-
});
|
|
4188
4206
|
}
|
|
4189
|
-
|
|
4190
|
-
const
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4207
|
+
return new Promise((resolve, reject) => {
|
|
4208
|
+
const timeout2 = poolConfig.acquireTimeout || 3e4;
|
|
4209
|
+
const timer = setTimeout(() => {
|
|
4210
|
+
const index = runtime.pending.findIndex((pending) => pending.resolve === resolve);
|
|
4211
|
+
if (index !== -1) {
|
|
4212
|
+
runtime.pending.splice(index, 1);
|
|
4213
|
+
runtime.stats.pending--;
|
|
4214
|
+
}
|
|
4215
|
+
reject(new Error("Acquire timeout"));
|
|
4216
|
+
}, timeout2);
|
|
4217
|
+
runtime.pending.push({ resolve, reject, timeout: timer });
|
|
4218
|
+
runtime.stats.pending++;
|
|
4219
|
+
});
|
|
4220
|
+
}
|
|
4221
|
+
async function releaseConnection(runtime, connection) {
|
|
4222
|
+
const pooled = runtime.connections.find((item) => item.connection === connection);
|
|
4223
|
+
if (!pooled) {
|
|
4224
|
+
throw new Error("Connection not found in pool");
|
|
4225
|
+
}
|
|
4226
|
+
if (!pooled.inUse) {
|
|
4227
|
+
throw new Error("Connection is not in use");
|
|
4228
|
+
}
|
|
4229
|
+
pooled.inUse = false;
|
|
4230
|
+
pooled.lastUsedAt = Date.now();
|
|
4231
|
+
runtime.stats.available++;
|
|
4232
|
+
runtime.stats.acquired--;
|
|
4233
|
+
runtime.options.onRelease?.(connection);
|
|
4234
|
+
const pending = runtime.pending.shift();
|
|
4235
|
+
if (!pending) {
|
|
4236
|
+
return;
|
|
4237
|
+
}
|
|
4238
|
+
clearTimeout(pending.timeout);
|
|
4239
|
+
runtime.stats.pending--;
|
|
4240
|
+
pooled.inUse = true;
|
|
4241
|
+
pooled.lastUsedAt = Date.now();
|
|
4242
|
+
runtime.stats.available--;
|
|
4243
|
+
runtime.stats.acquired++;
|
|
4244
|
+
runtime.options.onAcquire?.(connection);
|
|
4245
|
+
pending.resolve(connection);
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
// src/resources/pool-eviction.ts
|
|
4249
|
+
function selectIdleConnectionsForEviction(runtime, idleTimeout, min, now) {
|
|
4250
|
+
const idleConnections = runtime.connections.filter(
|
|
4251
|
+
(connection) => !connection.inUse && now - connection.lastUsedAt > idleTimeout
|
|
4252
|
+
);
|
|
4253
|
+
const evictableCount = Math.max(0, runtime.connections.length - min);
|
|
4254
|
+
return idleConnections.slice(0, evictableCount);
|
|
4255
|
+
}
|
|
4256
|
+
async function evictIdleConnections(runtime) {
|
|
4257
|
+
const poolConfig = getPoolConfig(runtime);
|
|
4258
|
+
const idleTimeout = poolConfig.idleTimeout || 6e4;
|
|
4259
|
+
const min = poolConfig.min || 0;
|
|
4260
|
+
const now = Date.now();
|
|
4261
|
+
const toEvict = selectIdleConnectionsForEviction(runtime, idleTimeout, min, now);
|
|
4262
|
+
for (const pooled of toEvict) {
|
|
4263
|
+
if (!runtime.connections.includes(pooled)) {
|
|
4264
|
+
continue;
|
|
4265
|
+
}
|
|
4266
|
+
if (pooled.inUse) {
|
|
4267
|
+
continue;
|
|
4268
|
+
}
|
|
4269
|
+
if (runtime.connections.length <= min) {
|
|
4270
|
+
break;
|
|
4271
|
+
}
|
|
4272
|
+
if (Date.now() - pooled.lastUsedAt <= idleTimeout) {
|
|
4273
|
+
continue;
|
|
4211
4274
|
}
|
|
4275
|
+
await destroyConnection(runtime, pooled);
|
|
4212
4276
|
}
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
// src/resources/pool-health.ts
|
|
4280
|
+
async function runHealthCheckWithTimeout(runtime, connection, timeout2) {
|
|
4281
|
+
let timer;
|
|
4282
|
+
try {
|
|
4283
|
+
return await Promise.race([
|
|
4284
|
+
runtime.options.validator(connection),
|
|
4285
|
+
new Promise((_, reject) => {
|
|
4286
|
+
timer = setTimeout(() => reject(new Error("Health check timeout")), timeout2);
|
|
4287
|
+
})
|
|
4288
|
+
]);
|
|
4289
|
+
} finally {
|
|
4290
|
+
if (timer) {
|
|
4291
|
+
clearTimeout(timer);
|
|
4223
4292
|
}
|
|
4224
4293
|
}
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4294
|
+
}
|
|
4295
|
+
async function performHealthChecks(runtime) {
|
|
4296
|
+
if (!runtime.options.validator) {
|
|
4297
|
+
return;
|
|
4298
|
+
}
|
|
4299
|
+
const healthCheck = getHealthCheckConfig(runtime);
|
|
4300
|
+
const timeout2 = healthCheck.timeout || 5e3;
|
|
4301
|
+
const retries = healthCheck.retries || 1;
|
|
4302
|
+
for (const pooled of [...runtime.connections]) {
|
|
4303
|
+
if (pooled.inUse) {
|
|
4304
|
+
continue;
|
|
4228
4305
|
}
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
let healthy = false;
|
|
4237
|
-
for (let i = 0; i < retries; i++) {
|
|
4238
|
-
try {
|
|
4239
|
-
const result = await Promise.race([
|
|
4240
|
-
this.options.validator(pooled.connection),
|
|
4241
|
-
new Promise(
|
|
4242
|
-
(_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout2)
|
|
4243
|
-
)
|
|
4244
|
-
]);
|
|
4245
|
-
if (result) {
|
|
4246
|
-
healthy = true;
|
|
4247
|
-
break;
|
|
4248
|
-
}
|
|
4249
|
-
} catch (error) {
|
|
4306
|
+
let healthy = false;
|
|
4307
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
4308
|
+
try {
|
|
4309
|
+
const result = await runHealthCheckWithTimeout(runtime, pooled.connection, timeout2);
|
|
4310
|
+
if (result) {
|
|
4311
|
+
healthy = true;
|
|
4312
|
+
break;
|
|
4250
4313
|
}
|
|
4251
|
-
}
|
|
4252
|
-
if (healthy) {
|
|
4253
|
-
this.stats.healthChecksPassed++;
|
|
4254
|
-
} else {
|
|
4255
|
-
this.stats.healthChecksFailed++;
|
|
4256
|
-
await this.destroyConnection(pooled);
|
|
4314
|
+
} catch {
|
|
4257
4315
|
}
|
|
4258
4316
|
}
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
for (const pending of this.pending) {
|
|
4263
|
-
clearTimeout(pending.timeout);
|
|
4264
|
-
pending.reject(new Error("Pool is draining"));
|
|
4317
|
+
if (healthy) {
|
|
4318
|
+
runtime.stats.healthChecksPassed++;
|
|
4319
|
+
continue;
|
|
4265
4320
|
}
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
while (this.connections.some((c) => c.inUse)) {
|
|
4269
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4321
|
+
if (!runtime.connections.includes(pooled) || pooled.inUse) {
|
|
4322
|
+
continue;
|
|
4270
4323
|
}
|
|
4324
|
+
runtime.stats.healthChecksFailed++;
|
|
4325
|
+
await destroyConnection(runtime, pooled);
|
|
4271
4326
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
// src/resources/pool-lifecycle.ts
|
|
4330
|
+
function rejectPendingAcquisitions(runtime, message) {
|
|
4331
|
+
for (const pending of runtime.pending) {
|
|
4332
|
+
clearTimeout(pending.timeout);
|
|
4333
|
+
pending.reject(new Error(message));
|
|
4334
|
+
}
|
|
4335
|
+
runtime.pending = [];
|
|
4336
|
+
runtime.stats.pending = 0;
|
|
4337
|
+
}
|
|
4338
|
+
async function drainPool(runtime) {
|
|
4339
|
+
runtime.draining = true;
|
|
4340
|
+
rejectPendingAcquisitions(runtime, "Pool is draining");
|
|
4341
|
+
while (runtime.connections.some((connection) => connection.inUse)) {
|
|
4342
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
async function clearPool(runtime) {
|
|
4346
|
+
runtime.draining = true;
|
|
4347
|
+
rejectPendingAcquisitions(runtime, "Pool is draining");
|
|
4348
|
+
if (runtime.evictionTimer) {
|
|
4349
|
+
clearInterval(runtime.evictionTimer);
|
|
4350
|
+
runtime.evictionTimer = void 0;
|
|
4351
|
+
}
|
|
4352
|
+
if (runtime.healthCheckTimer) {
|
|
4353
|
+
clearInterval(runtime.healthCheckTimer);
|
|
4354
|
+
runtime.healthCheckTimer = void 0;
|
|
4355
|
+
}
|
|
4356
|
+
const connections = [...runtime.connections];
|
|
4357
|
+
for (const pooled of connections) {
|
|
4358
|
+
await destroyConnection(runtime, pooled);
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
|
|
4362
|
+
// src/resources/pool.ts
|
|
4363
|
+
var logger4 = createLogger("agentforge:core:resources:pool");
|
|
4364
|
+
function toErrorPayload(error) {
|
|
4365
|
+
if (error instanceof Error) {
|
|
4366
|
+
return {
|
|
4367
|
+
error: error.message,
|
|
4368
|
+
stack: error.stack
|
|
4369
|
+
};
|
|
4370
|
+
}
|
|
4371
|
+
return { error: String(error) };
|
|
4372
|
+
}
|
|
4373
|
+
function toError3(error) {
|
|
4374
|
+
if (error instanceof Error) {
|
|
4375
|
+
return error;
|
|
4376
|
+
}
|
|
4377
|
+
return new Error(String(error));
|
|
4378
|
+
}
|
|
4379
|
+
var ConnectionPool = class {
|
|
4380
|
+
runtime;
|
|
4381
|
+
constructor(options) {
|
|
4382
|
+
this.runtime = {
|
|
4383
|
+
connections: [],
|
|
4384
|
+
pending: [],
|
|
4385
|
+
stats: createInitialPoolStats(),
|
|
4386
|
+
draining: false,
|
|
4387
|
+
creating: 0,
|
|
4388
|
+
options
|
|
4389
|
+
};
|
|
4390
|
+
const poolConfig = getPoolConfig(this.runtime);
|
|
4391
|
+
const min = poolConfig.min || 0;
|
|
4392
|
+
if (min > 0) {
|
|
4393
|
+
initializeConnections(this.runtime, min).catch((error) => {
|
|
4394
|
+
logger4.error("Failed to initialize pool", toErrorPayload(error));
|
|
4395
|
+
});
|
|
4280
4396
|
}
|
|
4281
|
-
const
|
|
4282
|
-
|
|
4283
|
-
|
|
4397
|
+
const evictionInterval = poolConfig.evictionInterval || 6e4;
|
|
4398
|
+
this.runtime.evictionTimer = setInterval(() => {
|
|
4399
|
+
evictIdleConnections(this.runtime).catch((error) => {
|
|
4400
|
+
logger4.error("Failed to evict idle connections", toErrorPayload(error));
|
|
4401
|
+
});
|
|
4402
|
+
}, evictionInterval);
|
|
4403
|
+
const healthCheck = getHealthCheckConfig(this.runtime);
|
|
4404
|
+
if (healthCheck.enabled) {
|
|
4405
|
+
const interval = healthCheck.interval || 3e4;
|
|
4406
|
+
this.runtime.healthCheckTimer = setInterval(() => {
|
|
4407
|
+
performHealthChecks(this.runtime).catch((error) => {
|
|
4408
|
+
const normalizedError = toError3(error);
|
|
4409
|
+
logger4.error("Health check failed", toErrorPayload(normalizedError));
|
|
4410
|
+
options.onHealthCheckFail?.(normalizedError);
|
|
4411
|
+
});
|
|
4412
|
+
}, interval);
|
|
4284
4413
|
}
|
|
4285
4414
|
}
|
|
4415
|
+
async acquire() {
|
|
4416
|
+
return acquireConnection(this.runtime);
|
|
4417
|
+
}
|
|
4418
|
+
async release(connection) {
|
|
4419
|
+
return releaseConnection(this.runtime, connection);
|
|
4420
|
+
}
|
|
4421
|
+
async drain() {
|
|
4422
|
+
return drainPool(this.runtime);
|
|
4423
|
+
}
|
|
4424
|
+
async clear() {
|
|
4425
|
+
return clearPool(this.runtime);
|
|
4426
|
+
}
|
|
4286
4427
|
getStats() {
|
|
4287
|
-
return
|
|
4428
|
+
return clonePoolStats(this.runtime);
|
|
4288
4429
|
}
|
|
4289
4430
|
};
|
|
4290
4431
|
function createConnectionPool(options) {
|
|
@@ -4817,7 +4958,7 @@ function createCircuitBreaker(options) {
|
|
|
4817
4958
|
}
|
|
4818
4959
|
|
|
4819
4960
|
// src/monitoring/health.ts
|
|
4820
|
-
var
|
|
4961
|
+
var logger5 = createLogger("agentforge:core:monitoring:health", { level: "info" /* INFO */ });
|
|
4821
4962
|
var HealthChecker = class {
|
|
4822
4963
|
constructor(options) {
|
|
4823
4964
|
this.options = options;
|
|
@@ -4833,14 +4974,14 @@ var HealthChecker = class {
|
|
|
4833
4974
|
this.running = true;
|
|
4834
4975
|
const interval = this.options.interval || 3e4;
|
|
4835
4976
|
this.runChecks().catch((error) => {
|
|
4836
|
-
|
|
4977
|
+
logger5.error("Initial health check failed", {
|
|
4837
4978
|
error: error instanceof Error ? error.message : String(error),
|
|
4838
4979
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
4839
4980
|
});
|
|
4840
4981
|
});
|
|
4841
4982
|
this.checkTimer = setInterval(() => {
|
|
4842
4983
|
this.runChecks().catch((error) => {
|
|
4843
|
-
|
|
4984
|
+
logger5.error("Health check failed", {
|
|
4844
4985
|
error: error instanceof Error ? error.message : String(error),
|
|
4845
4986
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
4846
4987
|
});
|
|
@@ -5050,7 +5191,7 @@ function createProfiler(options) {
|
|
|
5050
5191
|
}
|
|
5051
5192
|
|
|
5052
5193
|
// src/monitoring/alerts.ts
|
|
5053
|
-
var
|
|
5194
|
+
var logger6 = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5054
5195
|
function toAlertSummary(alert) {
|
|
5055
5196
|
return {
|
|
5056
5197
|
name: alert.name,
|
|
@@ -5102,7 +5243,7 @@ var AlertManager = class {
|
|
|
5102
5243
|
const currentMetrics = metrics();
|
|
5103
5244
|
this.checkRules(currentMetrics);
|
|
5104
5245
|
} catch (error) {
|
|
5105
|
-
|
|
5246
|
+
logger6.error("Metrics collection failed", toMetricsProviderErrorPayload(error));
|
|
5106
5247
|
}
|
|
5107
5248
|
}, interval);
|
|
5108
5249
|
}
|
|
@@ -5128,9 +5269,9 @@ var AlertManager = class {
|
|
|
5128
5269
|
try {
|
|
5129
5270
|
await this.options.onAlert?.(fullAlert);
|
|
5130
5271
|
} catch (error) {
|
|
5131
|
-
|
|
5272
|
+
logger6.error("Alert callback failed", toAlertCallbackErrorPayload(error));
|
|
5132
5273
|
}
|
|
5133
|
-
|
|
5274
|
+
logger6.warn("Alert triggered", {
|
|
5134
5275
|
name: alert.name,
|
|
5135
5276
|
severity: alert.severity,
|
|
5136
5277
|
message: alert.message,
|
|
@@ -5150,11 +5291,11 @@ var AlertManager = class {
|
|
|
5150
5291
|
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5151
5292
|
data: { metrics }
|
|
5152
5293
|
}).catch((error) => {
|
|
5153
|
-
|
|
5294
|
+
logger6.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5154
5295
|
});
|
|
5155
5296
|
}
|
|
5156
5297
|
} catch (error) {
|
|
5157
|
-
|
|
5298
|
+
logger6.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5158
5299
|
}
|
|
5159
5300
|
}
|
|
5160
5301
|
}
|
|
@@ -5176,28 +5317,28 @@ var AlertManager = class {
|
|
|
5176
5317
|
}
|
|
5177
5318
|
switch (channel.type) {
|
|
5178
5319
|
case "email":
|
|
5179
|
-
|
|
5320
|
+
logger6.info("Alert sent to email", {
|
|
5180
5321
|
channel: channelName,
|
|
5181
5322
|
to: channel.config.to,
|
|
5182
5323
|
alert: toAlertSummary(alert)
|
|
5183
5324
|
});
|
|
5184
5325
|
break;
|
|
5185
5326
|
case "slack":
|
|
5186
|
-
|
|
5327
|
+
logger6.info("Alert sent to Slack", {
|
|
5187
5328
|
channel: channelName,
|
|
5188
5329
|
webhookUrl: channel.config.webhookUrl,
|
|
5189
5330
|
alert: toAlertSummary(alert)
|
|
5190
5331
|
});
|
|
5191
5332
|
break;
|
|
5192
5333
|
case "webhook":
|
|
5193
|
-
|
|
5334
|
+
logger6.info("Alert sent to webhook", {
|
|
5194
5335
|
channel: channelName,
|
|
5195
5336
|
url: channel.config.url,
|
|
5196
5337
|
alert: toAlertSummary(alert)
|
|
5197
5338
|
});
|
|
5198
5339
|
break;
|
|
5199
5340
|
default:
|
|
5200
|
-
|
|
5341
|
+
logger6.info("Alert sent", {
|
|
5201
5342
|
channel: channelName,
|
|
5202
5343
|
channelType: channel.type,
|
|
5203
5344
|
alert: toAlertSummary(alert)
|