@agentforge/core 0.11.7 → 0.12.0
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 +572 -9
- package/dist/index.d.cts +325 -5
- package/dist/index.d.ts +325 -5
- package/dist/index.js +561 -9
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AgentError: () => AgentError,
|
|
34
|
+
AlertManager: () => AlertManager,
|
|
35
|
+
AuditLogger: () => AuditLogger,
|
|
34
36
|
BatchProcessor: () => BatchProcessor,
|
|
35
37
|
CircuitBreaker: () => CircuitBreaker,
|
|
36
38
|
ConnectionPool: () => ConnectionPool,
|
|
37
39
|
DatabasePool: () => DatabasePool,
|
|
40
|
+
HealthChecker: () => HealthChecker,
|
|
38
41
|
HttpPool: () => HttpPool,
|
|
39
42
|
LogLevel: () => LogLevel,
|
|
40
43
|
ManagedTool: () => ManagedTool,
|
|
@@ -42,6 +45,7 @@ __export(index_exports, {
|
|
|
42
45
|
MetricType: () => MetricType,
|
|
43
46
|
MiddlewareChain: () => MiddlewareChain,
|
|
44
47
|
MissingDescriptionError: () => MissingDescriptionError,
|
|
48
|
+
Profiler: () => Profiler,
|
|
45
49
|
RegistryEvent: () => RegistryEvent,
|
|
46
50
|
TimeoutError: () => TimeoutError,
|
|
47
51
|
ToolBuilder: () => ToolBuilder,
|
|
@@ -65,7 +69,9 @@ __export(index_exports, {
|
|
|
65
69
|
composeWithOptions: () => composeWithOptions,
|
|
66
70
|
conditional: () => conditional,
|
|
67
71
|
configureLangSmith: () => configureLangSmith,
|
|
72
|
+
createAlertManager: () => createAlertManager,
|
|
68
73
|
createApprovalRequiredInterrupt: () => createApprovalRequiredInterrupt,
|
|
74
|
+
createAuditLogger: () => createAuditLogger,
|
|
69
75
|
createBatchProcessor: () => createBatchProcessor,
|
|
70
76
|
createBinaryRouter: () => createBinaryRouter,
|
|
71
77
|
createCircuitBreaker: () => createCircuitBreaker,
|
|
@@ -75,6 +81,7 @@ __export(index_exports, {
|
|
|
75
81
|
createCustomInterrupt: () => createCustomInterrupt,
|
|
76
82
|
createDatabasePool: () => createDatabasePool,
|
|
77
83
|
createErrorReporter: () => createErrorReporter,
|
|
84
|
+
createHealthChecker: () => createHealthChecker,
|
|
78
85
|
createHeartbeat: () => createHeartbeat,
|
|
79
86
|
createHttpPool: () => createHttpPool,
|
|
80
87
|
createHumanRequestInterrupt: () => createHumanRequestInterrupt,
|
|
@@ -88,6 +95,7 @@ __export(index_exports, {
|
|
|
88
95
|
createMockTool: () => createMockTool,
|
|
89
96
|
createMultiRouter: () => createMultiRouter,
|
|
90
97
|
createParallelWorkflow: () => createParallelWorkflow,
|
|
98
|
+
createProfiler: () => createProfiler,
|
|
91
99
|
createProgressTracker: () => createProgressTracker,
|
|
92
100
|
createSSEFormatter: () => createSSEFormatter,
|
|
93
101
|
createSequentialWorkflow: () => createSequentialWorkflow,
|
|
@@ -124,6 +132,7 @@ __export(index_exports, {
|
|
|
124
132
|
isHumanRequestInterrupt: () => isHumanRequestInterrupt,
|
|
125
133
|
isMemoryCheckpointer: () => isMemoryCheckpointer,
|
|
126
134
|
isTracingEnabled: () => isTracingEnabled,
|
|
135
|
+
loadPrompt: () => loadPrompt,
|
|
127
136
|
map: () => map,
|
|
128
137
|
merge: () => merge,
|
|
129
138
|
mergeState: () => mergeState,
|
|
@@ -132,8 +141,10 @@ __export(index_exports, {
|
|
|
132
141
|
presets: () => presets,
|
|
133
142
|
production: () => production,
|
|
134
143
|
reduce: () => reduce,
|
|
144
|
+
renderTemplate: () => renderTemplate,
|
|
135
145
|
retry: () => retry,
|
|
136
146
|
safeValidateSchemaDescriptions: () => safeValidateSchemaDescriptions,
|
|
147
|
+
sanitizeValue: () => sanitizeValue,
|
|
137
148
|
sendMessage: () => sendMessage,
|
|
138
149
|
sequential: () => sequential,
|
|
139
150
|
sequentialBuilder: () => sequentialBuilder,
|
|
@@ -2679,14 +2690,14 @@ var withLogging = (options) => {
|
|
|
2679
2690
|
onComplete,
|
|
2680
2691
|
onError
|
|
2681
2692
|
} = options;
|
|
2682
|
-
const
|
|
2693
|
+
const logger5 = providedLogger || createLogger(name, { level });
|
|
2683
2694
|
return (node) => {
|
|
2684
2695
|
return async (state) => {
|
|
2685
2696
|
const startTime = Date.now();
|
|
2686
2697
|
try {
|
|
2687
2698
|
if (logInput) {
|
|
2688
2699
|
const data = extractData ? extractData(state) : { state };
|
|
2689
|
-
|
|
2700
|
+
logger5.info("Node execution started", data);
|
|
2690
2701
|
}
|
|
2691
2702
|
if (onStart) {
|
|
2692
2703
|
onStart(state);
|
|
@@ -2696,9 +2707,9 @@ var withLogging = (options) => {
|
|
|
2696
2707
|
if (logOutput) {
|
|
2697
2708
|
const data = extractData ? extractData(result) : { result };
|
|
2698
2709
|
if (logDuration) {
|
|
2699
|
-
|
|
2710
|
+
logger5.info(`Node execution completed (${duration}ms)`, data);
|
|
2700
2711
|
} else {
|
|
2701
|
-
|
|
2712
|
+
logger5.info("Node execution completed", data);
|
|
2702
2713
|
}
|
|
2703
2714
|
}
|
|
2704
2715
|
if (onComplete) {
|
|
@@ -2709,7 +2720,7 @@ var withLogging = (options) => {
|
|
|
2709
2720
|
const duration = Date.now() - startTime;
|
|
2710
2721
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2711
2722
|
if (logErrors) {
|
|
2712
|
-
|
|
2723
|
+
logger5.error(`Node execution failed (${duration}ms)`, {
|
|
2713
2724
|
error: err.message,
|
|
2714
2725
|
stack: err.stack
|
|
2715
2726
|
});
|
|
@@ -2745,7 +2756,7 @@ function withLogging2(options) {
|
|
|
2745
2756
|
function production(node, options) {
|
|
2746
2757
|
const {
|
|
2747
2758
|
nodeName,
|
|
2748
|
-
logger:
|
|
2759
|
+
logger: logger5,
|
|
2749
2760
|
enableMetrics = true,
|
|
2750
2761
|
enableTracing = true,
|
|
2751
2762
|
enableRetry = true,
|
|
@@ -2753,7 +2764,7 @@ function production(node, options) {
|
|
|
2753
2764
|
retryOptions = {},
|
|
2754
2765
|
errorOptions = {}
|
|
2755
2766
|
} = options;
|
|
2756
|
-
const actualLogger =
|
|
2767
|
+
const actualLogger = logger5 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2757
2768
|
const middleware = [];
|
|
2758
2769
|
middleware.push(
|
|
2759
2770
|
withLogging2({
|
|
@@ -2817,9 +2828,9 @@ function development(node, options) {
|
|
|
2817
2828
|
const {
|
|
2818
2829
|
nodeName,
|
|
2819
2830
|
verbose = true,
|
|
2820
|
-
logger:
|
|
2831
|
+
logger: logger5
|
|
2821
2832
|
} = options;
|
|
2822
|
-
const actualLogger =
|
|
2833
|
+
const actualLogger = logger5 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2823
2834
|
return withLogging2({
|
|
2824
2835
|
logger: actualLogger,
|
|
2825
2836
|
name: nodeName,
|
|
@@ -4930,13 +4941,557 @@ var CircuitBreaker = class {
|
|
|
4930
4941
|
function createCircuitBreaker(options) {
|
|
4931
4942
|
return new CircuitBreaker(options);
|
|
4932
4943
|
}
|
|
4944
|
+
|
|
4945
|
+
// src/monitoring/health.ts
|
|
4946
|
+
var HealthChecker = class {
|
|
4947
|
+
constructor(options) {
|
|
4948
|
+
this.options = options;
|
|
4949
|
+
}
|
|
4950
|
+
checkTimer;
|
|
4951
|
+
lastReport;
|
|
4952
|
+
startTime = Date.now();
|
|
4953
|
+
running = false;
|
|
4954
|
+
start() {
|
|
4955
|
+
if (this.running) {
|
|
4956
|
+
return;
|
|
4957
|
+
}
|
|
4958
|
+
this.running = true;
|
|
4959
|
+
const interval = this.options.interval || 3e4;
|
|
4960
|
+
this.runChecks().catch((error) => {
|
|
4961
|
+
console.error("Initial health check failed:", error);
|
|
4962
|
+
});
|
|
4963
|
+
this.checkTimer = setInterval(() => {
|
|
4964
|
+
this.runChecks().catch((error) => {
|
|
4965
|
+
console.error("Health check failed:", error);
|
|
4966
|
+
});
|
|
4967
|
+
}, interval);
|
|
4968
|
+
}
|
|
4969
|
+
stop() {
|
|
4970
|
+
if (!this.running) {
|
|
4971
|
+
return;
|
|
4972
|
+
}
|
|
4973
|
+
this.running = false;
|
|
4974
|
+
if (this.checkTimer) {
|
|
4975
|
+
clearInterval(this.checkTimer);
|
|
4976
|
+
this.checkTimer = void 0;
|
|
4977
|
+
}
|
|
4978
|
+
}
|
|
4979
|
+
async getHealth() {
|
|
4980
|
+
if (!this.lastReport) {
|
|
4981
|
+
return this.runChecks();
|
|
4982
|
+
}
|
|
4983
|
+
return this.lastReport;
|
|
4984
|
+
}
|
|
4985
|
+
async getLiveness() {
|
|
4986
|
+
return {
|
|
4987
|
+
healthy: true,
|
|
4988
|
+
status: "healthy",
|
|
4989
|
+
message: "Application is running",
|
|
4990
|
+
timestamp: Date.now()
|
|
4991
|
+
};
|
|
4992
|
+
}
|
|
4993
|
+
async getReadiness() {
|
|
4994
|
+
return this.getHealth();
|
|
4995
|
+
}
|
|
4996
|
+
async runChecks() {
|
|
4997
|
+
const timeout2 = this.options.timeout || 5e3;
|
|
4998
|
+
const results = {};
|
|
4999
|
+
const checkPromises = Object.entries(this.options.checks).map(async ([name, check]) => {
|
|
5000
|
+
const startTime = Date.now();
|
|
5001
|
+
try {
|
|
5002
|
+
const result = await Promise.race([
|
|
5003
|
+
check(),
|
|
5004
|
+
new Promise(
|
|
5005
|
+
(_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout2)
|
|
5006
|
+
)
|
|
5007
|
+
]);
|
|
5008
|
+
results[name] = {
|
|
5009
|
+
...result,
|
|
5010
|
+
timestamp: Date.now(),
|
|
5011
|
+
duration: Date.now() - startTime
|
|
5012
|
+
};
|
|
5013
|
+
} catch (error) {
|
|
5014
|
+
const errorMessage = error.message;
|
|
5015
|
+
results[name] = {
|
|
5016
|
+
healthy: false,
|
|
5017
|
+
status: "unhealthy",
|
|
5018
|
+
error: errorMessage,
|
|
5019
|
+
timestamp: Date.now(),
|
|
5020
|
+
duration: Date.now() - startTime
|
|
5021
|
+
};
|
|
5022
|
+
this.options.onCheckFail?.(name, error);
|
|
5023
|
+
}
|
|
5024
|
+
});
|
|
5025
|
+
await Promise.all(checkPromises);
|
|
5026
|
+
const allHealthy = Object.values(results).every((r) => r.healthy);
|
|
5027
|
+
const anyUnhealthy = Object.values(results).some((r) => r.status === "unhealthy");
|
|
5028
|
+
const status = allHealthy ? "healthy" : anyUnhealthy ? "unhealthy" : "degraded";
|
|
5029
|
+
const report = {
|
|
5030
|
+
healthy: allHealthy,
|
|
5031
|
+
status,
|
|
5032
|
+
timestamp: Date.now(),
|
|
5033
|
+
checks: results,
|
|
5034
|
+
uptime: Date.now() - this.startTime
|
|
5035
|
+
};
|
|
5036
|
+
if (this.lastReport && this.lastReport.healthy !== report.healthy) {
|
|
5037
|
+
this.options.onHealthChange?.(report);
|
|
5038
|
+
}
|
|
5039
|
+
this.lastReport = report;
|
|
5040
|
+
return report;
|
|
5041
|
+
}
|
|
5042
|
+
};
|
|
5043
|
+
function createHealthChecker(options) {
|
|
5044
|
+
return new HealthChecker(options);
|
|
5045
|
+
}
|
|
5046
|
+
|
|
5047
|
+
// src/monitoring/profiler.ts
|
|
5048
|
+
var Profiler = class {
|
|
5049
|
+
profiles = /* @__PURE__ */ new Map();
|
|
5050
|
+
enabled;
|
|
5051
|
+
sampleRate;
|
|
5052
|
+
includeMemory;
|
|
5053
|
+
includeStack;
|
|
5054
|
+
maxSamples;
|
|
5055
|
+
constructor(options = {}) {
|
|
5056
|
+
this.enabled = options.enabled ?? true;
|
|
5057
|
+
this.sampleRate = options.sampleRate ?? 1;
|
|
5058
|
+
this.includeMemory = options.includeMemory ?? false;
|
|
5059
|
+
this.includeStack = options.includeStack ?? false;
|
|
5060
|
+
this.maxSamples = options.maxSamples ?? 1e3;
|
|
5061
|
+
}
|
|
5062
|
+
profile(name, fn) {
|
|
5063
|
+
return async (...args) => {
|
|
5064
|
+
if (!this.enabled || Math.random() > this.sampleRate) {
|
|
5065
|
+
return fn(...args);
|
|
5066
|
+
}
|
|
5067
|
+
const startTime = Date.now();
|
|
5068
|
+
const startMemory = this.includeMemory ? process.memoryUsage() : void 0;
|
|
5069
|
+
const stack = this.includeStack ? new Error().stack : void 0;
|
|
5070
|
+
try {
|
|
5071
|
+
const result = await fn(...args);
|
|
5072
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
5073
|
+
return result;
|
|
5074
|
+
} catch (error) {
|
|
5075
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
5076
|
+
throw error;
|
|
5077
|
+
}
|
|
5078
|
+
};
|
|
5079
|
+
}
|
|
5080
|
+
wrap(name, promise) {
|
|
5081
|
+
if (!this.enabled || Math.random() > this.sampleRate) {
|
|
5082
|
+
return promise;
|
|
5083
|
+
}
|
|
5084
|
+
const startTime = Date.now();
|
|
5085
|
+
const startMemory = this.includeMemory ? process.memoryUsage() : void 0;
|
|
5086
|
+
const stack = this.includeStack ? new Error().stack : void 0;
|
|
5087
|
+
return promise.finally(() => {
|
|
5088
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
5089
|
+
});
|
|
5090
|
+
}
|
|
5091
|
+
recordSample(name, startTime, startMemory, stack) {
|
|
5092
|
+
const duration = Date.now() - startTime;
|
|
5093
|
+
const sample = {
|
|
5094
|
+
timestamp: startTime,
|
|
5095
|
+
duration
|
|
5096
|
+
};
|
|
5097
|
+
if (this.includeMemory && startMemory) {
|
|
5098
|
+
const currentMemory = process.memoryUsage();
|
|
5099
|
+
sample.memory = {
|
|
5100
|
+
heapUsed: currentMemory.heapUsed - startMemory.heapUsed,
|
|
5101
|
+
heapTotal: currentMemory.heapTotal,
|
|
5102
|
+
external: currentMemory.external
|
|
5103
|
+
};
|
|
5104
|
+
}
|
|
5105
|
+
if (this.includeStack && stack) {
|
|
5106
|
+
sample.stack = stack;
|
|
5107
|
+
}
|
|
5108
|
+
if (!this.profiles.has(name)) {
|
|
5109
|
+
this.profiles.set(name, []);
|
|
5110
|
+
}
|
|
5111
|
+
const samples = this.profiles.get(name);
|
|
5112
|
+
samples.push(sample);
|
|
5113
|
+
if (samples.length > this.maxSamples) {
|
|
5114
|
+
samples.shift();
|
|
5115
|
+
}
|
|
5116
|
+
}
|
|
5117
|
+
getReport() {
|
|
5118
|
+
const report = {};
|
|
5119
|
+
for (const [name, samples] of this.profiles.entries()) {
|
|
5120
|
+
if (samples.length === 0) {
|
|
5121
|
+
continue;
|
|
5122
|
+
}
|
|
5123
|
+
const durations = samples.map((s) => s.duration).sort((a, b) => a - b);
|
|
5124
|
+
const totalTime = durations.reduce((sum, d) => sum + d, 0);
|
|
5125
|
+
const stats = {
|
|
5126
|
+
calls: samples.length,
|
|
5127
|
+
totalTime,
|
|
5128
|
+
avgTime: totalTime / samples.length,
|
|
5129
|
+
minTime: durations[0],
|
|
5130
|
+
maxTime: durations[durations.length - 1],
|
|
5131
|
+
p50: this.percentile(durations, 0.5),
|
|
5132
|
+
p95: this.percentile(durations, 0.95),
|
|
5133
|
+
p99: this.percentile(durations, 0.99),
|
|
5134
|
+
samples
|
|
5135
|
+
};
|
|
5136
|
+
if (this.includeMemory) {
|
|
5137
|
+
const memorySamples = samples.filter((s) => s.memory).map((s) => s.memory.heapUsed);
|
|
5138
|
+
if (memorySamples.length > 0) {
|
|
5139
|
+
stats.memory = {
|
|
5140
|
+
avgHeapUsed: memorySamples.reduce((sum, m) => sum + m, 0) / memorySamples.length,
|
|
5141
|
+
maxHeapUsed: Math.max(...memorySamples),
|
|
5142
|
+
minHeapUsed: Math.min(...memorySamples)
|
|
5143
|
+
};
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
report[name] = stats;
|
|
5147
|
+
}
|
|
5148
|
+
return report;
|
|
5149
|
+
}
|
|
5150
|
+
percentile(sorted, p) {
|
|
5151
|
+
const index = Math.ceil(sorted.length * p) - 1;
|
|
5152
|
+
return sorted[Math.max(0, index)];
|
|
5153
|
+
}
|
|
5154
|
+
reset(name) {
|
|
5155
|
+
if (name) {
|
|
5156
|
+
this.profiles.delete(name);
|
|
5157
|
+
} else {
|
|
5158
|
+
this.profiles.clear();
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
5161
|
+
export(path) {
|
|
5162
|
+
const report = this.getReport();
|
|
5163
|
+
console.log("Exporting profile report to:", path);
|
|
5164
|
+
console.log(JSON.stringify(report, null, 2));
|
|
5165
|
+
}
|
|
5166
|
+
};
|
|
5167
|
+
function createProfiler(options) {
|
|
5168
|
+
return new Profiler(options);
|
|
5169
|
+
}
|
|
5170
|
+
|
|
5171
|
+
// src/monitoring/alerts.ts
|
|
5172
|
+
var logger4 = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
5173
|
+
var AlertManager = class {
|
|
5174
|
+
constructor(options) {
|
|
5175
|
+
this.options = options;
|
|
5176
|
+
}
|
|
5177
|
+
lastAlertTime = /* @__PURE__ */ new Map();
|
|
5178
|
+
monitorTimer;
|
|
5179
|
+
running = false;
|
|
5180
|
+
start(metrics, interval = 6e4) {
|
|
5181
|
+
if (this.running || !metrics) {
|
|
5182
|
+
return;
|
|
5183
|
+
}
|
|
5184
|
+
this.running = true;
|
|
5185
|
+
this.monitorTimer = setInterval(() => {
|
|
5186
|
+
const currentMetrics = metrics();
|
|
5187
|
+
this.checkRules(currentMetrics);
|
|
5188
|
+
}, interval);
|
|
5189
|
+
}
|
|
5190
|
+
stop() {
|
|
5191
|
+
if (!this.running) {
|
|
5192
|
+
return;
|
|
5193
|
+
}
|
|
5194
|
+
this.running = false;
|
|
5195
|
+
if (this.monitorTimer) {
|
|
5196
|
+
clearInterval(this.monitorTimer);
|
|
5197
|
+
this.monitorTimer = void 0;
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
async alert(alert) {
|
|
5201
|
+
const fullAlert = {
|
|
5202
|
+
...alert,
|
|
5203
|
+
timestamp: alert.timestamp || Date.now()
|
|
5204
|
+
};
|
|
5205
|
+
if (this.isThrottled(alert.name)) {
|
|
5206
|
+
return;
|
|
5207
|
+
}
|
|
5208
|
+
this.lastAlertTime.set(alert.name, Date.now());
|
|
5209
|
+
this.options.onAlert?.(fullAlert);
|
|
5210
|
+
logger4.warn("Alert triggered", {
|
|
5211
|
+
name: alert.name,
|
|
5212
|
+
severity: alert.severity,
|
|
5213
|
+
message: alert.message,
|
|
5214
|
+
data: alert.data
|
|
5215
|
+
});
|
|
5216
|
+
}
|
|
5217
|
+
checkRules(metrics) {
|
|
5218
|
+
if (!this.options.rules) {
|
|
5219
|
+
return;
|
|
5220
|
+
}
|
|
5221
|
+
for (const rule of this.options.rules) {
|
|
5222
|
+
try {
|
|
5223
|
+
if (rule.condition(metrics)) {
|
|
5224
|
+
this.alert({
|
|
5225
|
+
name: rule.name,
|
|
5226
|
+
severity: rule.severity,
|
|
5227
|
+
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5228
|
+
data: { metrics }
|
|
5229
|
+
});
|
|
5230
|
+
}
|
|
5231
|
+
} catch (error) {
|
|
5232
|
+
logger4.error("Rule check failed", {
|
|
5233
|
+
ruleName: rule.name,
|
|
5234
|
+
error: error instanceof Error ? error.message : String(error),
|
|
5235
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
5236
|
+
});
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5240
|
+
isThrottled(name) {
|
|
5241
|
+
const rule = this.options.rules?.find((r) => r.name === name);
|
|
5242
|
+
if (!rule?.throttle) {
|
|
5243
|
+
return false;
|
|
5244
|
+
}
|
|
5245
|
+
const lastTime = this.lastAlertTime.get(name);
|
|
5246
|
+
if (!lastTime) {
|
|
5247
|
+
return false;
|
|
5248
|
+
}
|
|
5249
|
+
return Date.now() - lastTime < rule.throttle;
|
|
5250
|
+
}
|
|
5251
|
+
async sendToChannel(channelName, alert) {
|
|
5252
|
+
const channel = this.options.channels[channelName];
|
|
5253
|
+
if (!channel) {
|
|
5254
|
+
throw new Error(`Channel not found: ${channelName}`);
|
|
5255
|
+
}
|
|
5256
|
+
switch (channel.type) {
|
|
5257
|
+
case "email":
|
|
5258
|
+
logger4.info("Alert sent to email", {
|
|
5259
|
+
channel: channelName,
|
|
5260
|
+
to: channel.config.to,
|
|
5261
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5262
|
+
});
|
|
5263
|
+
break;
|
|
5264
|
+
case "slack":
|
|
5265
|
+
logger4.info("Alert sent to Slack", {
|
|
5266
|
+
channel: channelName,
|
|
5267
|
+
webhookUrl: channel.config.webhookUrl,
|
|
5268
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5269
|
+
});
|
|
5270
|
+
break;
|
|
5271
|
+
case "webhook":
|
|
5272
|
+
logger4.info("Alert sent to webhook", {
|
|
5273
|
+
channel: channelName,
|
|
5274
|
+
url: channel.config.url,
|
|
5275
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5276
|
+
});
|
|
5277
|
+
break;
|
|
5278
|
+
default:
|
|
5279
|
+
logger4.info("Alert sent", {
|
|
5280
|
+
channel: channelName,
|
|
5281
|
+
channelType: channel.type,
|
|
5282
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5283
|
+
});
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
getAlertHistory(name, limit = 100) {
|
|
5287
|
+
return [];
|
|
5288
|
+
}
|
|
5289
|
+
clearAlertHistory(name) {
|
|
5290
|
+
if (name) {
|
|
5291
|
+
this.lastAlertTime.delete(name);
|
|
5292
|
+
} else {
|
|
5293
|
+
this.lastAlertTime.clear();
|
|
5294
|
+
}
|
|
5295
|
+
}
|
|
5296
|
+
};
|
|
5297
|
+
function createAlertManager(options) {
|
|
5298
|
+
return new AlertManager(options);
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
// src/monitoring/audit.ts
|
|
5302
|
+
var AuditLogger = class {
|
|
5303
|
+
constructor(options = {}) {
|
|
5304
|
+
this.options = options;
|
|
5305
|
+
if (options.retention?.autoCleanup) {
|
|
5306
|
+
this.startCleanup();
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
logs = [];
|
|
5310
|
+
cleanupTimer;
|
|
5311
|
+
async log(entry) {
|
|
5312
|
+
const fullEntry = {
|
|
5313
|
+
...entry,
|
|
5314
|
+
id: this.generateId(),
|
|
5315
|
+
timestamp: entry.timestamp || Date.now(),
|
|
5316
|
+
success: entry.success ?? true
|
|
5317
|
+
};
|
|
5318
|
+
const fields = this.options.fields || {};
|
|
5319
|
+
const filteredEntry = {
|
|
5320
|
+
id: fullEntry.id,
|
|
5321
|
+
userId: fields.userId !== false ? fullEntry.userId : "",
|
|
5322
|
+
action: fields.action !== false ? fullEntry.action : "",
|
|
5323
|
+
resource: fields.resource !== false ? fullEntry.resource : "",
|
|
5324
|
+
timestamp: fields.timestamp !== false ? fullEntry.timestamp : void 0
|
|
5325
|
+
};
|
|
5326
|
+
if (fields.input !== false && fullEntry.input) {
|
|
5327
|
+
filteredEntry.input = fullEntry.input;
|
|
5328
|
+
}
|
|
5329
|
+
if (fields.output !== false && fullEntry.output) {
|
|
5330
|
+
filteredEntry.output = fullEntry.output;
|
|
5331
|
+
}
|
|
5332
|
+
if (fullEntry.metadata) {
|
|
5333
|
+
filteredEntry.metadata = fullEntry.metadata;
|
|
5334
|
+
}
|
|
5335
|
+
if (fullEntry.error) {
|
|
5336
|
+
filteredEntry.error = fullEntry.error;
|
|
5337
|
+
filteredEntry.success = false;
|
|
5338
|
+
}
|
|
5339
|
+
this.logs.push(filteredEntry);
|
|
5340
|
+
this.options.onLog?.(filteredEntry);
|
|
5341
|
+
}
|
|
5342
|
+
async query(query = {}) {
|
|
5343
|
+
let results = [...this.logs];
|
|
5344
|
+
if (query.userId) {
|
|
5345
|
+
results = results.filter((log) => log.userId === query.userId);
|
|
5346
|
+
}
|
|
5347
|
+
if (query.action) {
|
|
5348
|
+
results = results.filter((log) => log.action === query.action);
|
|
5349
|
+
}
|
|
5350
|
+
if (query.resource) {
|
|
5351
|
+
results = results.filter((log) => log.resource === query.resource);
|
|
5352
|
+
}
|
|
5353
|
+
if (query.startDate) {
|
|
5354
|
+
const startTime = query.startDate.getTime();
|
|
5355
|
+
results = results.filter((log) => (log.timestamp || 0) >= startTime);
|
|
5356
|
+
}
|
|
5357
|
+
if (query.endDate) {
|
|
5358
|
+
const endTime = query.endDate.getTime();
|
|
5359
|
+
results = results.filter((log) => (log.timestamp || 0) <= endTime);
|
|
5360
|
+
}
|
|
5361
|
+
const offset = query.offset || 0;
|
|
5362
|
+
const limit = query.limit || 100;
|
|
5363
|
+
results = results.slice(offset, offset + limit);
|
|
5364
|
+
return results;
|
|
5365
|
+
}
|
|
5366
|
+
async export(path, options = {}) {
|
|
5367
|
+
const logs = await this.query({
|
|
5368
|
+
startDate: options.startDate,
|
|
5369
|
+
endDate: options.endDate
|
|
5370
|
+
});
|
|
5371
|
+
const format = options.format || "json";
|
|
5372
|
+
if (format === "json") {
|
|
5373
|
+
console.log(`Exporting ${logs.length} audit logs to ${path} (JSON)`);
|
|
5374
|
+
console.log(JSON.stringify(logs, null, 2));
|
|
5375
|
+
} else if (format === "csv") {
|
|
5376
|
+
console.log(`Exporting ${logs.length} audit logs to ${path} (CSV)`);
|
|
5377
|
+
const csv = this.convertToCSV(logs);
|
|
5378
|
+
console.log(csv);
|
|
5379
|
+
}
|
|
5380
|
+
}
|
|
5381
|
+
convertToCSV(logs) {
|
|
5382
|
+
if (logs.length === 0) {
|
|
5383
|
+
return "";
|
|
5384
|
+
}
|
|
5385
|
+
const headers = ["id", "userId", "action", "resource", "timestamp", "success"];
|
|
5386
|
+
const rows = logs.map((log) => [
|
|
5387
|
+
log.id,
|
|
5388
|
+
log.userId,
|
|
5389
|
+
log.action,
|
|
5390
|
+
log.resource,
|
|
5391
|
+
log.timestamp,
|
|
5392
|
+
log.success
|
|
5393
|
+
]);
|
|
5394
|
+
return [headers.join(","), ...rows.map((row) => row.join(","))].join("\n");
|
|
5395
|
+
}
|
|
5396
|
+
startCleanup() {
|
|
5397
|
+
const interval = 24 * 60 * 60 * 1e3;
|
|
5398
|
+
this.cleanupTimer = setInterval(() => {
|
|
5399
|
+
this.cleanup();
|
|
5400
|
+
}, interval);
|
|
5401
|
+
}
|
|
5402
|
+
cleanup() {
|
|
5403
|
+
if (!this.options.retention) {
|
|
5404
|
+
return;
|
|
5405
|
+
}
|
|
5406
|
+
const retentionMs = this.options.retention.days * 24 * 60 * 60 * 1e3;
|
|
5407
|
+
const cutoffTime = Date.now() - retentionMs;
|
|
5408
|
+
this.logs = this.logs.filter((log) => (log.timestamp || 0) >= cutoffTime);
|
|
5409
|
+
}
|
|
5410
|
+
generateId() {
|
|
5411
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
5412
|
+
}
|
|
5413
|
+
stop() {
|
|
5414
|
+
if (this.cleanupTimer) {
|
|
5415
|
+
clearInterval(this.cleanupTimer);
|
|
5416
|
+
this.cleanupTimer = void 0;
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
};
|
|
5420
|
+
function createAuditLogger(options) {
|
|
5421
|
+
return new AuditLogger(options);
|
|
5422
|
+
}
|
|
5423
|
+
|
|
5424
|
+
// src/prompt-loader/index.ts
|
|
5425
|
+
var import_fs = require("fs");
|
|
5426
|
+
var import_path = require("path");
|
|
5427
|
+
var MAX_VARIABLE_LENGTH = 500;
|
|
5428
|
+
function sanitizeValue(value) {
|
|
5429
|
+
if (value === void 0 || value === null) return "";
|
|
5430
|
+
let sanitized = String(value);
|
|
5431
|
+
sanitized = sanitized.replace(/^#+\s*/gm, "");
|
|
5432
|
+
sanitized = sanitized.replace(/[\r\n]+/g, " ");
|
|
5433
|
+
sanitized = sanitized.trim().replace(/\s+/g, " ");
|
|
5434
|
+
if (sanitized.length > MAX_VARIABLE_LENGTH) {
|
|
5435
|
+
sanitized = sanitized.substring(0, MAX_VARIABLE_LENGTH) + "...";
|
|
5436
|
+
}
|
|
5437
|
+
return sanitized;
|
|
5438
|
+
}
|
|
5439
|
+
function renderTemplate(template, options) {
|
|
5440
|
+
let rawVariables;
|
|
5441
|
+
let sanitizedVariables;
|
|
5442
|
+
if ("trustedVariables" in options || "untrustedVariables" in options) {
|
|
5443
|
+
const opts = options;
|
|
5444
|
+
rawVariables = {
|
|
5445
|
+
...opts.trustedVariables,
|
|
5446
|
+
...opts.untrustedVariables
|
|
5447
|
+
};
|
|
5448
|
+
const sanitizedUntrusted = {};
|
|
5449
|
+
if (opts.untrustedVariables) {
|
|
5450
|
+
for (const [key, value] of Object.entries(opts.untrustedVariables)) {
|
|
5451
|
+
sanitizedUntrusted[key] = sanitizeValue(value);
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
sanitizedVariables = {
|
|
5455
|
+
...opts.trustedVariables,
|
|
5456
|
+
...sanitizedUntrusted
|
|
5457
|
+
};
|
|
5458
|
+
} else {
|
|
5459
|
+
rawVariables = options;
|
|
5460
|
+
sanitizedVariables = options;
|
|
5461
|
+
}
|
|
5462
|
+
let result = template;
|
|
5463
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, varName, content) => {
|
|
5464
|
+
return rawVariables[varName] ? content : "";
|
|
5465
|
+
});
|
|
5466
|
+
result = result.replace(/\{\{(\w+)\}\}/g, (_, varName) => {
|
|
5467
|
+
const value = sanitizedVariables[varName];
|
|
5468
|
+
if (value === void 0 || value === null) return "";
|
|
5469
|
+
return String(value);
|
|
5470
|
+
});
|
|
5471
|
+
return result;
|
|
5472
|
+
}
|
|
5473
|
+
function loadPrompt(promptName, options = {}, promptsDir) {
|
|
5474
|
+
const baseDir = promptsDir || (0, import_path.join)(process.cwd(), "prompts");
|
|
5475
|
+
const promptPath = (0, import_path.join)(baseDir, `${promptName}.md`);
|
|
5476
|
+
try {
|
|
5477
|
+
const template = (0, import_fs.readFileSync)(promptPath, "utf-8");
|
|
5478
|
+
return renderTemplate(template, options);
|
|
5479
|
+
} catch (error) {
|
|
5480
|
+
throw new Error(
|
|
5481
|
+
`Failed to load prompt "${promptName}" from ${promptPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
5482
|
+
);
|
|
5483
|
+
}
|
|
5484
|
+
}
|
|
4933
5485
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4934
5486
|
0 && (module.exports = {
|
|
4935
5487
|
AgentError,
|
|
5488
|
+
AlertManager,
|
|
5489
|
+
AuditLogger,
|
|
4936
5490
|
BatchProcessor,
|
|
4937
5491
|
CircuitBreaker,
|
|
4938
5492
|
ConnectionPool,
|
|
4939
5493
|
DatabasePool,
|
|
5494
|
+
HealthChecker,
|
|
4940
5495
|
HttpPool,
|
|
4941
5496
|
LogLevel,
|
|
4942
5497
|
ManagedTool,
|
|
@@ -4944,6 +5499,7 @@ function createCircuitBreaker(options) {
|
|
|
4944
5499
|
MetricType,
|
|
4945
5500
|
MiddlewareChain,
|
|
4946
5501
|
MissingDescriptionError,
|
|
5502
|
+
Profiler,
|
|
4947
5503
|
RegistryEvent,
|
|
4948
5504
|
TimeoutError,
|
|
4949
5505
|
ToolBuilder,
|
|
@@ -4967,7 +5523,9 @@ function createCircuitBreaker(options) {
|
|
|
4967
5523
|
composeWithOptions,
|
|
4968
5524
|
conditional,
|
|
4969
5525
|
configureLangSmith,
|
|
5526
|
+
createAlertManager,
|
|
4970
5527
|
createApprovalRequiredInterrupt,
|
|
5528
|
+
createAuditLogger,
|
|
4971
5529
|
createBatchProcessor,
|
|
4972
5530
|
createBinaryRouter,
|
|
4973
5531
|
createCircuitBreaker,
|
|
@@ -4977,6 +5535,7 @@ function createCircuitBreaker(options) {
|
|
|
4977
5535
|
createCustomInterrupt,
|
|
4978
5536
|
createDatabasePool,
|
|
4979
5537
|
createErrorReporter,
|
|
5538
|
+
createHealthChecker,
|
|
4980
5539
|
createHeartbeat,
|
|
4981
5540
|
createHttpPool,
|
|
4982
5541
|
createHumanRequestInterrupt,
|
|
@@ -4990,6 +5549,7 @@ function createCircuitBreaker(options) {
|
|
|
4990
5549
|
createMockTool,
|
|
4991
5550
|
createMultiRouter,
|
|
4992
5551
|
createParallelWorkflow,
|
|
5552
|
+
createProfiler,
|
|
4993
5553
|
createProgressTracker,
|
|
4994
5554
|
createSSEFormatter,
|
|
4995
5555
|
createSequentialWorkflow,
|
|
@@ -5026,6 +5586,7 @@ function createCircuitBreaker(options) {
|
|
|
5026
5586
|
isHumanRequestInterrupt,
|
|
5027
5587
|
isMemoryCheckpointer,
|
|
5028
5588
|
isTracingEnabled,
|
|
5589
|
+
loadPrompt,
|
|
5029
5590
|
map,
|
|
5030
5591
|
merge,
|
|
5031
5592
|
mergeState,
|
|
@@ -5034,8 +5595,10 @@ function createCircuitBreaker(options) {
|
|
|
5034
5595
|
presets,
|
|
5035
5596
|
production,
|
|
5036
5597
|
reduce,
|
|
5598
|
+
renderTemplate,
|
|
5037
5599
|
retry,
|
|
5038
5600
|
safeValidateSchemaDescriptions,
|
|
5601
|
+
sanitizeValue,
|
|
5039
5602
|
sendMessage,
|
|
5040
5603
|
sequential,
|
|
5041
5604
|
sequentialBuilder,
|