@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 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
- console.error(`Error in event handler for ${event}:`, error);
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(console.error);
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 logger = providedLogger || createLogger(name, { level });
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
- logger.info("Node execution started", data);
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
- logger.info(`Node execution completed (${duration}ms)`, data);
2867
+ logger3.info(`Node execution completed (${duration}ms)`, data);
2812
2868
  } else {
2813
- logger.info("Node execution completed", data);
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
- logger.error(`Node execution failed (${duration}ms)`, {
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 = logger || createLogger(nodeName, { level: "info" /* INFO */ });
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 = logger || createLogger(nodeName, { level: "debug" /* DEBUG */ });
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
- console.error(`Error in event handler for ${event}:`, error);
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(console.error);
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 logger = providedLogger || createLogger(name, { level });
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
- logger.info("Node execution started", data);
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
- logger.info(`Node execution completed (${duration}ms)`, data);
2711
+ logger3.info(`Node execution completed (${duration}ms)`, data);
2656
2712
  } else {
2657
- logger.info("Node execution completed", data);
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
- logger.error(`Node execution failed (${duration}ms)`, {
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 = logger || createLogger(nodeName, { level: "info" /* INFO */ });
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 = logger || createLogger(nodeName, { level: "debug" /* DEBUG */ });
2834
+ const actualLogger = logger3 || createLogger(nodeName, { level: "debug" /* DEBUG */ });
2779
2835
  return withLogging2({
2780
2836
  logger: actualLogger,
2781
2837
  name: nodeName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge/core",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "description": "Core abstractions for AgentForge - production-ready deep agents framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",