@agentforge/core 0.6.3 → 0.7.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 +157 -101
- package/dist/index.d.cts +48 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +157 -101
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -688,13 +688,51 @@ var ToolBuilder = class {
|
|
|
688
688
|
}
|
|
689
689
|
/**
|
|
690
690
|
* Set the implementation function (required)
|
|
691
|
-
*
|
|
691
|
+
*
|
|
692
692
|
* @param execute - Async function that implements the tool
|
|
693
693
|
*/
|
|
694
694
|
implement(execute) {
|
|
695
695
|
this._execute = execute;
|
|
696
696
|
return this;
|
|
697
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Set the implementation function with automatic error handling
|
|
700
|
+
*
|
|
701
|
+
* Wraps the implementation in a try-catch block and returns a standardized
|
|
702
|
+
* result object with success/error information.
|
|
703
|
+
*
|
|
704
|
+
* @param execute - Async function that implements the tool
|
|
705
|
+
* @returns ToolBuilder with safe result type { success: boolean; data?: T; error?: string }
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```ts
|
|
709
|
+
* const tool = toolBuilder()
|
|
710
|
+
* .name('read-file')
|
|
711
|
+
* .schema(z.object({ path: z.string() }))
|
|
712
|
+
* .implementSafe(async ({ path }) => {
|
|
713
|
+
* return await fs.readFile(path, 'utf-8');
|
|
714
|
+
* })
|
|
715
|
+
* .build();
|
|
716
|
+
*
|
|
717
|
+
* // Result will be: { success: true, data: "file content" }
|
|
718
|
+
* // Or on error: { success: false, error: "ENOENT: no such file..." }
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
implementSafe(execute) {
|
|
722
|
+
const safeExecute = async (input) => {
|
|
723
|
+
try {
|
|
724
|
+
const data = await execute(input);
|
|
725
|
+
return { success: true, data };
|
|
726
|
+
} catch (error) {
|
|
727
|
+
return {
|
|
728
|
+
success: false,
|
|
729
|
+
error: error instanceof Error ? error.message : String(error)
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
this._execute = safeExecute;
|
|
734
|
+
return this;
|
|
735
|
+
}
|
|
698
736
|
/**
|
|
699
737
|
* Build the tool with validation
|
|
700
738
|
*
|
|
@@ -803,7 +841,103 @@ Examples:`);
|
|
|
803
841
|
return parts.join("\n");
|
|
804
842
|
}
|
|
805
843
|
|
|
844
|
+
// src/langgraph/observability/logger.ts
|
|
845
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
846
|
+
LogLevel2["DEBUG"] = "debug";
|
|
847
|
+
LogLevel2["INFO"] = "info";
|
|
848
|
+
LogLevel2["WARN"] = "warn";
|
|
849
|
+
LogLevel2["ERROR"] = "error";
|
|
850
|
+
return LogLevel2;
|
|
851
|
+
})(LogLevel || {});
|
|
852
|
+
var LOG_LEVEL_PRIORITY = {
|
|
853
|
+
["debug" /* DEBUG */]: 0,
|
|
854
|
+
["info" /* INFO */]: 1,
|
|
855
|
+
["warn" /* WARN */]: 2,
|
|
856
|
+
["error" /* ERROR */]: 3
|
|
857
|
+
};
|
|
858
|
+
var LoggerImpl = class _LoggerImpl {
|
|
859
|
+
name;
|
|
860
|
+
options;
|
|
861
|
+
context;
|
|
862
|
+
constructor(name, options = {}, context = {}) {
|
|
863
|
+
this.name = name;
|
|
864
|
+
this.context = context;
|
|
865
|
+
this.options = {
|
|
866
|
+
level: options.level ?? "info" /* INFO */,
|
|
867
|
+
format: options.format ?? "pretty",
|
|
868
|
+
destination: options.destination ?? process.stdout,
|
|
869
|
+
includeTimestamp: options.includeTimestamp ?? true,
|
|
870
|
+
includeContext: options.includeContext ?? true
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
debug(message, data) {
|
|
874
|
+
this.log("debug" /* DEBUG */, message, data);
|
|
875
|
+
}
|
|
876
|
+
info(message, data) {
|
|
877
|
+
this.log("info" /* INFO */, message, data);
|
|
878
|
+
}
|
|
879
|
+
warn(message, data) {
|
|
880
|
+
this.log("warn" /* WARN */, message, data);
|
|
881
|
+
}
|
|
882
|
+
error(message, data) {
|
|
883
|
+
this.log("error" /* ERROR */, message, data);
|
|
884
|
+
}
|
|
885
|
+
isDebugEnabled() {
|
|
886
|
+
return this.isLevelEnabled("debug" /* DEBUG */);
|
|
887
|
+
}
|
|
888
|
+
isLevelEnabled(level) {
|
|
889
|
+
return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.options.level];
|
|
890
|
+
}
|
|
891
|
+
withContext(context) {
|
|
892
|
+
return new _LoggerImpl(this.name, this.options, { ...this.context, ...context });
|
|
893
|
+
}
|
|
894
|
+
log(level, message, data) {
|
|
895
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.options.level]) {
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
const entry = {
|
|
899
|
+
level,
|
|
900
|
+
name: this.name,
|
|
901
|
+
message
|
|
902
|
+
};
|
|
903
|
+
if (this.options.includeTimestamp) {
|
|
904
|
+
entry.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
905
|
+
}
|
|
906
|
+
if (this.options.includeContext && Object.keys(this.context).length > 0) {
|
|
907
|
+
entry.context = this.context;
|
|
908
|
+
}
|
|
909
|
+
if (data) {
|
|
910
|
+
entry.data = data;
|
|
911
|
+
}
|
|
912
|
+
const output = this.format(entry);
|
|
913
|
+
this.options.destination.write(output + "\n");
|
|
914
|
+
}
|
|
915
|
+
format(entry) {
|
|
916
|
+
if (this.options.format === "json") {
|
|
917
|
+
return JSON.stringify(entry);
|
|
918
|
+
}
|
|
919
|
+
const parts = [];
|
|
920
|
+
if (entry.timestamp) {
|
|
921
|
+
parts.push(`[${entry.timestamp}]`);
|
|
922
|
+
}
|
|
923
|
+
parts.push(`[${entry.level.toUpperCase()}]`);
|
|
924
|
+
parts.push(`[${entry.name}]`);
|
|
925
|
+
parts.push(entry.message);
|
|
926
|
+
if (entry.context) {
|
|
927
|
+
parts.push(`context=${JSON.stringify(entry.context)}`);
|
|
928
|
+
}
|
|
929
|
+
if (entry.data) {
|
|
930
|
+
parts.push(`data=${JSON.stringify(entry.data)}`);
|
|
931
|
+
}
|
|
932
|
+
return parts.join(" ");
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
function createLogger(name, options) {
|
|
936
|
+
return new LoggerImpl(name, options);
|
|
937
|
+
}
|
|
938
|
+
|
|
806
939
|
// src/tools/registry.ts
|
|
940
|
+
var logger = createLogger("agentforge:core:tools:registry", { level: "info" /* INFO */ });
|
|
807
941
|
var RegistryEvent = /* @__PURE__ */ ((RegistryEvent2) => {
|
|
808
942
|
RegistryEvent2["TOOL_REGISTERED"] = "tool:registered";
|
|
809
943
|
RegistryEvent2["TOOL_REMOVED"] = "tool:removed";
|
|
@@ -1095,7 +1229,11 @@ var ToolRegistry = class {
|
|
|
1095
1229
|
try {
|
|
1096
1230
|
handler(data);
|
|
1097
1231
|
} catch (error) {
|
|
1098
|
-
|
|
1232
|
+
logger.error("Event handler error", {
|
|
1233
|
+
event,
|
|
1234
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1235
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
1236
|
+
});
|
|
1099
1237
|
}
|
|
1100
1238
|
});
|
|
1101
1239
|
}
|
|
@@ -1493,6 +1631,7 @@ function createToolExecutor(config = {}) {
|
|
|
1493
1631
|
}
|
|
1494
1632
|
|
|
1495
1633
|
// src/tools/lifecycle.ts
|
|
1634
|
+
var logger2 = createLogger("agentforge:core:tools:lifecycle", { level: "info" /* INFO */ });
|
|
1496
1635
|
var ManagedTool = class {
|
|
1497
1636
|
name;
|
|
1498
1637
|
description;
|
|
@@ -1523,7 +1662,13 @@ var ManagedTool = class {
|
|
|
1523
1662
|
this._context = config.context;
|
|
1524
1663
|
if (this.autoCleanup) {
|
|
1525
1664
|
process.on("beforeExit", () => {
|
|
1526
|
-
this.cleanup().catch(
|
|
1665
|
+
this.cleanup().catch(
|
|
1666
|
+
(err) => logger2.error("Cleanup failed", {
|
|
1667
|
+
toolName: this.name,
|
|
1668
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1669
|
+
stack: err instanceof Error ? err.stack : void 0
|
|
1670
|
+
})
|
|
1671
|
+
);
|
|
1527
1672
|
});
|
|
1528
1673
|
}
|
|
1529
1674
|
}
|
|
@@ -2393,95 +2538,6 @@ function withTracing(node, options) {
|
|
|
2393
2538
|
};
|
|
2394
2539
|
}
|
|
2395
2540
|
|
|
2396
|
-
// src/langgraph/observability/logger.ts
|
|
2397
|
-
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
2398
|
-
LogLevel2["DEBUG"] = "debug";
|
|
2399
|
-
LogLevel2["INFO"] = "info";
|
|
2400
|
-
LogLevel2["WARN"] = "warn";
|
|
2401
|
-
LogLevel2["ERROR"] = "error";
|
|
2402
|
-
return LogLevel2;
|
|
2403
|
-
})(LogLevel || {});
|
|
2404
|
-
var LOG_LEVEL_PRIORITY = {
|
|
2405
|
-
["debug" /* DEBUG */]: 0,
|
|
2406
|
-
["info" /* INFO */]: 1,
|
|
2407
|
-
["warn" /* WARN */]: 2,
|
|
2408
|
-
["error" /* ERROR */]: 3
|
|
2409
|
-
};
|
|
2410
|
-
var LoggerImpl = class _LoggerImpl {
|
|
2411
|
-
name;
|
|
2412
|
-
options;
|
|
2413
|
-
context;
|
|
2414
|
-
constructor(name, options = {}, context = {}) {
|
|
2415
|
-
this.name = name;
|
|
2416
|
-
this.context = context;
|
|
2417
|
-
this.options = {
|
|
2418
|
-
level: options.level ?? "info" /* INFO */,
|
|
2419
|
-
format: options.format ?? "pretty",
|
|
2420
|
-
destination: options.destination ?? process.stdout,
|
|
2421
|
-
includeTimestamp: options.includeTimestamp ?? true,
|
|
2422
|
-
includeContext: options.includeContext ?? true
|
|
2423
|
-
};
|
|
2424
|
-
}
|
|
2425
|
-
debug(message, data) {
|
|
2426
|
-
this.log("debug" /* DEBUG */, message, data);
|
|
2427
|
-
}
|
|
2428
|
-
info(message, data) {
|
|
2429
|
-
this.log("info" /* INFO */, message, data);
|
|
2430
|
-
}
|
|
2431
|
-
warn(message, data) {
|
|
2432
|
-
this.log("warn" /* WARN */, message, data);
|
|
2433
|
-
}
|
|
2434
|
-
error(message, data) {
|
|
2435
|
-
this.log("error" /* ERROR */, message, data);
|
|
2436
|
-
}
|
|
2437
|
-
withContext(context) {
|
|
2438
|
-
return new _LoggerImpl(this.name, this.options, { ...this.context, ...context });
|
|
2439
|
-
}
|
|
2440
|
-
log(level, message, data) {
|
|
2441
|
-
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.options.level]) {
|
|
2442
|
-
return;
|
|
2443
|
-
}
|
|
2444
|
-
const entry = {
|
|
2445
|
-
level,
|
|
2446
|
-
name: this.name,
|
|
2447
|
-
message
|
|
2448
|
-
};
|
|
2449
|
-
if (this.options.includeTimestamp) {
|
|
2450
|
-
entry.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2451
|
-
}
|
|
2452
|
-
if (this.options.includeContext && Object.keys(this.context).length > 0) {
|
|
2453
|
-
entry.context = this.context;
|
|
2454
|
-
}
|
|
2455
|
-
if (data) {
|
|
2456
|
-
entry.data = data;
|
|
2457
|
-
}
|
|
2458
|
-
const output = this.format(entry);
|
|
2459
|
-
this.options.destination.write(output + "\n");
|
|
2460
|
-
}
|
|
2461
|
-
format(entry) {
|
|
2462
|
-
if (this.options.format === "json") {
|
|
2463
|
-
return JSON.stringify(entry);
|
|
2464
|
-
}
|
|
2465
|
-
const parts = [];
|
|
2466
|
-
if (entry.timestamp) {
|
|
2467
|
-
parts.push(`[${entry.timestamp}]`);
|
|
2468
|
-
}
|
|
2469
|
-
parts.push(`[${entry.level.toUpperCase()}]`);
|
|
2470
|
-
parts.push(`[${entry.name}]`);
|
|
2471
|
-
parts.push(entry.message);
|
|
2472
|
-
if (entry.context) {
|
|
2473
|
-
parts.push(`context=${JSON.stringify(entry.context)}`);
|
|
2474
|
-
}
|
|
2475
|
-
if (entry.data) {
|
|
2476
|
-
parts.push(`data=${JSON.stringify(entry.data)}`);
|
|
2477
|
-
}
|
|
2478
|
-
return parts.join(" ");
|
|
2479
|
-
}
|
|
2480
|
-
};
|
|
2481
|
-
function createLogger(name, options) {
|
|
2482
|
-
return new LoggerImpl(name, options);
|
|
2483
|
-
}
|
|
2484
|
-
|
|
2485
2541
|
// src/langgraph/observability/metrics.ts
|
|
2486
2542
|
var MetricType = /* @__PURE__ */ ((MetricType2) => {
|
|
2487
2543
|
MetricType2["COUNTER"] = "counter";
|
|
@@ -2791,14 +2847,14 @@ var withLogging = (options) => {
|
|
|
2791
2847
|
onComplete,
|
|
2792
2848
|
onError
|
|
2793
2849
|
} = options;
|
|
2794
|
-
const
|
|
2850
|
+
const logger3 = providedLogger || createLogger(name, { level });
|
|
2795
2851
|
return (node) => {
|
|
2796
2852
|
return async (state) => {
|
|
2797
2853
|
const startTime = Date.now();
|
|
2798
2854
|
try {
|
|
2799
2855
|
if (logInput) {
|
|
2800
2856
|
const data = extractData ? extractData(state) : { state };
|
|
2801
|
-
|
|
2857
|
+
logger3.info("Node execution started", data);
|
|
2802
2858
|
}
|
|
2803
2859
|
if (onStart) {
|
|
2804
2860
|
onStart(state);
|
|
@@ -2808,9 +2864,9 @@ var withLogging = (options) => {
|
|
|
2808
2864
|
if (logOutput) {
|
|
2809
2865
|
const data = extractData ? extractData(result) : { result };
|
|
2810
2866
|
if (logDuration) {
|
|
2811
|
-
|
|
2867
|
+
logger3.info(`Node execution completed (${duration}ms)`, data);
|
|
2812
2868
|
} else {
|
|
2813
|
-
|
|
2869
|
+
logger3.info("Node execution completed", data);
|
|
2814
2870
|
}
|
|
2815
2871
|
}
|
|
2816
2872
|
if (onComplete) {
|
|
@@ -2821,7 +2877,7 @@ var withLogging = (options) => {
|
|
|
2821
2877
|
const duration = Date.now() - startTime;
|
|
2822
2878
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2823
2879
|
if (logErrors) {
|
|
2824
|
-
|
|
2880
|
+
logger3.error(`Node execution failed (${duration}ms)`, {
|
|
2825
2881
|
error: err.message,
|
|
2826
2882
|
stack: err.stack
|
|
2827
2883
|
});
|
|
@@ -2857,7 +2913,7 @@ function withLogging2(options) {
|
|
|
2857
2913
|
function production(node, options) {
|
|
2858
2914
|
const {
|
|
2859
2915
|
nodeName,
|
|
2860
|
-
logger,
|
|
2916
|
+
logger: logger3,
|
|
2861
2917
|
enableMetrics = true,
|
|
2862
2918
|
enableTracing = true,
|
|
2863
2919
|
enableRetry = true,
|
|
@@ -2865,7 +2921,7 @@ function production(node, options) {
|
|
|
2865
2921
|
retryOptions = {},
|
|
2866
2922
|
errorOptions = {}
|
|
2867
2923
|
} = options;
|
|
2868
|
-
const actualLogger =
|
|
2924
|
+
const actualLogger = logger3 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2869
2925
|
const middleware = [];
|
|
2870
2926
|
middleware.push(
|
|
2871
2927
|
withLogging2({
|
|
@@ -2929,9 +2985,9 @@ function development(node, options) {
|
|
|
2929
2985
|
const {
|
|
2930
2986
|
nodeName,
|
|
2931
2987
|
verbose = true,
|
|
2932
|
-
logger
|
|
2988
|
+
logger: logger3
|
|
2933
2989
|
} = options;
|
|
2934
|
-
const actualLogger =
|
|
2990
|
+
const actualLogger = logger3 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2935
2991
|
return withLogging2({
|
|
2936
2992
|
logger: actualLogger,
|
|
2937
2993
|
name: nodeName,
|
package/dist/index.d.cts
CHANGED
|
@@ -1070,6 +1070,34 @@ declare class ToolBuilder<TInput = unknown, TOutput = unknown> {
|
|
|
1070
1070
|
* @param execute - Async function that implements the tool
|
|
1071
1071
|
*/
|
|
1072
1072
|
implement<T>(execute: (input: TInput) => Promise<T>): ToolBuilder<TInput, T>;
|
|
1073
|
+
/**
|
|
1074
|
+
* Set the implementation function with automatic error handling
|
|
1075
|
+
*
|
|
1076
|
+
* Wraps the implementation in a try-catch block and returns a standardized
|
|
1077
|
+
* result object with success/error information.
|
|
1078
|
+
*
|
|
1079
|
+
* @param execute - Async function that implements the tool
|
|
1080
|
+
* @returns ToolBuilder with safe result type { success: boolean; data?: T; error?: string }
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* ```ts
|
|
1084
|
+
* const tool = toolBuilder()
|
|
1085
|
+
* .name('read-file')
|
|
1086
|
+
* .schema(z.object({ path: z.string() }))
|
|
1087
|
+
* .implementSafe(async ({ path }) => {
|
|
1088
|
+
* return await fs.readFile(path, 'utf-8');
|
|
1089
|
+
* })
|
|
1090
|
+
* .build();
|
|
1091
|
+
*
|
|
1092
|
+
* // Result will be: { success: true, data: "file content" }
|
|
1093
|
+
* // Or on error: { success: false, error: "ENOENT: no such file..." }
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
implementSafe<T>(execute: (input: TInput) => Promise<T>): ToolBuilder<TInput, {
|
|
1097
|
+
success: boolean;
|
|
1098
|
+
data?: T;
|
|
1099
|
+
error?: string;
|
|
1100
|
+
}>;
|
|
1073
1101
|
/**
|
|
1074
1102
|
* Build the tool with validation
|
|
1075
1103
|
*
|
|
@@ -3013,6 +3041,15 @@ interface Logger {
|
|
|
3013
3041
|
* Log an error message
|
|
3014
3042
|
*/
|
|
3015
3043
|
error(message: string, data?: Record<string, any>): void;
|
|
3044
|
+
/**
|
|
3045
|
+
* Check if debug logging is enabled
|
|
3046
|
+
* Useful for avoiding expensive computations when debug is disabled
|
|
3047
|
+
*/
|
|
3048
|
+
isDebugEnabled(): boolean;
|
|
3049
|
+
/**
|
|
3050
|
+
* Check if a specific log level is enabled
|
|
3051
|
+
*/
|
|
3052
|
+
isLevelEnabled(level: LogLevel): boolean;
|
|
3016
3053
|
/**
|
|
3017
3054
|
* Create a child logger with additional context
|
|
3018
3055
|
*/
|
|
@@ -3022,6 +3059,7 @@ interface Logger {
|
|
|
3022
3059
|
* Create a structured logger.
|
|
3023
3060
|
*
|
|
3024
3061
|
* @example
|
|
3062
|
+
* Basic usage:
|
|
3025
3063
|
* ```typescript
|
|
3026
3064
|
* import { createLogger, LogLevel } from '@agentforge/core';
|
|
3027
3065
|
*
|
|
@@ -3034,6 +3072,16 @@ interface Logger {
|
|
|
3034
3072
|
* logger.error('Request failed', { error: err.message });
|
|
3035
3073
|
* ```
|
|
3036
3074
|
*
|
|
3075
|
+
* @example
|
|
3076
|
+
* Performance optimization with isDebugEnabled:
|
|
3077
|
+
* ```typescript
|
|
3078
|
+
* // Avoid expensive computations when debug is disabled
|
|
3079
|
+
* if (logger.isDebugEnabled()) {
|
|
3080
|
+
* const expensiveData = computeExpensiveDebugInfo();
|
|
3081
|
+
* logger.debug('Debug info', expensiveData);
|
|
3082
|
+
* }
|
|
3083
|
+
* ```
|
|
3084
|
+
*
|
|
3037
3085
|
* @param name - Logger name (typically the agent or component name)
|
|
3038
3086
|
* @param options - Logger configuration options
|
|
3039
3087
|
* @returns A logger instance
|
package/dist/index.d.ts
CHANGED
|
@@ -1070,6 +1070,34 @@ declare class ToolBuilder<TInput = unknown, TOutput = unknown> {
|
|
|
1070
1070
|
* @param execute - Async function that implements the tool
|
|
1071
1071
|
*/
|
|
1072
1072
|
implement<T>(execute: (input: TInput) => Promise<T>): ToolBuilder<TInput, T>;
|
|
1073
|
+
/**
|
|
1074
|
+
* Set the implementation function with automatic error handling
|
|
1075
|
+
*
|
|
1076
|
+
* Wraps the implementation in a try-catch block and returns a standardized
|
|
1077
|
+
* result object with success/error information.
|
|
1078
|
+
*
|
|
1079
|
+
* @param execute - Async function that implements the tool
|
|
1080
|
+
* @returns ToolBuilder with safe result type { success: boolean; data?: T; error?: string }
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* ```ts
|
|
1084
|
+
* const tool = toolBuilder()
|
|
1085
|
+
* .name('read-file')
|
|
1086
|
+
* .schema(z.object({ path: z.string() }))
|
|
1087
|
+
* .implementSafe(async ({ path }) => {
|
|
1088
|
+
* return await fs.readFile(path, 'utf-8');
|
|
1089
|
+
* })
|
|
1090
|
+
* .build();
|
|
1091
|
+
*
|
|
1092
|
+
* // Result will be: { success: true, data: "file content" }
|
|
1093
|
+
* // Or on error: { success: false, error: "ENOENT: no such file..." }
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
implementSafe<T>(execute: (input: TInput) => Promise<T>): ToolBuilder<TInput, {
|
|
1097
|
+
success: boolean;
|
|
1098
|
+
data?: T;
|
|
1099
|
+
error?: string;
|
|
1100
|
+
}>;
|
|
1073
1101
|
/**
|
|
1074
1102
|
* Build the tool with validation
|
|
1075
1103
|
*
|
|
@@ -3013,6 +3041,15 @@ interface Logger {
|
|
|
3013
3041
|
* Log an error message
|
|
3014
3042
|
*/
|
|
3015
3043
|
error(message: string, data?: Record<string, any>): void;
|
|
3044
|
+
/**
|
|
3045
|
+
* Check if debug logging is enabled
|
|
3046
|
+
* Useful for avoiding expensive computations when debug is disabled
|
|
3047
|
+
*/
|
|
3048
|
+
isDebugEnabled(): boolean;
|
|
3049
|
+
/**
|
|
3050
|
+
* Check if a specific log level is enabled
|
|
3051
|
+
*/
|
|
3052
|
+
isLevelEnabled(level: LogLevel): boolean;
|
|
3016
3053
|
/**
|
|
3017
3054
|
* Create a child logger with additional context
|
|
3018
3055
|
*/
|
|
@@ -3022,6 +3059,7 @@ interface Logger {
|
|
|
3022
3059
|
* Create a structured logger.
|
|
3023
3060
|
*
|
|
3024
3061
|
* @example
|
|
3062
|
+
* Basic usage:
|
|
3025
3063
|
* ```typescript
|
|
3026
3064
|
* import { createLogger, LogLevel } from '@agentforge/core';
|
|
3027
3065
|
*
|
|
@@ -3034,6 +3072,16 @@ interface Logger {
|
|
|
3034
3072
|
* logger.error('Request failed', { error: err.message });
|
|
3035
3073
|
* ```
|
|
3036
3074
|
*
|
|
3075
|
+
* @example
|
|
3076
|
+
* Performance optimization with isDebugEnabled:
|
|
3077
|
+
* ```typescript
|
|
3078
|
+
* // Avoid expensive computations when debug is disabled
|
|
3079
|
+
* if (logger.isDebugEnabled()) {
|
|
3080
|
+
* const expensiveData = computeExpensiveDebugInfo();
|
|
3081
|
+
* logger.debug('Debug info', expensiveData);
|
|
3082
|
+
* }
|
|
3083
|
+
* ```
|
|
3084
|
+
*
|
|
3037
3085
|
* @param name - Logger name (typically the agent or component name)
|
|
3038
3086
|
* @param options - Logger configuration options
|
|
3039
3087
|
* @returns A logger instance
|
package/dist/index.js
CHANGED
|
@@ -532,13 +532,51 @@ var ToolBuilder = class {
|
|
|
532
532
|
}
|
|
533
533
|
/**
|
|
534
534
|
* Set the implementation function (required)
|
|
535
|
-
*
|
|
535
|
+
*
|
|
536
536
|
* @param execute - Async function that implements the tool
|
|
537
537
|
*/
|
|
538
538
|
implement(execute) {
|
|
539
539
|
this._execute = execute;
|
|
540
540
|
return this;
|
|
541
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Set the implementation function with automatic error handling
|
|
544
|
+
*
|
|
545
|
+
* Wraps the implementation in a try-catch block and returns a standardized
|
|
546
|
+
* result object with success/error information.
|
|
547
|
+
*
|
|
548
|
+
* @param execute - Async function that implements the tool
|
|
549
|
+
* @returns ToolBuilder with safe result type { success: boolean; data?: T; error?: string }
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* ```ts
|
|
553
|
+
* const tool = toolBuilder()
|
|
554
|
+
* .name('read-file')
|
|
555
|
+
* .schema(z.object({ path: z.string() }))
|
|
556
|
+
* .implementSafe(async ({ path }) => {
|
|
557
|
+
* return await fs.readFile(path, 'utf-8');
|
|
558
|
+
* })
|
|
559
|
+
* .build();
|
|
560
|
+
*
|
|
561
|
+
* // Result will be: { success: true, data: "file content" }
|
|
562
|
+
* // Or on error: { success: false, error: "ENOENT: no such file..." }
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
implementSafe(execute) {
|
|
566
|
+
const safeExecute = async (input) => {
|
|
567
|
+
try {
|
|
568
|
+
const data = await execute(input);
|
|
569
|
+
return { success: true, data };
|
|
570
|
+
} catch (error) {
|
|
571
|
+
return {
|
|
572
|
+
success: false,
|
|
573
|
+
error: error instanceof Error ? error.message : String(error)
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
this._execute = safeExecute;
|
|
578
|
+
return this;
|
|
579
|
+
}
|
|
542
580
|
/**
|
|
543
581
|
* Build the tool with validation
|
|
544
582
|
*
|
|
@@ -647,7 +685,103 @@ Examples:`);
|
|
|
647
685
|
return parts.join("\n");
|
|
648
686
|
}
|
|
649
687
|
|
|
688
|
+
// src/langgraph/observability/logger.ts
|
|
689
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
690
|
+
LogLevel2["DEBUG"] = "debug";
|
|
691
|
+
LogLevel2["INFO"] = "info";
|
|
692
|
+
LogLevel2["WARN"] = "warn";
|
|
693
|
+
LogLevel2["ERROR"] = "error";
|
|
694
|
+
return LogLevel2;
|
|
695
|
+
})(LogLevel || {});
|
|
696
|
+
var LOG_LEVEL_PRIORITY = {
|
|
697
|
+
["debug" /* DEBUG */]: 0,
|
|
698
|
+
["info" /* INFO */]: 1,
|
|
699
|
+
["warn" /* WARN */]: 2,
|
|
700
|
+
["error" /* ERROR */]: 3
|
|
701
|
+
};
|
|
702
|
+
var LoggerImpl = class _LoggerImpl {
|
|
703
|
+
name;
|
|
704
|
+
options;
|
|
705
|
+
context;
|
|
706
|
+
constructor(name, options = {}, context = {}) {
|
|
707
|
+
this.name = name;
|
|
708
|
+
this.context = context;
|
|
709
|
+
this.options = {
|
|
710
|
+
level: options.level ?? "info" /* INFO */,
|
|
711
|
+
format: options.format ?? "pretty",
|
|
712
|
+
destination: options.destination ?? process.stdout,
|
|
713
|
+
includeTimestamp: options.includeTimestamp ?? true,
|
|
714
|
+
includeContext: options.includeContext ?? true
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
debug(message, data) {
|
|
718
|
+
this.log("debug" /* DEBUG */, message, data);
|
|
719
|
+
}
|
|
720
|
+
info(message, data) {
|
|
721
|
+
this.log("info" /* INFO */, message, data);
|
|
722
|
+
}
|
|
723
|
+
warn(message, data) {
|
|
724
|
+
this.log("warn" /* WARN */, message, data);
|
|
725
|
+
}
|
|
726
|
+
error(message, data) {
|
|
727
|
+
this.log("error" /* ERROR */, message, data);
|
|
728
|
+
}
|
|
729
|
+
isDebugEnabled() {
|
|
730
|
+
return this.isLevelEnabled("debug" /* DEBUG */);
|
|
731
|
+
}
|
|
732
|
+
isLevelEnabled(level) {
|
|
733
|
+
return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.options.level];
|
|
734
|
+
}
|
|
735
|
+
withContext(context) {
|
|
736
|
+
return new _LoggerImpl(this.name, this.options, { ...this.context, ...context });
|
|
737
|
+
}
|
|
738
|
+
log(level, message, data) {
|
|
739
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.options.level]) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const entry = {
|
|
743
|
+
level,
|
|
744
|
+
name: this.name,
|
|
745
|
+
message
|
|
746
|
+
};
|
|
747
|
+
if (this.options.includeTimestamp) {
|
|
748
|
+
entry.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
749
|
+
}
|
|
750
|
+
if (this.options.includeContext && Object.keys(this.context).length > 0) {
|
|
751
|
+
entry.context = this.context;
|
|
752
|
+
}
|
|
753
|
+
if (data) {
|
|
754
|
+
entry.data = data;
|
|
755
|
+
}
|
|
756
|
+
const output = this.format(entry);
|
|
757
|
+
this.options.destination.write(output + "\n");
|
|
758
|
+
}
|
|
759
|
+
format(entry) {
|
|
760
|
+
if (this.options.format === "json") {
|
|
761
|
+
return JSON.stringify(entry);
|
|
762
|
+
}
|
|
763
|
+
const parts = [];
|
|
764
|
+
if (entry.timestamp) {
|
|
765
|
+
parts.push(`[${entry.timestamp}]`);
|
|
766
|
+
}
|
|
767
|
+
parts.push(`[${entry.level.toUpperCase()}]`);
|
|
768
|
+
parts.push(`[${entry.name}]`);
|
|
769
|
+
parts.push(entry.message);
|
|
770
|
+
if (entry.context) {
|
|
771
|
+
parts.push(`context=${JSON.stringify(entry.context)}`);
|
|
772
|
+
}
|
|
773
|
+
if (entry.data) {
|
|
774
|
+
parts.push(`data=${JSON.stringify(entry.data)}`);
|
|
775
|
+
}
|
|
776
|
+
return parts.join(" ");
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
function createLogger(name, options) {
|
|
780
|
+
return new LoggerImpl(name, options);
|
|
781
|
+
}
|
|
782
|
+
|
|
650
783
|
// src/tools/registry.ts
|
|
784
|
+
var logger = createLogger("agentforge:core:tools:registry", { level: "info" /* INFO */ });
|
|
651
785
|
var RegistryEvent = /* @__PURE__ */ ((RegistryEvent2) => {
|
|
652
786
|
RegistryEvent2["TOOL_REGISTERED"] = "tool:registered";
|
|
653
787
|
RegistryEvent2["TOOL_REMOVED"] = "tool:removed";
|
|
@@ -939,7 +1073,11 @@ var ToolRegistry = class {
|
|
|
939
1073
|
try {
|
|
940
1074
|
handler(data);
|
|
941
1075
|
} catch (error) {
|
|
942
|
-
|
|
1076
|
+
logger.error("Event handler error", {
|
|
1077
|
+
event,
|
|
1078
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1079
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
1080
|
+
});
|
|
943
1081
|
}
|
|
944
1082
|
});
|
|
945
1083
|
}
|
|
@@ -1337,6 +1475,7 @@ function createToolExecutor(config = {}) {
|
|
|
1337
1475
|
}
|
|
1338
1476
|
|
|
1339
1477
|
// src/tools/lifecycle.ts
|
|
1478
|
+
var logger2 = createLogger("agentforge:core:tools:lifecycle", { level: "info" /* INFO */ });
|
|
1340
1479
|
var ManagedTool = class {
|
|
1341
1480
|
name;
|
|
1342
1481
|
description;
|
|
@@ -1367,7 +1506,13 @@ var ManagedTool = class {
|
|
|
1367
1506
|
this._context = config.context;
|
|
1368
1507
|
if (this.autoCleanup) {
|
|
1369
1508
|
process.on("beforeExit", () => {
|
|
1370
|
-
this.cleanup().catch(
|
|
1509
|
+
this.cleanup().catch(
|
|
1510
|
+
(err) => logger2.error("Cleanup failed", {
|
|
1511
|
+
toolName: this.name,
|
|
1512
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1513
|
+
stack: err instanceof Error ? err.stack : void 0
|
|
1514
|
+
})
|
|
1515
|
+
);
|
|
1371
1516
|
});
|
|
1372
1517
|
}
|
|
1373
1518
|
}
|
|
@@ -2237,95 +2382,6 @@ function withTracing(node, options) {
|
|
|
2237
2382
|
};
|
|
2238
2383
|
}
|
|
2239
2384
|
|
|
2240
|
-
// src/langgraph/observability/logger.ts
|
|
2241
|
-
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
2242
|
-
LogLevel2["DEBUG"] = "debug";
|
|
2243
|
-
LogLevel2["INFO"] = "info";
|
|
2244
|
-
LogLevel2["WARN"] = "warn";
|
|
2245
|
-
LogLevel2["ERROR"] = "error";
|
|
2246
|
-
return LogLevel2;
|
|
2247
|
-
})(LogLevel || {});
|
|
2248
|
-
var LOG_LEVEL_PRIORITY = {
|
|
2249
|
-
["debug" /* DEBUG */]: 0,
|
|
2250
|
-
["info" /* INFO */]: 1,
|
|
2251
|
-
["warn" /* WARN */]: 2,
|
|
2252
|
-
["error" /* ERROR */]: 3
|
|
2253
|
-
};
|
|
2254
|
-
var LoggerImpl = class _LoggerImpl {
|
|
2255
|
-
name;
|
|
2256
|
-
options;
|
|
2257
|
-
context;
|
|
2258
|
-
constructor(name, options = {}, context = {}) {
|
|
2259
|
-
this.name = name;
|
|
2260
|
-
this.context = context;
|
|
2261
|
-
this.options = {
|
|
2262
|
-
level: options.level ?? "info" /* INFO */,
|
|
2263
|
-
format: options.format ?? "pretty",
|
|
2264
|
-
destination: options.destination ?? process.stdout,
|
|
2265
|
-
includeTimestamp: options.includeTimestamp ?? true,
|
|
2266
|
-
includeContext: options.includeContext ?? true
|
|
2267
|
-
};
|
|
2268
|
-
}
|
|
2269
|
-
debug(message, data) {
|
|
2270
|
-
this.log("debug" /* DEBUG */, message, data);
|
|
2271
|
-
}
|
|
2272
|
-
info(message, data) {
|
|
2273
|
-
this.log("info" /* INFO */, message, data);
|
|
2274
|
-
}
|
|
2275
|
-
warn(message, data) {
|
|
2276
|
-
this.log("warn" /* WARN */, message, data);
|
|
2277
|
-
}
|
|
2278
|
-
error(message, data) {
|
|
2279
|
-
this.log("error" /* ERROR */, message, data);
|
|
2280
|
-
}
|
|
2281
|
-
withContext(context) {
|
|
2282
|
-
return new _LoggerImpl(this.name, this.options, { ...this.context, ...context });
|
|
2283
|
-
}
|
|
2284
|
-
log(level, message, data) {
|
|
2285
|
-
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.options.level]) {
|
|
2286
|
-
return;
|
|
2287
|
-
}
|
|
2288
|
-
const entry = {
|
|
2289
|
-
level,
|
|
2290
|
-
name: this.name,
|
|
2291
|
-
message
|
|
2292
|
-
};
|
|
2293
|
-
if (this.options.includeTimestamp) {
|
|
2294
|
-
entry.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2295
|
-
}
|
|
2296
|
-
if (this.options.includeContext && Object.keys(this.context).length > 0) {
|
|
2297
|
-
entry.context = this.context;
|
|
2298
|
-
}
|
|
2299
|
-
if (data) {
|
|
2300
|
-
entry.data = data;
|
|
2301
|
-
}
|
|
2302
|
-
const output = this.format(entry);
|
|
2303
|
-
this.options.destination.write(output + "\n");
|
|
2304
|
-
}
|
|
2305
|
-
format(entry) {
|
|
2306
|
-
if (this.options.format === "json") {
|
|
2307
|
-
return JSON.stringify(entry);
|
|
2308
|
-
}
|
|
2309
|
-
const parts = [];
|
|
2310
|
-
if (entry.timestamp) {
|
|
2311
|
-
parts.push(`[${entry.timestamp}]`);
|
|
2312
|
-
}
|
|
2313
|
-
parts.push(`[${entry.level.toUpperCase()}]`);
|
|
2314
|
-
parts.push(`[${entry.name}]`);
|
|
2315
|
-
parts.push(entry.message);
|
|
2316
|
-
if (entry.context) {
|
|
2317
|
-
parts.push(`context=${JSON.stringify(entry.context)}`);
|
|
2318
|
-
}
|
|
2319
|
-
if (entry.data) {
|
|
2320
|
-
parts.push(`data=${JSON.stringify(entry.data)}`);
|
|
2321
|
-
}
|
|
2322
|
-
return parts.join(" ");
|
|
2323
|
-
}
|
|
2324
|
-
};
|
|
2325
|
-
function createLogger(name, options) {
|
|
2326
|
-
return new LoggerImpl(name, options);
|
|
2327
|
-
}
|
|
2328
|
-
|
|
2329
2385
|
// src/langgraph/observability/metrics.ts
|
|
2330
2386
|
var MetricType = /* @__PURE__ */ ((MetricType2) => {
|
|
2331
2387
|
MetricType2["COUNTER"] = "counter";
|
|
@@ -2635,14 +2691,14 @@ var withLogging = (options) => {
|
|
|
2635
2691
|
onComplete,
|
|
2636
2692
|
onError
|
|
2637
2693
|
} = options;
|
|
2638
|
-
const
|
|
2694
|
+
const logger3 = providedLogger || createLogger(name, { level });
|
|
2639
2695
|
return (node) => {
|
|
2640
2696
|
return async (state) => {
|
|
2641
2697
|
const startTime = Date.now();
|
|
2642
2698
|
try {
|
|
2643
2699
|
if (logInput) {
|
|
2644
2700
|
const data = extractData ? extractData(state) : { state };
|
|
2645
|
-
|
|
2701
|
+
logger3.info("Node execution started", data);
|
|
2646
2702
|
}
|
|
2647
2703
|
if (onStart) {
|
|
2648
2704
|
onStart(state);
|
|
@@ -2652,9 +2708,9 @@ var withLogging = (options) => {
|
|
|
2652
2708
|
if (logOutput) {
|
|
2653
2709
|
const data = extractData ? extractData(result) : { result };
|
|
2654
2710
|
if (logDuration) {
|
|
2655
|
-
|
|
2711
|
+
logger3.info(`Node execution completed (${duration}ms)`, data);
|
|
2656
2712
|
} else {
|
|
2657
|
-
|
|
2713
|
+
logger3.info("Node execution completed", data);
|
|
2658
2714
|
}
|
|
2659
2715
|
}
|
|
2660
2716
|
if (onComplete) {
|
|
@@ -2665,7 +2721,7 @@ var withLogging = (options) => {
|
|
|
2665
2721
|
const duration = Date.now() - startTime;
|
|
2666
2722
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
2667
2723
|
if (logErrors) {
|
|
2668
|
-
|
|
2724
|
+
logger3.error(`Node execution failed (${duration}ms)`, {
|
|
2669
2725
|
error: err.message,
|
|
2670
2726
|
stack: err.stack
|
|
2671
2727
|
});
|
|
@@ -2701,7 +2757,7 @@ function withLogging2(options) {
|
|
|
2701
2757
|
function production(node, options) {
|
|
2702
2758
|
const {
|
|
2703
2759
|
nodeName,
|
|
2704
|
-
logger,
|
|
2760
|
+
logger: logger3,
|
|
2705
2761
|
enableMetrics = true,
|
|
2706
2762
|
enableTracing = true,
|
|
2707
2763
|
enableRetry = true,
|
|
@@ -2709,7 +2765,7 @@ function production(node, options) {
|
|
|
2709
2765
|
retryOptions = {},
|
|
2710
2766
|
errorOptions = {}
|
|
2711
2767
|
} = options;
|
|
2712
|
-
const actualLogger =
|
|
2768
|
+
const actualLogger = logger3 || createLogger(nodeName, { level: "info" /* INFO */ });
|
|
2713
2769
|
const middleware = [];
|
|
2714
2770
|
middleware.push(
|
|
2715
2771
|
withLogging2({
|
|
@@ -2773,9 +2829,9 @@ function development(node, options) {
|
|
|
2773
2829
|
const {
|
|
2774
2830
|
nodeName,
|
|
2775
2831
|
verbose = true,
|
|
2776
|
-
logger
|
|
2832
|
+
logger: logger3
|
|
2777
2833
|
} = options;
|
|
2778
|
-
const actualLogger =
|
|
2834
|
+
const actualLogger = logger3 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
|
|
2779
2835
|
return withLogging2({
|
|
2780
2836
|
logger: actualLogger,
|
|
2781
2837
|
name: nodeName,
|