@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.js
CHANGED
|
@@ -2515,14 +2515,14 @@ var withLogging = (options) => {
|
|
|
2515
2515
|
onComplete,
|
|
2516
2516
|
onError
|
|
2517
2517
|
} = options;
|
|
2518
|
-
const
|
|
2518
|
+
const logger5 = providedLogger || createLogger(name, { level });
|
|
2519
2519
|
return (node) => {
|
|
2520
2520
|
return async (state) => {
|
|
2521
2521
|
const startTime = Date.now();
|
|
2522
2522
|
try {
|
|
2523
2523
|
if (logInput) {
|
|
2524
2524
|
const data = extractData ? extractData(state) : { state };
|
|
2525
|
-
|
|
2525
|
+
logger5.info("Node execution started", data);
|
|
2526
2526
|
}
|
|
2527
2527
|
if (onStart) {
|
|
2528
2528
|
onStart(state);
|
|
@@ -2532,9 +2532,9 @@ var withLogging = (options) => {
|
|
|
2532
2532
|
if (logOutput) {
|
|
2533
2533
|
const data = extractData ? extractData(result) : { result };
|
|
2534
2534
|
if (logDuration) {
|
|
2535
|
-
|
|
2535
|
+
logger5.info(`Node execution completed (${duration}ms)`, data);
|
|
2536
2536
|
} else {
|
|
2537
|
-
|
|
2537
|
+
logger5.info("Node execution completed", data);
|
|
2538
2538
|
}
|
|
2539
2539
|
}
|
|
2540
2540
|
if (onComplete) {
|
|
@@ -2545,7 +2545,7 @@ var withLogging = (options) => {
|
|
|
2545
2545
|
const duration = Date.now() - startTime;
|
|
2546
2546
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2547
2547
|
if (logErrors) {
|
|
2548
|
-
|
|
2548
|
+
logger5.error(`Node execution failed (${duration}ms)`, {
|
|
2549
2549
|
error: err.message,
|
|
2550
2550
|
stack: err.stack
|
|
2551
2551
|
});
|
|
@@ -2581,7 +2581,7 @@ function withLogging2(options) {
|
|
|
2581
2581
|
function production(node, options) {
|
|
2582
2582
|
const {
|
|
2583
2583
|
nodeName,
|
|
2584
|
-
logger:
|
|
2584
|
+
logger: logger5,
|
|
2585
2585
|
enableMetrics = true,
|
|
2586
2586
|
enableTracing = true,
|
|
2587
2587
|
enableRetry = true,
|
|
@@ -2589,7 +2589,7 @@ function production(node, options) {
|
|
|
2589
2589
|
retryOptions = {},
|
|
2590
2590
|
errorOptions = {}
|
|
2591
2591
|
} = options;
|
|
2592
|
-
const actualLogger =
|
|
2592
|
+
const actualLogger = logger5 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2593
2593
|
const middleware = [];
|
|
2594
2594
|
middleware.push(
|
|
2595
2595
|
withLogging2({
|
|
@@ -2653,9 +2653,9 @@ function development(node, options) {
|
|
|
2653
2653
|
const {
|
|
2654
2654
|
nodeName,
|
|
2655
2655
|
verbose = true,
|
|
2656
|
-
logger:
|
|
2656
|
+
logger: logger5
|
|
2657
2657
|
} = options;
|
|
2658
|
-
const actualLogger =
|
|
2658
|
+
const actualLogger = logger5 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2659
2659
|
return withLogging2({
|
|
2660
2660
|
logger: actualLogger,
|
|
2661
2661
|
name: nodeName,
|
|
@@ -4766,12 +4766,556 @@ var CircuitBreaker = class {
|
|
|
4766
4766
|
function createCircuitBreaker(options) {
|
|
4767
4767
|
return new CircuitBreaker(options);
|
|
4768
4768
|
}
|
|
4769
|
+
|
|
4770
|
+
// src/monitoring/health.ts
|
|
4771
|
+
var HealthChecker = class {
|
|
4772
|
+
constructor(options) {
|
|
4773
|
+
this.options = options;
|
|
4774
|
+
}
|
|
4775
|
+
checkTimer;
|
|
4776
|
+
lastReport;
|
|
4777
|
+
startTime = Date.now();
|
|
4778
|
+
running = false;
|
|
4779
|
+
start() {
|
|
4780
|
+
if (this.running) {
|
|
4781
|
+
return;
|
|
4782
|
+
}
|
|
4783
|
+
this.running = true;
|
|
4784
|
+
const interval = this.options.interval || 3e4;
|
|
4785
|
+
this.runChecks().catch((error) => {
|
|
4786
|
+
console.error("Initial health check failed:", error);
|
|
4787
|
+
});
|
|
4788
|
+
this.checkTimer = setInterval(() => {
|
|
4789
|
+
this.runChecks().catch((error) => {
|
|
4790
|
+
console.error("Health check failed:", error);
|
|
4791
|
+
});
|
|
4792
|
+
}, interval);
|
|
4793
|
+
}
|
|
4794
|
+
stop() {
|
|
4795
|
+
if (!this.running) {
|
|
4796
|
+
return;
|
|
4797
|
+
}
|
|
4798
|
+
this.running = false;
|
|
4799
|
+
if (this.checkTimer) {
|
|
4800
|
+
clearInterval(this.checkTimer);
|
|
4801
|
+
this.checkTimer = void 0;
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
async getHealth() {
|
|
4805
|
+
if (!this.lastReport) {
|
|
4806
|
+
return this.runChecks();
|
|
4807
|
+
}
|
|
4808
|
+
return this.lastReport;
|
|
4809
|
+
}
|
|
4810
|
+
async getLiveness() {
|
|
4811
|
+
return {
|
|
4812
|
+
healthy: true,
|
|
4813
|
+
status: "healthy",
|
|
4814
|
+
message: "Application is running",
|
|
4815
|
+
timestamp: Date.now()
|
|
4816
|
+
};
|
|
4817
|
+
}
|
|
4818
|
+
async getReadiness() {
|
|
4819
|
+
return this.getHealth();
|
|
4820
|
+
}
|
|
4821
|
+
async runChecks() {
|
|
4822
|
+
const timeout2 = this.options.timeout || 5e3;
|
|
4823
|
+
const results = {};
|
|
4824
|
+
const checkPromises = Object.entries(this.options.checks).map(async ([name, check]) => {
|
|
4825
|
+
const startTime = Date.now();
|
|
4826
|
+
try {
|
|
4827
|
+
const result = await Promise.race([
|
|
4828
|
+
check(),
|
|
4829
|
+
new Promise(
|
|
4830
|
+
(_, reject) => setTimeout(() => reject(new Error("Health check timeout")), timeout2)
|
|
4831
|
+
)
|
|
4832
|
+
]);
|
|
4833
|
+
results[name] = {
|
|
4834
|
+
...result,
|
|
4835
|
+
timestamp: Date.now(),
|
|
4836
|
+
duration: Date.now() - startTime
|
|
4837
|
+
};
|
|
4838
|
+
} catch (error) {
|
|
4839
|
+
const errorMessage = error.message;
|
|
4840
|
+
results[name] = {
|
|
4841
|
+
healthy: false,
|
|
4842
|
+
status: "unhealthy",
|
|
4843
|
+
error: errorMessage,
|
|
4844
|
+
timestamp: Date.now(),
|
|
4845
|
+
duration: Date.now() - startTime
|
|
4846
|
+
};
|
|
4847
|
+
this.options.onCheckFail?.(name, error);
|
|
4848
|
+
}
|
|
4849
|
+
});
|
|
4850
|
+
await Promise.all(checkPromises);
|
|
4851
|
+
const allHealthy = Object.values(results).every((r) => r.healthy);
|
|
4852
|
+
const anyUnhealthy = Object.values(results).some((r) => r.status === "unhealthy");
|
|
4853
|
+
const status = allHealthy ? "healthy" : anyUnhealthy ? "unhealthy" : "degraded";
|
|
4854
|
+
const report = {
|
|
4855
|
+
healthy: allHealthy,
|
|
4856
|
+
status,
|
|
4857
|
+
timestamp: Date.now(),
|
|
4858
|
+
checks: results,
|
|
4859
|
+
uptime: Date.now() - this.startTime
|
|
4860
|
+
};
|
|
4861
|
+
if (this.lastReport && this.lastReport.healthy !== report.healthy) {
|
|
4862
|
+
this.options.onHealthChange?.(report);
|
|
4863
|
+
}
|
|
4864
|
+
this.lastReport = report;
|
|
4865
|
+
return report;
|
|
4866
|
+
}
|
|
4867
|
+
};
|
|
4868
|
+
function createHealthChecker(options) {
|
|
4869
|
+
return new HealthChecker(options);
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4872
|
+
// src/monitoring/profiler.ts
|
|
4873
|
+
var Profiler = class {
|
|
4874
|
+
profiles = /* @__PURE__ */ new Map();
|
|
4875
|
+
enabled;
|
|
4876
|
+
sampleRate;
|
|
4877
|
+
includeMemory;
|
|
4878
|
+
includeStack;
|
|
4879
|
+
maxSamples;
|
|
4880
|
+
constructor(options = {}) {
|
|
4881
|
+
this.enabled = options.enabled ?? true;
|
|
4882
|
+
this.sampleRate = options.sampleRate ?? 1;
|
|
4883
|
+
this.includeMemory = options.includeMemory ?? false;
|
|
4884
|
+
this.includeStack = options.includeStack ?? false;
|
|
4885
|
+
this.maxSamples = options.maxSamples ?? 1e3;
|
|
4886
|
+
}
|
|
4887
|
+
profile(name, fn) {
|
|
4888
|
+
return async (...args) => {
|
|
4889
|
+
if (!this.enabled || Math.random() > this.sampleRate) {
|
|
4890
|
+
return fn(...args);
|
|
4891
|
+
}
|
|
4892
|
+
const startTime = Date.now();
|
|
4893
|
+
const startMemory = this.includeMemory ? process.memoryUsage() : void 0;
|
|
4894
|
+
const stack = this.includeStack ? new Error().stack : void 0;
|
|
4895
|
+
try {
|
|
4896
|
+
const result = await fn(...args);
|
|
4897
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
4898
|
+
return result;
|
|
4899
|
+
} catch (error) {
|
|
4900
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
4901
|
+
throw error;
|
|
4902
|
+
}
|
|
4903
|
+
};
|
|
4904
|
+
}
|
|
4905
|
+
wrap(name, promise) {
|
|
4906
|
+
if (!this.enabled || Math.random() > this.sampleRate) {
|
|
4907
|
+
return promise;
|
|
4908
|
+
}
|
|
4909
|
+
const startTime = Date.now();
|
|
4910
|
+
const startMemory = this.includeMemory ? process.memoryUsage() : void 0;
|
|
4911
|
+
const stack = this.includeStack ? new Error().stack : void 0;
|
|
4912
|
+
return promise.finally(() => {
|
|
4913
|
+
this.recordSample(name, startTime, startMemory, stack);
|
|
4914
|
+
});
|
|
4915
|
+
}
|
|
4916
|
+
recordSample(name, startTime, startMemory, stack) {
|
|
4917
|
+
const duration = Date.now() - startTime;
|
|
4918
|
+
const sample = {
|
|
4919
|
+
timestamp: startTime,
|
|
4920
|
+
duration
|
|
4921
|
+
};
|
|
4922
|
+
if (this.includeMemory && startMemory) {
|
|
4923
|
+
const currentMemory = process.memoryUsage();
|
|
4924
|
+
sample.memory = {
|
|
4925
|
+
heapUsed: currentMemory.heapUsed - startMemory.heapUsed,
|
|
4926
|
+
heapTotal: currentMemory.heapTotal,
|
|
4927
|
+
external: currentMemory.external
|
|
4928
|
+
};
|
|
4929
|
+
}
|
|
4930
|
+
if (this.includeStack && stack) {
|
|
4931
|
+
sample.stack = stack;
|
|
4932
|
+
}
|
|
4933
|
+
if (!this.profiles.has(name)) {
|
|
4934
|
+
this.profiles.set(name, []);
|
|
4935
|
+
}
|
|
4936
|
+
const samples = this.profiles.get(name);
|
|
4937
|
+
samples.push(sample);
|
|
4938
|
+
if (samples.length > this.maxSamples) {
|
|
4939
|
+
samples.shift();
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
getReport() {
|
|
4943
|
+
const report = {};
|
|
4944
|
+
for (const [name, samples] of this.profiles.entries()) {
|
|
4945
|
+
if (samples.length === 0) {
|
|
4946
|
+
continue;
|
|
4947
|
+
}
|
|
4948
|
+
const durations = samples.map((s) => s.duration).sort((a, b) => a - b);
|
|
4949
|
+
const totalTime = durations.reduce((sum, d) => sum + d, 0);
|
|
4950
|
+
const stats = {
|
|
4951
|
+
calls: samples.length,
|
|
4952
|
+
totalTime,
|
|
4953
|
+
avgTime: totalTime / samples.length,
|
|
4954
|
+
minTime: durations[0],
|
|
4955
|
+
maxTime: durations[durations.length - 1],
|
|
4956
|
+
p50: this.percentile(durations, 0.5),
|
|
4957
|
+
p95: this.percentile(durations, 0.95),
|
|
4958
|
+
p99: this.percentile(durations, 0.99),
|
|
4959
|
+
samples
|
|
4960
|
+
};
|
|
4961
|
+
if (this.includeMemory) {
|
|
4962
|
+
const memorySamples = samples.filter((s) => s.memory).map((s) => s.memory.heapUsed);
|
|
4963
|
+
if (memorySamples.length > 0) {
|
|
4964
|
+
stats.memory = {
|
|
4965
|
+
avgHeapUsed: memorySamples.reduce((sum, m) => sum + m, 0) / memorySamples.length,
|
|
4966
|
+
maxHeapUsed: Math.max(...memorySamples),
|
|
4967
|
+
minHeapUsed: Math.min(...memorySamples)
|
|
4968
|
+
};
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
report[name] = stats;
|
|
4972
|
+
}
|
|
4973
|
+
return report;
|
|
4974
|
+
}
|
|
4975
|
+
percentile(sorted, p) {
|
|
4976
|
+
const index = Math.ceil(sorted.length * p) - 1;
|
|
4977
|
+
return sorted[Math.max(0, index)];
|
|
4978
|
+
}
|
|
4979
|
+
reset(name) {
|
|
4980
|
+
if (name) {
|
|
4981
|
+
this.profiles.delete(name);
|
|
4982
|
+
} else {
|
|
4983
|
+
this.profiles.clear();
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
export(path) {
|
|
4987
|
+
const report = this.getReport();
|
|
4988
|
+
console.log("Exporting profile report to:", path);
|
|
4989
|
+
console.log(JSON.stringify(report, null, 2));
|
|
4990
|
+
}
|
|
4991
|
+
};
|
|
4992
|
+
function createProfiler(options) {
|
|
4993
|
+
return new Profiler(options);
|
|
4994
|
+
}
|
|
4995
|
+
|
|
4996
|
+
// src/monitoring/alerts.ts
|
|
4997
|
+
var logger4 = createLogger("agentforge:core:monitoring:alerts", { level: "info" /* INFO */ });
|
|
4998
|
+
var AlertManager = class {
|
|
4999
|
+
constructor(options) {
|
|
5000
|
+
this.options = options;
|
|
5001
|
+
}
|
|
5002
|
+
lastAlertTime = /* @__PURE__ */ new Map();
|
|
5003
|
+
monitorTimer;
|
|
5004
|
+
running = false;
|
|
5005
|
+
start(metrics, interval = 6e4) {
|
|
5006
|
+
if (this.running || !metrics) {
|
|
5007
|
+
return;
|
|
5008
|
+
}
|
|
5009
|
+
this.running = true;
|
|
5010
|
+
this.monitorTimer = setInterval(() => {
|
|
5011
|
+
const currentMetrics = metrics();
|
|
5012
|
+
this.checkRules(currentMetrics);
|
|
5013
|
+
}, interval);
|
|
5014
|
+
}
|
|
5015
|
+
stop() {
|
|
5016
|
+
if (!this.running) {
|
|
5017
|
+
return;
|
|
5018
|
+
}
|
|
5019
|
+
this.running = false;
|
|
5020
|
+
if (this.monitorTimer) {
|
|
5021
|
+
clearInterval(this.monitorTimer);
|
|
5022
|
+
this.monitorTimer = void 0;
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
async alert(alert) {
|
|
5026
|
+
const fullAlert = {
|
|
5027
|
+
...alert,
|
|
5028
|
+
timestamp: alert.timestamp || Date.now()
|
|
5029
|
+
};
|
|
5030
|
+
if (this.isThrottled(alert.name)) {
|
|
5031
|
+
return;
|
|
5032
|
+
}
|
|
5033
|
+
this.lastAlertTime.set(alert.name, Date.now());
|
|
5034
|
+
this.options.onAlert?.(fullAlert);
|
|
5035
|
+
logger4.warn("Alert triggered", {
|
|
5036
|
+
name: alert.name,
|
|
5037
|
+
severity: alert.severity,
|
|
5038
|
+
message: alert.message,
|
|
5039
|
+
data: alert.data
|
|
5040
|
+
});
|
|
5041
|
+
}
|
|
5042
|
+
checkRules(metrics) {
|
|
5043
|
+
if (!this.options.rules) {
|
|
5044
|
+
return;
|
|
5045
|
+
}
|
|
5046
|
+
for (const rule of this.options.rules) {
|
|
5047
|
+
try {
|
|
5048
|
+
if (rule.condition(metrics)) {
|
|
5049
|
+
this.alert({
|
|
5050
|
+
name: rule.name,
|
|
5051
|
+
severity: rule.severity,
|
|
5052
|
+
message: rule.message || `Alert triggered: ${rule.name}`,
|
|
5053
|
+
data: { metrics }
|
|
5054
|
+
});
|
|
5055
|
+
}
|
|
5056
|
+
} catch (error) {
|
|
5057
|
+
logger4.error("Rule check failed", {
|
|
5058
|
+
ruleName: rule.name,
|
|
5059
|
+
error: error instanceof Error ? error.message : String(error),
|
|
5060
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
5061
|
+
});
|
|
5062
|
+
}
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5065
|
+
isThrottled(name) {
|
|
5066
|
+
const rule = this.options.rules?.find((r) => r.name === name);
|
|
5067
|
+
if (!rule?.throttle) {
|
|
5068
|
+
return false;
|
|
5069
|
+
}
|
|
5070
|
+
const lastTime = this.lastAlertTime.get(name);
|
|
5071
|
+
if (!lastTime) {
|
|
5072
|
+
return false;
|
|
5073
|
+
}
|
|
5074
|
+
return Date.now() - lastTime < rule.throttle;
|
|
5075
|
+
}
|
|
5076
|
+
async sendToChannel(channelName, alert) {
|
|
5077
|
+
const channel = this.options.channels[channelName];
|
|
5078
|
+
if (!channel) {
|
|
5079
|
+
throw new Error(`Channel not found: ${channelName}`);
|
|
5080
|
+
}
|
|
5081
|
+
switch (channel.type) {
|
|
5082
|
+
case "email":
|
|
5083
|
+
logger4.info("Alert sent to email", {
|
|
5084
|
+
channel: channelName,
|
|
5085
|
+
to: channel.config.to,
|
|
5086
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5087
|
+
});
|
|
5088
|
+
break;
|
|
5089
|
+
case "slack":
|
|
5090
|
+
logger4.info("Alert sent to Slack", {
|
|
5091
|
+
channel: channelName,
|
|
5092
|
+
webhookUrl: channel.config.webhookUrl,
|
|
5093
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5094
|
+
});
|
|
5095
|
+
break;
|
|
5096
|
+
case "webhook":
|
|
5097
|
+
logger4.info("Alert sent to webhook", {
|
|
5098
|
+
channel: channelName,
|
|
5099
|
+
url: channel.config.url,
|
|
5100
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5101
|
+
});
|
|
5102
|
+
break;
|
|
5103
|
+
default:
|
|
5104
|
+
logger4.info("Alert sent", {
|
|
5105
|
+
channel: channelName,
|
|
5106
|
+
channelType: channel.type,
|
|
5107
|
+
alert: { name: alert.name, severity: alert.severity, message: alert.message }
|
|
5108
|
+
});
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
getAlertHistory(name, limit = 100) {
|
|
5112
|
+
return [];
|
|
5113
|
+
}
|
|
5114
|
+
clearAlertHistory(name) {
|
|
5115
|
+
if (name) {
|
|
5116
|
+
this.lastAlertTime.delete(name);
|
|
5117
|
+
} else {
|
|
5118
|
+
this.lastAlertTime.clear();
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
};
|
|
5122
|
+
function createAlertManager(options) {
|
|
5123
|
+
return new AlertManager(options);
|
|
5124
|
+
}
|
|
5125
|
+
|
|
5126
|
+
// src/monitoring/audit.ts
|
|
5127
|
+
var AuditLogger = class {
|
|
5128
|
+
constructor(options = {}) {
|
|
5129
|
+
this.options = options;
|
|
5130
|
+
if (options.retention?.autoCleanup) {
|
|
5131
|
+
this.startCleanup();
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
5134
|
+
logs = [];
|
|
5135
|
+
cleanupTimer;
|
|
5136
|
+
async log(entry) {
|
|
5137
|
+
const fullEntry = {
|
|
5138
|
+
...entry,
|
|
5139
|
+
id: this.generateId(),
|
|
5140
|
+
timestamp: entry.timestamp || Date.now(),
|
|
5141
|
+
success: entry.success ?? true
|
|
5142
|
+
};
|
|
5143
|
+
const fields = this.options.fields || {};
|
|
5144
|
+
const filteredEntry = {
|
|
5145
|
+
id: fullEntry.id,
|
|
5146
|
+
userId: fields.userId !== false ? fullEntry.userId : "",
|
|
5147
|
+
action: fields.action !== false ? fullEntry.action : "",
|
|
5148
|
+
resource: fields.resource !== false ? fullEntry.resource : "",
|
|
5149
|
+
timestamp: fields.timestamp !== false ? fullEntry.timestamp : void 0
|
|
5150
|
+
};
|
|
5151
|
+
if (fields.input !== false && fullEntry.input) {
|
|
5152
|
+
filteredEntry.input = fullEntry.input;
|
|
5153
|
+
}
|
|
5154
|
+
if (fields.output !== false && fullEntry.output) {
|
|
5155
|
+
filteredEntry.output = fullEntry.output;
|
|
5156
|
+
}
|
|
5157
|
+
if (fullEntry.metadata) {
|
|
5158
|
+
filteredEntry.metadata = fullEntry.metadata;
|
|
5159
|
+
}
|
|
5160
|
+
if (fullEntry.error) {
|
|
5161
|
+
filteredEntry.error = fullEntry.error;
|
|
5162
|
+
filteredEntry.success = false;
|
|
5163
|
+
}
|
|
5164
|
+
this.logs.push(filteredEntry);
|
|
5165
|
+
this.options.onLog?.(filteredEntry);
|
|
5166
|
+
}
|
|
5167
|
+
async query(query = {}) {
|
|
5168
|
+
let results = [...this.logs];
|
|
5169
|
+
if (query.userId) {
|
|
5170
|
+
results = results.filter((log) => log.userId === query.userId);
|
|
5171
|
+
}
|
|
5172
|
+
if (query.action) {
|
|
5173
|
+
results = results.filter((log) => log.action === query.action);
|
|
5174
|
+
}
|
|
5175
|
+
if (query.resource) {
|
|
5176
|
+
results = results.filter((log) => log.resource === query.resource);
|
|
5177
|
+
}
|
|
5178
|
+
if (query.startDate) {
|
|
5179
|
+
const startTime = query.startDate.getTime();
|
|
5180
|
+
results = results.filter((log) => (log.timestamp || 0) >= startTime);
|
|
5181
|
+
}
|
|
5182
|
+
if (query.endDate) {
|
|
5183
|
+
const endTime = query.endDate.getTime();
|
|
5184
|
+
results = results.filter((log) => (log.timestamp || 0) <= endTime);
|
|
5185
|
+
}
|
|
5186
|
+
const offset = query.offset || 0;
|
|
5187
|
+
const limit = query.limit || 100;
|
|
5188
|
+
results = results.slice(offset, offset + limit);
|
|
5189
|
+
return results;
|
|
5190
|
+
}
|
|
5191
|
+
async export(path, options = {}) {
|
|
5192
|
+
const logs = await this.query({
|
|
5193
|
+
startDate: options.startDate,
|
|
5194
|
+
endDate: options.endDate
|
|
5195
|
+
});
|
|
5196
|
+
const format = options.format || "json";
|
|
5197
|
+
if (format === "json") {
|
|
5198
|
+
console.log(`Exporting ${logs.length} audit logs to ${path} (JSON)`);
|
|
5199
|
+
console.log(JSON.stringify(logs, null, 2));
|
|
5200
|
+
} else if (format === "csv") {
|
|
5201
|
+
console.log(`Exporting ${logs.length} audit logs to ${path} (CSV)`);
|
|
5202
|
+
const csv = this.convertToCSV(logs);
|
|
5203
|
+
console.log(csv);
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
convertToCSV(logs) {
|
|
5207
|
+
if (logs.length === 0) {
|
|
5208
|
+
return "";
|
|
5209
|
+
}
|
|
5210
|
+
const headers = ["id", "userId", "action", "resource", "timestamp", "success"];
|
|
5211
|
+
const rows = logs.map((log) => [
|
|
5212
|
+
log.id,
|
|
5213
|
+
log.userId,
|
|
5214
|
+
log.action,
|
|
5215
|
+
log.resource,
|
|
5216
|
+
log.timestamp,
|
|
5217
|
+
log.success
|
|
5218
|
+
]);
|
|
5219
|
+
return [headers.join(","), ...rows.map((row) => row.join(","))].join("\n");
|
|
5220
|
+
}
|
|
5221
|
+
startCleanup() {
|
|
5222
|
+
const interval = 24 * 60 * 60 * 1e3;
|
|
5223
|
+
this.cleanupTimer = setInterval(() => {
|
|
5224
|
+
this.cleanup();
|
|
5225
|
+
}, interval);
|
|
5226
|
+
}
|
|
5227
|
+
cleanup() {
|
|
5228
|
+
if (!this.options.retention) {
|
|
5229
|
+
return;
|
|
5230
|
+
}
|
|
5231
|
+
const retentionMs = this.options.retention.days * 24 * 60 * 60 * 1e3;
|
|
5232
|
+
const cutoffTime = Date.now() - retentionMs;
|
|
5233
|
+
this.logs = this.logs.filter((log) => (log.timestamp || 0) >= cutoffTime);
|
|
5234
|
+
}
|
|
5235
|
+
generateId() {
|
|
5236
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
5237
|
+
}
|
|
5238
|
+
stop() {
|
|
5239
|
+
if (this.cleanupTimer) {
|
|
5240
|
+
clearInterval(this.cleanupTimer);
|
|
5241
|
+
this.cleanupTimer = void 0;
|
|
5242
|
+
}
|
|
5243
|
+
}
|
|
5244
|
+
};
|
|
5245
|
+
function createAuditLogger(options) {
|
|
5246
|
+
return new AuditLogger(options);
|
|
5247
|
+
}
|
|
5248
|
+
|
|
5249
|
+
// src/prompt-loader/index.ts
|
|
5250
|
+
import { readFileSync } from "fs";
|
|
5251
|
+
import { join } from "path";
|
|
5252
|
+
var MAX_VARIABLE_LENGTH = 500;
|
|
5253
|
+
function sanitizeValue(value) {
|
|
5254
|
+
if (value === void 0 || value === null) return "";
|
|
5255
|
+
let sanitized = String(value);
|
|
5256
|
+
sanitized = sanitized.replace(/^#+\s*/gm, "");
|
|
5257
|
+
sanitized = sanitized.replace(/[\r\n]+/g, " ");
|
|
5258
|
+
sanitized = sanitized.trim().replace(/\s+/g, " ");
|
|
5259
|
+
if (sanitized.length > MAX_VARIABLE_LENGTH) {
|
|
5260
|
+
sanitized = sanitized.substring(0, MAX_VARIABLE_LENGTH) + "...";
|
|
5261
|
+
}
|
|
5262
|
+
return sanitized;
|
|
5263
|
+
}
|
|
5264
|
+
function renderTemplate(template, options) {
|
|
5265
|
+
let rawVariables;
|
|
5266
|
+
let sanitizedVariables;
|
|
5267
|
+
if ("trustedVariables" in options || "untrustedVariables" in options) {
|
|
5268
|
+
const opts = options;
|
|
5269
|
+
rawVariables = {
|
|
5270
|
+
...opts.trustedVariables,
|
|
5271
|
+
...opts.untrustedVariables
|
|
5272
|
+
};
|
|
5273
|
+
const sanitizedUntrusted = {};
|
|
5274
|
+
if (opts.untrustedVariables) {
|
|
5275
|
+
for (const [key, value] of Object.entries(opts.untrustedVariables)) {
|
|
5276
|
+
sanitizedUntrusted[key] = sanitizeValue(value);
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
sanitizedVariables = {
|
|
5280
|
+
...opts.trustedVariables,
|
|
5281
|
+
...sanitizedUntrusted
|
|
5282
|
+
};
|
|
5283
|
+
} else {
|
|
5284
|
+
rawVariables = options;
|
|
5285
|
+
sanitizedVariables = options;
|
|
5286
|
+
}
|
|
5287
|
+
let result = template;
|
|
5288
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, varName, content) => {
|
|
5289
|
+
return rawVariables[varName] ? content : "";
|
|
5290
|
+
});
|
|
5291
|
+
result = result.replace(/\{\{(\w+)\}\}/g, (_, varName) => {
|
|
5292
|
+
const value = sanitizedVariables[varName];
|
|
5293
|
+
if (value === void 0 || value === null) return "";
|
|
5294
|
+
return String(value);
|
|
5295
|
+
});
|
|
5296
|
+
return result;
|
|
5297
|
+
}
|
|
5298
|
+
function loadPrompt(promptName, options = {}, promptsDir) {
|
|
5299
|
+
const baseDir = promptsDir || join(process.cwd(), "prompts");
|
|
5300
|
+
const promptPath = join(baseDir, `${promptName}.md`);
|
|
5301
|
+
try {
|
|
5302
|
+
const template = readFileSync(promptPath, "utf-8");
|
|
5303
|
+
return renderTemplate(template, options);
|
|
5304
|
+
} catch (error) {
|
|
5305
|
+
throw new Error(
|
|
5306
|
+
`Failed to load prompt "${promptName}" from ${promptPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
5307
|
+
);
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
4769
5310
|
export {
|
|
4770
5311
|
AgentError,
|
|
5312
|
+
AlertManager,
|
|
5313
|
+
AuditLogger,
|
|
4771
5314
|
BatchProcessor,
|
|
4772
5315
|
CircuitBreaker,
|
|
4773
5316
|
ConnectionPool,
|
|
4774
5317
|
DatabasePool,
|
|
5318
|
+
HealthChecker,
|
|
4775
5319
|
HttpPool,
|
|
4776
5320
|
LogLevel,
|
|
4777
5321
|
ManagedTool,
|
|
@@ -4779,6 +5323,7 @@ export {
|
|
|
4779
5323
|
MetricType,
|
|
4780
5324
|
MiddlewareChain,
|
|
4781
5325
|
MissingDescriptionError,
|
|
5326
|
+
Profiler,
|
|
4782
5327
|
RegistryEvent,
|
|
4783
5328
|
TimeoutError,
|
|
4784
5329
|
ToolBuilder,
|
|
@@ -4802,7 +5347,9 @@ export {
|
|
|
4802
5347
|
composeWithOptions,
|
|
4803
5348
|
conditional,
|
|
4804
5349
|
configureLangSmith,
|
|
5350
|
+
createAlertManager,
|
|
4805
5351
|
createApprovalRequiredInterrupt,
|
|
5352
|
+
createAuditLogger,
|
|
4806
5353
|
createBatchProcessor,
|
|
4807
5354
|
createBinaryRouter,
|
|
4808
5355
|
createCircuitBreaker,
|
|
@@ -4812,6 +5359,7 @@ export {
|
|
|
4812
5359
|
createCustomInterrupt,
|
|
4813
5360
|
createDatabasePool,
|
|
4814
5361
|
createErrorReporter,
|
|
5362
|
+
createHealthChecker,
|
|
4815
5363
|
createHeartbeat,
|
|
4816
5364
|
createHttpPool,
|
|
4817
5365
|
createHumanRequestInterrupt,
|
|
@@ -4825,6 +5373,7 @@ export {
|
|
|
4825
5373
|
createMockTool,
|
|
4826
5374
|
createMultiRouter,
|
|
4827
5375
|
createParallelWorkflow,
|
|
5376
|
+
createProfiler,
|
|
4828
5377
|
createProgressTracker,
|
|
4829
5378
|
createSSEFormatter,
|
|
4830
5379
|
createSequentialWorkflow,
|
|
@@ -4861,6 +5410,7 @@ export {
|
|
|
4861
5410
|
isHumanRequestInterrupt,
|
|
4862
5411
|
isMemoryCheckpointer,
|
|
4863
5412
|
isTracingEnabled,
|
|
5413
|
+
loadPrompt,
|
|
4864
5414
|
map,
|
|
4865
5415
|
merge,
|
|
4866
5416
|
mergeState,
|
|
@@ -4869,8 +5419,10 @@ export {
|
|
|
4869
5419
|
presets,
|
|
4870
5420
|
production,
|
|
4871
5421
|
reduce,
|
|
5422
|
+
renderTemplate,
|
|
4872
5423
|
retry,
|
|
4873
5424
|
safeValidateSchemaDescriptions,
|
|
5425
|
+
sanitizeValue,
|
|
4874
5426
|
sendMessage,
|
|
4875
5427
|
sequential,
|
|
4876
5428
|
sequentialBuilder,
|