@agentforge/core 0.16.66 → 0.16.68
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 +113 -98
- package/dist/index.d.cts +1 -6
- package/dist/index.d.ts +1 -6
- package/dist/index.js +113 -98
- package/package.json +3 -3
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, logger6) {
|
|
1355
1355
|
const executeFn = tool.invoke || tool.execute;
|
|
1356
1356
|
if (!executeFn) {
|
|
1357
1357
|
throw new Error(
|
|
@@ -1359,14 +1359,14 @@ function resolveExecutionMethod(tool, logger7) {
|
|
|
1359
1359
|
);
|
|
1360
1360
|
}
|
|
1361
1361
|
if (!tool.invoke && tool.execute) {
|
|
1362
|
-
|
|
1362
|
+
logger6.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, logger6) {
|
|
1369
|
+
const executeFn = resolveExecutionMethod(tool, logger6);
|
|
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: logger6,
|
|
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) => logger6.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 logger6 = 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
|
+
logger6.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
|
+
logger6.info(`Node execution completed (${duration}ms)`, data);
|
|
2646
2646
|
} else {
|
|
2647
|
-
|
|
2647
|
+
logger6.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
|
+
logger6.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: logger6,
|
|
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 = logger6 || 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: logger6 } = options;
|
|
2844
|
+
const actualLogger = logger6 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2845
2845
|
return withLogging2({
|
|
2846
2846
|
logger: actualLogger,
|
|
2847
2847
|
name: nodeName,
|
|
@@ -5351,8 +5351,8 @@ function createProfiler(options) {
|
|
|
5351
5351
|
return new Profiler(options);
|
|
5352
5352
|
}
|
|
5353
5353
|
|
|
5354
|
-
// src/monitoring/alerts.ts
|
|
5355
|
-
var
|
|
5354
|
+
// src/monitoring/alerts-shared.ts
|
|
5355
|
+
var alertLogger = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5356
5356
|
function toAlertSummary(alert) {
|
|
5357
5357
|
return {
|
|
5358
5358
|
name: alert.name,
|
|
@@ -5360,13 +5360,57 @@ function toAlertSummary(alert) {
|
|
|
5360
5360
|
message: alert.message
|
|
5361
5361
|
};
|
|
5362
5362
|
}
|
|
5363
|
-
|
|
5363
|
+
|
|
5364
|
+
// src/monitoring/alerts-channels.ts
|
|
5365
|
+
async function sendAlertToChannel(channels, channelName, alert) {
|
|
5366
|
+
const channel = channels[channelName];
|
|
5367
|
+
if (!channel) {
|
|
5368
|
+
throw new Error(`Channel not found: ${channelName}`);
|
|
5369
|
+
}
|
|
5370
|
+
switch (channel.type) {
|
|
5371
|
+
case "email":
|
|
5372
|
+
alertLogger.info("Alert sent to email", {
|
|
5373
|
+
channel: channelName,
|
|
5374
|
+
to: channel.config.to,
|
|
5375
|
+
alert: toAlertSummary(alert)
|
|
5376
|
+
});
|
|
5377
|
+
return;
|
|
5378
|
+
case "slack":
|
|
5379
|
+
alertLogger.info("Alert sent to Slack", {
|
|
5380
|
+
channel: channelName,
|
|
5381
|
+
webhookUrl: channel.config.webhookUrl,
|
|
5382
|
+
alert: toAlertSummary(alert)
|
|
5383
|
+
});
|
|
5384
|
+
return;
|
|
5385
|
+
case "webhook":
|
|
5386
|
+
alertLogger.info("Alert sent to webhook", {
|
|
5387
|
+
channel: channelName,
|
|
5388
|
+
url: channel.config.url,
|
|
5389
|
+
alert: toAlertSummary(alert)
|
|
5390
|
+
});
|
|
5391
|
+
return;
|
|
5392
|
+
default:
|
|
5393
|
+
alertLogger.info("Alert sent", {
|
|
5394
|
+
channel: channelName,
|
|
5395
|
+
channelType: channel.type,
|
|
5396
|
+
alert: toAlertSummary(alert)
|
|
5397
|
+
});
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
// src/monitoring/alerts-errors.ts
|
|
5402
|
+
function toErrorDetails(error) {
|
|
5364
5403
|
return {
|
|
5365
|
-
ruleName,
|
|
5366
5404
|
error: error instanceof Error ? error.message : String(error),
|
|
5367
5405
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5368
5406
|
};
|
|
5369
5407
|
}
|
|
5408
|
+
function toRuleErrorPayload(ruleName, error) {
|
|
5409
|
+
return {
|
|
5410
|
+
ruleName,
|
|
5411
|
+
...toErrorDetails(error)
|
|
5412
|
+
};
|
|
5413
|
+
}
|
|
5370
5414
|
function toAlertDispatchErrorPayload(ruleName, error) {
|
|
5371
5415
|
return {
|
|
5372
5416
|
stage: "alert-dispatch",
|
|
@@ -5376,17 +5420,52 @@ function toAlertDispatchErrorPayload(ruleName, error) {
|
|
|
5376
5420
|
function toAlertCallbackErrorPayload(error) {
|
|
5377
5421
|
return {
|
|
5378
5422
|
stage: "alert-callback",
|
|
5379
|
-
|
|
5380
|
-
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5423
|
+
...toErrorDetails(error)
|
|
5381
5424
|
};
|
|
5382
5425
|
}
|
|
5383
5426
|
function toMetricsProviderErrorPayload(error) {
|
|
5384
5427
|
return {
|
|
5385
5428
|
stage: "metrics-provider",
|
|
5386
|
-
|
|
5387
|
-
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5429
|
+
...toErrorDetails(error)
|
|
5388
5430
|
};
|
|
5389
5431
|
}
|
|
5432
|
+
|
|
5433
|
+
// src/monitoring/alerts-rules.ts
|
|
5434
|
+
function checkAlertRules(rules, metrics, alert) {
|
|
5435
|
+
if (!rules) {
|
|
5436
|
+
return;
|
|
5437
|
+
}
|
|
5438
|
+
for (const rule of rules) {
|
|
5439
|
+
try {
|
|
5440
|
+
if (!rule.condition(metrics)) {
|
|
5441
|
+
continue;
|
|
5442
|
+
}
|
|
5443
|
+
void alert({
|
|
5444
|
+
name: rule.name,
|
|
5445
|
+
severity: rule.severity,
|
|
5446
|
+
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5447
|
+
data: { metrics }
|
|
5448
|
+
}).catch((error) => {
|
|
5449
|
+
alertLogger.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5450
|
+
});
|
|
5451
|
+
} catch (error) {
|
|
5452
|
+
alertLogger.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
function isAlertThrottled(rules, name, lastAlertTime, now) {
|
|
5457
|
+
const rule = rules?.find((candidate) => candidate.name === name);
|
|
5458
|
+
if (!rule?.throttle) {
|
|
5459
|
+
return false;
|
|
5460
|
+
}
|
|
5461
|
+
const lastTime = lastAlertTime.get(name);
|
|
5462
|
+
if (!lastTime) {
|
|
5463
|
+
return false;
|
|
5464
|
+
}
|
|
5465
|
+
return now - lastTime < rule.throttle;
|
|
5466
|
+
}
|
|
5467
|
+
|
|
5468
|
+
// src/monitoring/alerts-manager.ts
|
|
5390
5469
|
var AlertManager = class {
|
|
5391
5470
|
constructor(options) {
|
|
5392
5471
|
this.options = options;
|
|
@@ -5401,10 +5480,9 @@ var AlertManager = class {
|
|
|
5401
5480
|
this.running = true;
|
|
5402
5481
|
this.monitorTimer = setInterval(() => {
|
|
5403
5482
|
try {
|
|
5404
|
-
|
|
5405
|
-
this.checkRules(currentMetrics);
|
|
5483
|
+
checkAlertRules(this.options.rules, metrics(), (alert) => this.alert(alert));
|
|
5406
5484
|
} catch (error) {
|
|
5407
|
-
|
|
5485
|
+
alertLogger.error("Metrics collection failed", toMetricsProviderErrorPayload(error));
|
|
5408
5486
|
}
|
|
5409
5487
|
}, interval);
|
|
5410
5488
|
}
|
|
@@ -5419,92 +5497,29 @@ var AlertManager = class {
|
|
|
5419
5497
|
}
|
|
5420
5498
|
}
|
|
5421
5499
|
async alert(alert) {
|
|
5500
|
+
const now = Date.now();
|
|
5422
5501
|
const fullAlert = {
|
|
5423
5502
|
...alert,
|
|
5424
|
-
timestamp: alert.timestamp ??
|
|
5503
|
+
timestamp: alert.timestamp ?? now
|
|
5425
5504
|
};
|
|
5426
|
-
if (this.
|
|
5505
|
+
if (isAlertThrottled(this.options.rules, alert.name, this.lastAlertTime, now)) {
|
|
5427
5506
|
return;
|
|
5428
5507
|
}
|
|
5429
|
-
this.lastAlertTime.set(alert.name,
|
|
5508
|
+
this.lastAlertTime.set(alert.name, now);
|
|
5430
5509
|
try {
|
|
5431
5510
|
await this.options.onAlert?.(fullAlert);
|
|
5432
5511
|
} catch (error) {
|
|
5433
|
-
|
|
5512
|
+
alertLogger.error("Alert callback failed", toAlertCallbackErrorPayload(error));
|
|
5434
5513
|
}
|
|
5435
|
-
|
|
5514
|
+
alertLogger.warn("Alert triggered", {
|
|
5436
5515
|
name: alert.name,
|
|
5437
5516
|
severity: alert.severity,
|
|
5438
5517
|
message: alert.message,
|
|
5439
5518
|
...alert.data ? { data: alert.data } : {}
|
|
5440
5519
|
});
|
|
5441
5520
|
}
|
|
5442
|
-
checkRules(metrics) {
|
|
5443
|
-
if (!this.options.rules) {
|
|
5444
|
-
return;
|
|
5445
|
-
}
|
|
5446
|
-
for (const rule of this.options.rules) {
|
|
5447
|
-
try {
|
|
5448
|
-
if (rule.condition(metrics)) {
|
|
5449
|
-
void this.alert({
|
|
5450
|
-
name: rule.name,
|
|
5451
|
-
severity: rule.severity,
|
|
5452
|
-
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5453
|
-
data: { metrics }
|
|
5454
|
-
}).catch((error) => {
|
|
5455
|
-
logger6.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5456
|
-
});
|
|
5457
|
-
}
|
|
5458
|
-
} catch (error) {
|
|
5459
|
-
logger6.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5460
|
-
}
|
|
5461
|
-
}
|
|
5462
|
-
}
|
|
5463
|
-
isThrottled(name) {
|
|
5464
|
-
const rule = this.options.rules?.find((r) => r.name === name);
|
|
5465
|
-
if (!rule?.throttle) {
|
|
5466
|
-
return false;
|
|
5467
|
-
}
|
|
5468
|
-
const lastTime = this.lastAlertTime.get(name);
|
|
5469
|
-
if (!lastTime) {
|
|
5470
|
-
return false;
|
|
5471
|
-
}
|
|
5472
|
-
return Date.now() - lastTime < rule.throttle;
|
|
5473
|
-
}
|
|
5474
5521
|
async sendToChannel(channelName, alert) {
|
|
5475
|
-
|
|
5476
|
-
if (!channel) {
|
|
5477
|
-
throw new Error(`Channel not found: ${channelName}`);
|
|
5478
|
-
}
|
|
5479
|
-
switch (channel.type) {
|
|
5480
|
-
case "email":
|
|
5481
|
-
logger6.info("Alert sent to email", {
|
|
5482
|
-
channel: channelName,
|
|
5483
|
-
to: channel.config.to,
|
|
5484
|
-
alert: toAlertSummary(alert)
|
|
5485
|
-
});
|
|
5486
|
-
break;
|
|
5487
|
-
case "slack":
|
|
5488
|
-
logger6.info("Alert sent to Slack", {
|
|
5489
|
-
channel: channelName,
|
|
5490
|
-
webhookUrl: channel.config.webhookUrl,
|
|
5491
|
-
alert: toAlertSummary(alert)
|
|
5492
|
-
});
|
|
5493
|
-
break;
|
|
5494
|
-
case "webhook":
|
|
5495
|
-
logger6.info("Alert sent to webhook", {
|
|
5496
|
-
channel: channelName,
|
|
5497
|
-
url: channel.config.url,
|
|
5498
|
-
alert: toAlertSummary(alert)
|
|
5499
|
-
});
|
|
5500
|
-
break;
|
|
5501
|
-
default:
|
|
5502
|
-
logger6.info("Alert sent", {
|
|
5503
|
-
channel: channelName,
|
|
5504
|
-
channelType: channel.type,
|
|
5505
|
-
alert: toAlertSummary(alert)
|
|
5506
|
-
});
|
|
5507
|
-
}
|
|
5522
|
+
await sendAlertToChannel(this.options.channels, channelName, alert);
|
|
5508
5523
|
}
|
|
5509
5524
|
getAlertHistory(_name, _limit = 100) {
|
|
5510
5525
|
return [];
|
|
@@ -5512,9 +5527,9 @@ var AlertManager = class {
|
|
|
5512
5527
|
clearAlertHistory(name) {
|
|
5513
5528
|
if (name) {
|
|
5514
5529
|
this.lastAlertTime.delete(name);
|
|
5515
|
-
|
|
5516
|
-
this.lastAlertTime.clear();
|
|
5530
|
+
return;
|
|
5517
5531
|
}
|
|
5532
|
+
this.lastAlertTime.clear();
|
|
5518
5533
|
}
|
|
5519
5534
|
};
|
|
5520
5535
|
function createAlertManager(options) {
|
package/dist/index.d.cts
CHANGED
|
@@ -4440,10 +4440,6 @@ declare class Profiler {
|
|
|
4440
4440
|
}
|
|
4441
4441
|
declare function createProfiler(options?: ProfilerOptions): Profiler;
|
|
4442
4442
|
|
|
4443
|
-
/**
|
|
4444
|
-
* Alert system for production monitoring
|
|
4445
|
-
*/
|
|
4446
|
-
|
|
4447
4443
|
type AlertSeverity = 'info' | 'warning' | 'error' | 'critical';
|
|
4448
4444
|
interface Alert<TData extends JsonObject = JsonObject> {
|
|
4449
4445
|
name: string;
|
|
@@ -4501,6 +4497,7 @@ interface AlertManagerOptions<TMetrics extends JsonObject = JsonObject, TChannel
|
|
|
4501
4497
|
rules?: AlertRule<TMetrics, AlertChannelName<TChannels>>[];
|
|
4502
4498
|
onAlert?: (alert: Alert<AlertCallbackData<TMetrics>>) => void | Promise<void>;
|
|
4503
4499
|
}
|
|
4500
|
+
|
|
4504
4501
|
declare class AlertManager<TMetrics extends JsonObject = JsonObject, TChannels extends AlertChannelMap = Record<string, GenericAlertChannel>> {
|
|
4505
4502
|
private options;
|
|
4506
4503
|
private lastAlertTime;
|
|
@@ -4510,8 +4507,6 @@ declare class AlertManager<TMetrics extends JsonObject = JsonObject, TChannels e
|
|
|
4510
4507
|
start(metrics?: () => TMetrics, interval?: number): void;
|
|
4511
4508
|
stop(): void;
|
|
4512
4509
|
alert(alert: Alert<AlertCallbackData<TMetrics>>): Promise<void>;
|
|
4513
|
-
private checkRules;
|
|
4514
|
-
private isThrottled;
|
|
4515
4510
|
sendToChannel(channelName: keyof TChannels & string, alert: Alert<AlertCallbackData<TMetrics>>): Promise<void>;
|
|
4516
4511
|
getAlertHistory(_name?: string, _limit?: number): Alert<AlertCallbackData<TMetrics>>[];
|
|
4517
4512
|
clearAlertHistory(name?: string): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -4440,10 +4440,6 @@ declare class Profiler {
|
|
|
4440
4440
|
}
|
|
4441
4441
|
declare function createProfiler(options?: ProfilerOptions): Profiler;
|
|
4442
4442
|
|
|
4443
|
-
/**
|
|
4444
|
-
* Alert system for production monitoring
|
|
4445
|
-
*/
|
|
4446
|
-
|
|
4447
4443
|
type AlertSeverity = 'info' | 'warning' | 'error' | 'critical';
|
|
4448
4444
|
interface Alert<TData extends JsonObject = JsonObject> {
|
|
4449
4445
|
name: string;
|
|
@@ -4501,6 +4497,7 @@ interface AlertManagerOptions<TMetrics extends JsonObject = JsonObject, TChannel
|
|
|
4501
4497
|
rules?: AlertRule<TMetrics, AlertChannelName<TChannels>>[];
|
|
4502
4498
|
onAlert?: (alert: Alert<AlertCallbackData<TMetrics>>) => void | Promise<void>;
|
|
4503
4499
|
}
|
|
4500
|
+
|
|
4504
4501
|
declare class AlertManager<TMetrics extends JsonObject = JsonObject, TChannels extends AlertChannelMap = Record<string, GenericAlertChannel>> {
|
|
4505
4502
|
private options;
|
|
4506
4503
|
private lastAlertTime;
|
|
@@ -4510,8 +4507,6 @@ declare class AlertManager<TMetrics extends JsonObject = JsonObject, TChannels e
|
|
|
4510
4507
|
start(metrics?: () => TMetrics, interval?: number): void;
|
|
4511
4508
|
stop(): void;
|
|
4512
4509
|
alert(alert: Alert<AlertCallbackData<TMetrics>>): Promise<void>;
|
|
4513
|
-
private checkRules;
|
|
4514
|
-
private isThrottled;
|
|
4515
4510
|
sendToChannel(channelName: keyof TChannels & string, alert: Alert<AlertCallbackData<TMetrics>>): Promise<void>;
|
|
4516
4511
|
getAlertHistory(_name?: string, _limit?: number): Alert<AlertCallbackData<TMetrics>>[];
|
|
4517
4512
|
clearAlertHistory(name?: string): void;
|
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, logger6) {
|
|
1180
1180
|
const executeFn = tool.invoke || tool.execute;
|
|
1181
1181
|
if (!executeFn) {
|
|
1182
1182
|
throw new Error(
|
|
@@ -1184,14 +1184,14 @@ function resolveExecutionMethod(tool, logger7) {
|
|
|
1184
1184
|
);
|
|
1185
1185
|
}
|
|
1186
1186
|
if (!tool.invoke && tool.execute) {
|
|
1187
|
-
|
|
1187
|
+
logger6.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, logger6) {
|
|
1194
|
+
const executeFn = resolveExecutionMethod(tool, logger6);
|
|
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: logger6,
|
|
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) => logger6.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 logger6 = 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
|
+
logger6.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
|
+
logger6.info(`Node execution completed (${duration}ms)`, data);
|
|
2471
2471
|
} else {
|
|
2472
|
-
|
|
2472
|
+
logger6.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
|
+
logger6.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: logger6,
|
|
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 = logger6 || 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: logger6 } = options;
|
|
2669
|
+
const actualLogger = logger6 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2670
2670
|
return withLogging2({
|
|
2671
2671
|
logger: actualLogger,
|
|
2672
2672
|
name: nodeName,
|
|
@@ -5176,8 +5176,8 @@ function createProfiler(options) {
|
|
|
5176
5176
|
return new Profiler(options);
|
|
5177
5177
|
}
|
|
5178
5178
|
|
|
5179
|
-
// src/monitoring/alerts.ts
|
|
5180
|
-
var
|
|
5179
|
+
// src/monitoring/alerts-shared.ts
|
|
5180
|
+
var alertLogger = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5181
5181
|
function toAlertSummary(alert) {
|
|
5182
5182
|
return {
|
|
5183
5183
|
name: alert.name,
|
|
@@ -5185,13 +5185,57 @@ function toAlertSummary(alert) {
|
|
|
5185
5185
|
message: alert.message
|
|
5186
5186
|
};
|
|
5187
5187
|
}
|
|
5188
|
-
|
|
5188
|
+
|
|
5189
|
+
// src/monitoring/alerts-channels.ts
|
|
5190
|
+
async function sendAlertToChannel(channels, channelName, alert) {
|
|
5191
|
+
const channel = channels[channelName];
|
|
5192
|
+
if (!channel) {
|
|
5193
|
+
throw new Error(`Channel not found: ${channelName}`);
|
|
5194
|
+
}
|
|
5195
|
+
switch (channel.type) {
|
|
5196
|
+
case "email":
|
|
5197
|
+
alertLogger.info("Alert sent to email", {
|
|
5198
|
+
channel: channelName,
|
|
5199
|
+
to: channel.config.to,
|
|
5200
|
+
alert: toAlertSummary(alert)
|
|
5201
|
+
});
|
|
5202
|
+
return;
|
|
5203
|
+
case "slack":
|
|
5204
|
+
alertLogger.info("Alert sent to Slack", {
|
|
5205
|
+
channel: channelName,
|
|
5206
|
+
webhookUrl: channel.config.webhookUrl,
|
|
5207
|
+
alert: toAlertSummary(alert)
|
|
5208
|
+
});
|
|
5209
|
+
return;
|
|
5210
|
+
case "webhook":
|
|
5211
|
+
alertLogger.info("Alert sent to webhook", {
|
|
5212
|
+
channel: channelName,
|
|
5213
|
+
url: channel.config.url,
|
|
5214
|
+
alert: toAlertSummary(alert)
|
|
5215
|
+
});
|
|
5216
|
+
return;
|
|
5217
|
+
default:
|
|
5218
|
+
alertLogger.info("Alert sent", {
|
|
5219
|
+
channel: channelName,
|
|
5220
|
+
channelType: channel.type,
|
|
5221
|
+
alert: toAlertSummary(alert)
|
|
5222
|
+
});
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
|
|
5226
|
+
// src/monitoring/alerts-errors.ts
|
|
5227
|
+
function toErrorDetails(error) {
|
|
5189
5228
|
return {
|
|
5190
|
-
ruleName,
|
|
5191
5229
|
error: error instanceof Error ? error.message : String(error),
|
|
5192
5230
|
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5193
5231
|
};
|
|
5194
5232
|
}
|
|
5233
|
+
function toRuleErrorPayload(ruleName, error) {
|
|
5234
|
+
return {
|
|
5235
|
+
ruleName,
|
|
5236
|
+
...toErrorDetails(error)
|
|
5237
|
+
};
|
|
5238
|
+
}
|
|
5195
5239
|
function toAlertDispatchErrorPayload(ruleName, error) {
|
|
5196
5240
|
return {
|
|
5197
5241
|
stage: "alert-dispatch",
|
|
@@ -5201,17 +5245,52 @@ function toAlertDispatchErrorPayload(ruleName, error) {
|
|
|
5201
5245
|
function toAlertCallbackErrorPayload(error) {
|
|
5202
5246
|
return {
|
|
5203
5247
|
stage: "alert-callback",
|
|
5204
|
-
|
|
5205
|
-
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5248
|
+
...toErrorDetails(error)
|
|
5206
5249
|
};
|
|
5207
5250
|
}
|
|
5208
5251
|
function toMetricsProviderErrorPayload(error) {
|
|
5209
5252
|
return {
|
|
5210
5253
|
stage: "metrics-provider",
|
|
5211
|
-
|
|
5212
|
-
...error instanceof Error && error.stack ? { stack: error.stack } : {}
|
|
5254
|
+
...toErrorDetails(error)
|
|
5213
5255
|
};
|
|
5214
5256
|
}
|
|
5257
|
+
|
|
5258
|
+
// src/monitoring/alerts-rules.ts
|
|
5259
|
+
function checkAlertRules(rules, metrics, alert) {
|
|
5260
|
+
if (!rules) {
|
|
5261
|
+
return;
|
|
5262
|
+
}
|
|
5263
|
+
for (const rule of rules) {
|
|
5264
|
+
try {
|
|
5265
|
+
if (!rule.condition(metrics)) {
|
|
5266
|
+
continue;
|
|
5267
|
+
}
|
|
5268
|
+
void alert({
|
|
5269
|
+
name: rule.name,
|
|
5270
|
+
severity: rule.severity,
|
|
5271
|
+
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5272
|
+
data: { metrics }
|
|
5273
|
+
}).catch((error) => {
|
|
5274
|
+
alertLogger.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5275
|
+
});
|
|
5276
|
+
} catch (error) {
|
|
5277
|
+
alertLogger.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
function isAlertThrottled(rules, name, lastAlertTime, now) {
|
|
5282
|
+
const rule = rules?.find((candidate) => candidate.name === name);
|
|
5283
|
+
if (!rule?.throttle) {
|
|
5284
|
+
return false;
|
|
5285
|
+
}
|
|
5286
|
+
const lastTime = lastAlertTime.get(name);
|
|
5287
|
+
if (!lastTime) {
|
|
5288
|
+
return false;
|
|
5289
|
+
}
|
|
5290
|
+
return now - lastTime < rule.throttle;
|
|
5291
|
+
}
|
|
5292
|
+
|
|
5293
|
+
// src/monitoring/alerts-manager.ts
|
|
5215
5294
|
var AlertManager = class {
|
|
5216
5295
|
constructor(options) {
|
|
5217
5296
|
this.options = options;
|
|
@@ -5226,10 +5305,9 @@ var AlertManager = class {
|
|
|
5226
5305
|
this.running = true;
|
|
5227
5306
|
this.monitorTimer = setInterval(() => {
|
|
5228
5307
|
try {
|
|
5229
|
-
|
|
5230
|
-
this.checkRules(currentMetrics);
|
|
5308
|
+
checkAlertRules(this.options.rules, metrics(), (alert) => this.alert(alert));
|
|
5231
5309
|
} catch (error) {
|
|
5232
|
-
|
|
5310
|
+
alertLogger.error("Metrics collection failed", toMetricsProviderErrorPayload(error));
|
|
5233
5311
|
}
|
|
5234
5312
|
}, interval);
|
|
5235
5313
|
}
|
|
@@ -5244,92 +5322,29 @@ var AlertManager = class {
|
|
|
5244
5322
|
}
|
|
5245
5323
|
}
|
|
5246
5324
|
async alert(alert) {
|
|
5325
|
+
const now = Date.now();
|
|
5247
5326
|
const fullAlert = {
|
|
5248
5327
|
...alert,
|
|
5249
|
-
timestamp: alert.timestamp ??
|
|
5328
|
+
timestamp: alert.timestamp ?? now
|
|
5250
5329
|
};
|
|
5251
|
-
if (this.
|
|
5330
|
+
if (isAlertThrottled(this.options.rules, alert.name, this.lastAlertTime, now)) {
|
|
5252
5331
|
return;
|
|
5253
5332
|
}
|
|
5254
|
-
this.lastAlertTime.set(alert.name,
|
|
5333
|
+
this.lastAlertTime.set(alert.name, now);
|
|
5255
5334
|
try {
|
|
5256
5335
|
await this.options.onAlert?.(fullAlert);
|
|
5257
5336
|
} catch (error) {
|
|
5258
|
-
|
|
5337
|
+
alertLogger.error("Alert callback failed", toAlertCallbackErrorPayload(error));
|
|
5259
5338
|
}
|
|
5260
|
-
|
|
5339
|
+
alertLogger.warn("Alert triggered", {
|
|
5261
5340
|
name: alert.name,
|
|
5262
5341
|
severity: alert.severity,
|
|
5263
5342
|
message: alert.message,
|
|
5264
5343
|
...alert.data ? { data: alert.data } : {}
|
|
5265
5344
|
});
|
|
5266
5345
|
}
|
|
5267
|
-
checkRules(metrics) {
|
|
5268
|
-
if (!this.options.rules) {
|
|
5269
|
-
return;
|
|
5270
|
-
}
|
|
5271
|
-
for (const rule of this.options.rules) {
|
|
5272
|
-
try {
|
|
5273
|
-
if (rule.condition(metrics)) {
|
|
5274
|
-
void this.alert({
|
|
5275
|
-
name: rule.name,
|
|
5276
|
-
severity: rule.severity,
|
|
5277
|
-
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5278
|
-
data: { metrics }
|
|
5279
|
-
}).catch((error) => {
|
|
5280
|
-
logger6.error("Alert dispatch failed", toAlertDispatchErrorPayload(rule.name, error));
|
|
5281
|
-
});
|
|
5282
|
-
}
|
|
5283
|
-
} catch (error) {
|
|
5284
|
-
logger6.error("Rule check failed", toRuleErrorPayload(rule.name, error));
|
|
5285
|
-
}
|
|
5286
|
-
}
|
|
5287
|
-
}
|
|
5288
|
-
isThrottled(name) {
|
|
5289
|
-
const rule = this.options.rules?.find((r) => r.name === name);
|
|
5290
|
-
if (!rule?.throttle) {
|
|
5291
|
-
return false;
|
|
5292
|
-
}
|
|
5293
|
-
const lastTime = this.lastAlertTime.get(name);
|
|
5294
|
-
if (!lastTime) {
|
|
5295
|
-
return false;
|
|
5296
|
-
}
|
|
5297
|
-
return Date.now() - lastTime < rule.throttle;
|
|
5298
|
-
}
|
|
5299
5346
|
async sendToChannel(channelName, alert) {
|
|
5300
|
-
|
|
5301
|
-
if (!channel) {
|
|
5302
|
-
throw new Error(`Channel not found: ${channelName}`);
|
|
5303
|
-
}
|
|
5304
|
-
switch (channel.type) {
|
|
5305
|
-
case "email":
|
|
5306
|
-
logger6.info("Alert sent to email", {
|
|
5307
|
-
channel: channelName,
|
|
5308
|
-
to: channel.config.to,
|
|
5309
|
-
alert: toAlertSummary(alert)
|
|
5310
|
-
});
|
|
5311
|
-
break;
|
|
5312
|
-
case "slack":
|
|
5313
|
-
logger6.info("Alert sent to Slack", {
|
|
5314
|
-
channel: channelName,
|
|
5315
|
-
webhookUrl: channel.config.webhookUrl,
|
|
5316
|
-
alert: toAlertSummary(alert)
|
|
5317
|
-
});
|
|
5318
|
-
break;
|
|
5319
|
-
case "webhook":
|
|
5320
|
-
logger6.info("Alert sent to webhook", {
|
|
5321
|
-
channel: channelName,
|
|
5322
|
-
url: channel.config.url,
|
|
5323
|
-
alert: toAlertSummary(alert)
|
|
5324
|
-
});
|
|
5325
|
-
break;
|
|
5326
|
-
default:
|
|
5327
|
-
logger6.info("Alert sent", {
|
|
5328
|
-
channel: channelName,
|
|
5329
|
-
channelType: channel.type,
|
|
5330
|
-
alert: toAlertSummary(alert)
|
|
5331
|
-
});
|
|
5332
|
-
}
|
|
5347
|
+
await sendAlertToChannel(this.options.channels, channelName, alert);
|
|
5333
5348
|
}
|
|
5334
5349
|
getAlertHistory(_name, _limit = 100) {
|
|
5335
5350
|
return [];
|
|
@@ -5337,9 +5352,9 @@ var AlertManager = class {
|
|
|
5337
5352
|
clearAlertHistory(name) {
|
|
5338
5353
|
if (name) {
|
|
5339
5354
|
this.lastAlertTime.delete(name);
|
|
5340
|
-
|
|
5341
|
-
this.lastAlertTime.clear();
|
|
5355
|
+
return;
|
|
5342
5356
|
}
|
|
5357
|
+
this.lastAlertTime.clear();
|
|
5343
5358
|
}
|
|
5344
5359
|
};
|
|
5345
5360
|
function createAlertManager(options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/core",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.68",
|
|
4
4
|
"description": "Production-ready TypeScript agent framework built on LangGraph with orchestration, middleware, and typed abstractions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
63
63
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
64
|
-
"test": "vitest",
|
|
65
|
-
"test:coverage": "vitest --coverage",
|
|
64
|
+
"test": "vitest --config vitest.config.ts",
|
|
65
|
+
"test:coverage": "vitest --config vitest.config.ts --coverage",
|
|
66
66
|
"typecheck": "tsc --noEmit",
|
|
67
67
|
"lint": "eslint src",
|
|
68
68
|
"lint:fix": "eslint src --fix",
|