@agentforge/patterns 0.16.30 → 0.16.32

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
@@ -411,9 +411,9 @@ function stringifyActionArguments(arguments_) {
411
411
  function getLatestThought(thoughts) {
412
412
  return thoughts[thoughts.length - 1]?.content ?? "";
413
413
  }
414
- function debugIfVerbose(logger4, verbose, message, data) {
414
+ function debugIfVerbose(logger5, verbose, message, data) {
415
415
  if (verbose) {
416
- logger4.debug(message, data);
416
+ logger5.debug(message, data);
417
417
  }
418
418
  }
419
419
 
@@ -2393,6 +2393,82 @@ var MultiAgentState = (0, import_core7.createStateAnnotation)(MultiAgentStateCon
2393
2393
 
2394
2394
  // src/multi-agent/routing.ts
2395
2395
  var import_messages5 = require("@langchain/core/messages");
2396
+ var logger = createPatternLogger("agentforge:patterns:multi-agent:routing");
2397
+ function hasStructuredOutput(model) {
2398
+ return typeof model.withStructuredOutput === "function";
2399
+ }
2400
+ function isRecord(value) {
2401
+ return typeof value === "object" && value !== null;
2402
+ }
2403
+ function isContentCarrier(value) {
2404
+ return isRecord(value) && "content" in value;
2405
+ }
2406
+ function serializeRoutingContent(content) {
2407
+ if (typeof content === "string") {
2408
+ return content;
2409
+ }
2410
+ if (Array.isArray(content)) {
2411
+ const textParts = content.flatMap((part) => {
2412
+ if (typeof part === "string") {
2413
+ return [part];
2414
+ }
2415
+ if (isRecord(part) && typeof part.text === "string") {
2416
+ return [part.text];
2417
+ }
2418
+ return [];
2419
+ });
2420
+ if (textParts.length > 0) {
2421
+ return textParts.join("\n");
2422
+ }
2423
+ return JSON.stringify(content);
2424
+ }
2425
+ return JSON.stringify(content);
2426
+ }
2427
+ function normalizeRoutingDecisionInput(decision) {
2428
+ if (isContentCarrier(decision)) {
2429
+ return JSON.parse(serializeRoutingContent(decision.content));
2430
+ }
2431
+ return decision;
2432
+ }
2433
+ function parseRoutingDecision(decision) {
2434
+ try {
2435
+ return RoutingDecisionSchema.parse(normalizeRoutingDecisionInput(decision));
2436
+ } catch (error) {
2437
+ const message = error instanceof Error ? error.message : String(error);
2438
+ throw new Error(`Invalid LLM routing decision: ${message}`);
2439
+ }
2440
+ }
2441
+ function finalizeLlmRoutingDecision(decision) {
2442
+ const parsed = parseRoutingDecision(decision);
2443
+ return {
2444
+ targetAgent: parsed.targetAgent,
2445
+ targetAgents: parsed.targetAgents,
2446
+ reasoning: parsed.reasoning,
2447
+ confidence: parsed.confidence,
2448
+ strategy: "llm-based",
2449
+ timestamp: Date.now()
2450
+ };
2451
+ }
2452
+ async function invokeRoutingDecision(model, messages) {
2453
+ if (hasStructuredOutput(model)) {
2454
+ let structuredModel;
2455
+ try {
2456
+ structuredModel = model.withStructuredOutput(RoutingDecisionSchema);
2457
+ } catch (error) {
2458
+ logger.warn("Structured output unavailable, using direct routing fallback", {
2459
+ strategy: "llm-based",
2460
+ fallback: "direct-model-invoke",
2461
+ error: error instanceof Error ? error.message : String(error)
2462
+ });
2463
+ const decision3 = await model.invoke(messages);
2464
+ return finalizeLlmRoutingDecision(decision3);
2465
+ }
2466
+ const decision2 = await structuredModel.invoke(messages);
2467
+ return finalizeLlmRoutingDecision(decision2);
2468
+ }
2469
+ const decision = await model.invoke(messages);
2470
+ return finalizeLlmRoutingDecision(decision);
2471
+ }
2396
2472
  var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
2397
2473
 
2398
2474
  Your job is to:
@@ -2450,20 +2526,12 @@ Select the best worker(s) for this task and explain your reasoning.`;
2450
2526
  new import_messages5.SystemMessage(systemPrompt),
2451
2527
  new import_messages5.HumanMessage(userPrompt)
2452
2528
  ];
2453
- const decision = await config.model.invoke(messages);
2454
- return {
2455
- targetAgent: decision.targetAgent,
2456
- targetAgents: decision.targetAgents,
2457
- reasoning: decision.reasoning,
2458
- confidence: decision.confidence,
2459
- strategy: "llm-based",
2460
- timestamp: Date.now()
2461
- };
2529
+ return await invokeRoutingDecision(config.model, messages);
2462
2530
  }
2463
2531
  };
2464
2532
  var roundRobinRouting = {
2465
2533
  name: "round-robin",
2466
- async route(state, config) {
2534
+ async route(state, _config) {
2467
2535
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
2468
2536
  if (availableWorkers.length === 0) {
2469
2537
  throw new Error("No available workers for round-robin routing");
@@ -2482,7 +2550,7 @@ var roundRobinRouting = {
2482
2550
  };
2483
2551
  var skillBasedRouting = {
2484
2552
  name: "skill-based",
2485
- async route(state, config) {
2553
+ async route(state, _config) {
2486
2554
  const lastMessage = state.messages[state.messages.length - 1];
2487
2555
  const taskContent = (lastMessage?.content || state.input).toLowerCase();
2488
2556
  const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
@@ -2523,7 +2591,7 @@ var skillBasedRouting = {
2523
2591
  };
2524
2592
  var loadBalancedRouting = {
2525
2593
  name: "load-balanced",
2526
- async route(state, config) {
2594
+ async route(state, _config) {
2527
2595
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
2528
2596
  if (availableWorkers.length === 0) {
2529
2597
  throw new Error("No available workers for load-balanced routing");
@@ -2568,22 +2636,22 @@ function getRoutingStrategy(name) {
2568
2636
  }
2569
2637
 
2570
2638
  // src/multi-agent/utils.ts
2571
- var logger = createPatternLogger("agentforge:patterns:multi-agent:utils");
2572
- function isRecord(value) {
2639
+ var logger2 = createPatternLogger("agentforge:patterns:multi-agent:utils");
2640
+ function isRecord2(value) {
2573
2641
  return typeof value === "object" && value !== null && !Array.isArray(value);
2574
2642
  }
2575
2643
  function toRunnableConfig(config) {
2576
- if (!isRecord(config)) {
2644
+ if (!isRecord2(config)) {
2577
2645
  return void 0;
2578
2646
  }
2579
2647
  return config;
2580
2648
  }
2581
2649
  function getReActResultShape(value) {
2582
- if (!isRecord(value)) {
2650
+ if (!isRecord2(value)) {
2583
2651
  return {};
2584
2652
  }
2585
- const messages = Array.isArray(value.messages) ? value.messages.filter((message) => isRecord(message)) : void 0;
2586
- const actions = Array.isArray(value.actions) ? value.actions.filter((action) => isRecord(action)) : void 0;
2653
+ const messages = Array.isArray(value.messages) ? value.messages.filter((message) => isRecord2(message)) : void 0;
2654
+ const actions = Array.isArray(value.actions) ? value.actions.filter((action) => isRecord2(action)) : void 0;
2587
2655
  return {
2588
2656
  messages,
2589
2657
  actions,
@@ -2602,7 +2670,7 @@ function safeSerializeContent(content) {
2602
2670
  if (typeof part === "string") {
2603
2671
  return part;
2604
2672
  }
2605
- if (isRecord(part) && typeof part.text === "string" && part.text.length > 0) {
2673
+ if (isRecord2(part) && typeof part.text === "string" && part.text.length > 0) {
2606
2674
  return part.text;
2607
2675
  }
2608
2676
  try {
@@ -2647,17 +2715,17 @@ function isReActAgent(obj) {
2647
2715
  function wrapReActAgent(workerId, agent, verbose = false) {
2648
2716
  return async (state, config) => {
2649
2717
  try {
2650
- logger.debug("Wrapping ReAct agent execution", { workerId });
2718
+ logger2.debug("Wrapping ReAct agent execution", { workerId });
2651
2719
  const runnableConfig = toRunnableConfig(config);
2652
2720
  const currentAssignment = state.activeAssignments.find(
2653
2721
  (assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2654
2722
  );
2655
2723
  if (!currentAssignment) {
2656
- logger.debug("No active assignment found", { workerId });
2724
+ logger2.debug("No active assignment found", { workerId });
2657
2725
  return {};
2658
2726
  }
2659
2727
  const task = currentAssignment.task;
2660
- logger.debug("Extracted task from assignment", {
2728
+ logger2.debug("Extracted task from assignment", {
2661
2729
  workerId,
2662
2730
  assignmentId: currentAssignment.id,
2663
2731
  taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
@@ -2670,7 +2738,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2670
2738
  thread_id: workerThreadId
2671
2739
  }
2672
2740
  } : runnableConfig;
2673
- logger.debug("Invoking ReAct agent with worker-specific config", {
2741
+ logger2.debug("Invoking ReAct agent with worker-specific config", {
2674
2742
  workerId,
2675
2743
  ...runnableConfig?.configurable?.thread_id !== void 0 ? { parentThreadId: String(runnableConfig.configurable.thread_id) } : {},
2676
2744
  ...workerThreadId ? { workerThreadId } : {},
@@ -2685,13 +2753,13 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2685
2753
  );
2686
2754
  const resultShape = getReActResultShape(result);
2687
2755
  const response = extractResponse(resultShape);
2688
- logger.debug("Received response from ReAct agent", {
2756
+ logger2.debug("Received response from ReAct agent", {
2689
2757
  workerId,
2690
2758
  responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
2691
2759
  });
2692
2760
  const uniqueTools = extractToolsUsed(resultShape);
2693
2761
  if (uniqueTools.length > 0) {
2694
- logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2762
+ logger2.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2695
2763
  }
2696
2764
  const taskResult = {
2697
2765
  assignmentId: currentAssignment.id,
@@ -2710,7 +2778,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2710
2778
  };
2711
2779
  } catch (error) {
2712
2780
  const errorMessage = handleNodeError(error, `react-agent:${workerId}`, verbose);
2713
- logger.error("Error in ReAct agent execution", {
2781
+ logger2.error("Error in ReAct agent execution", {
2714
2782
  workerId,
2715
2783
  error: errorMessage
2716
2784
  });
@@ -2743,7 +2811,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2743
2811
  // src/multi-agent/nodes/shared.ts
2744
2812
  var import_messages6 = require("@langchain/core/messages");
2745
2813
  var import_core8 = require("@agentforge/core");
2746
- var logger2 = createPatternLogger("agentforge:patterns:multi-agent:nodes");
2814
+ var logger3 = createPatternLogger("agentforge:patterns:multi-agent:nodes");
2747
2815
  function createGeneratedId(prefix) {
2748
2816
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
2749
2817
  }
@@ -2795,7 +2863,7 @@ function serializeModelContent(content) {
2795
2863
  const error = new Error(
2796
2864
  "Failed to serialize model content: JSON.stringify returned undefined"
2797
2865
  );
2798
- logger2.error("Model content serialization failed", {
2866
+ logger3.error("Model content serialization failed", {
2799
2867
  errorMessage: error.message,
2800
2868
  contentType: content === null ? "null" : typeof content
2801
2869
  });
@@ -2804,7 +2872,7 @@ function serializeModelContent(content) {
2804
2872
  return serialized;
2805
2873
  } catch (error) {
2806
2874
  const normalizedError = error instanceof Error ? error : new Error("Unknown error during model content serialization");
2807
- logger2.error("Model content serialization threw an error", {
2875
+ logger3.error("Model content serialization threw an error", {
2808
2876
  errorMessage: normalizedError.message,
2809
2877
  contentType: content === null ? "null" : typeof content
2810
2878
  });
@@ -2847,16 +2915,16 @@ function createAggregatorNode(config = {}) {
2847
2915
  } = config;
2848
2916
  return async (state) => {
2849
2917
  try {
2850
- logger2.info("Aggregator node executing", {
2918
+ logger3.info("Aggregator node executing", {
2851
2919
  completedTasks: state.completedTasks.length,
2852
2920
  successfulTasks: state.completedTasks.filter((task) => task.success).length,
2853
2921
  failedTasks: state.completedTasks.filter((task) => !task.success).length
2854
2922
  });
2855
- logger2.debug("Combining results from workers");
2923
+ logger3.debug("Combining results from workers");
2856
2924
  if (aggregateFn) {
2857
- logger2.debug("Using custom aggregation function");
2925
+ logger3.debug("Using custom aggregation function");
2858
2926
  const response2 = await aggregateFn(state);
2859
- logger2.info("Custom aggregation complete", {
2927
+ logger3.info("Custom aggregation complete", {
2860
2928
  responseLength: response2.length
2861
2929
  });
2862
2930
  return {
@@ -2865,16 +2933,16 @@ function createAggregatorNode(config = {}) {
2865
2933
  };
2866
2934
  }
2867
2935
  if (state.completedTasks.length === 0) {
2868
- logger2.warn("No completed tasks to aggregate");
2936
+ logger3.warn("No completed tasks to aggregate");
2869
2937
  return {
2870
2938
  response: "No tasks were completed.",
2871
2939
  status: "completed"
2872
2940
  };
2873
2941
  }
2874
2942
  if (!model) {
2875
- logger2.debug("No model provided, concatenating results");
2943
+ logger3.debug("No model provided, concatenating results");
2876
2944
  const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
2877
- logger2.info("Simple concatenation complete", {
2945
+ logger3.info("Simple concatenation complete", {
2878
2946
  resultLength: combinedResults.length
2879
2947
  });
2880
2948
  return {
@@ -2882,27 +2950,27 @@ function createAggregatorNode(config = {}) {
2882
2950
  status: "completed"
2883
2951
  };
2884
2952
  }
2885
- logger2.debug("Using LLM for intelligent aggregation", {
2953
+ logger3.debug("Using LLM for intelligent aggregation", {
2886
2954
  taskCount: state.completedTasks.length
2887
2955
  });
2888
2956
  const messages = createPromptMessages(systemPrompt, createAggregationPrompt(state));
2889
- logger2.debug("Invoking aggregation LLM");
2957
+ logger3.debug("Invoking aggregation LLM");
2890
2958
  const response = await model.invoke(messages);
2891
2959
  const aggregatedResponse = serializeModelContent(response.content);
2892
- logger2.info("Aggregation complete", {
2960
+ logger3.info("Aggregation complete", {
2893
2961
  responseLength: aggregatedResponse.length
2894
2962
  });
2895
- logger2.debug("Aggregation response details", {
2963
+ logger3.debug("Aggregation response details", {
2896
2964
  responseLength: aggregatedResponse.length
2897
2965
  });
2898
- logger2.debug("Aggregation complete");
2966
+ logger3.debug("Aggregation complete");
2899
2967
  return {
2900
2968
  response: aggregatedResponse,
2901
2969
  status: "completed"
2902
2970
  };
2903
2971
  } catch (error) {
2904
2972
  const errorMessage = handleNodeError(error, "aggregator", false);
2905
- logger2.error("Aggregator node error", {
2973
+ logger3.error("Aggregator node error", {
2906
2974
  error: errorMessage,
2907
2975
  ...error instanceof Error && error.stack ? { stack: error.stack } : {},
2908
2976
  completedTasks: state.completedTasks.length
@@ -2926,7 +2994,7 @@ function incrementAssignedWorkerLoads(state, assignments) {
2926
2994
  for (const assignment of assignments) {
2927
2995
  const worker = updatedWorkers[assignment.workerId];
2928
2996
  if (!worker) {
2929
- logger2.error("Worker not found in state", {
2997
+ logger3.error("Worker not found in state", {
2930
2998
  workerId: assignment.workerId,
2931
2999
  availableWorkers: Object.keys(updatedWorkers)
2932
3000
  });
@@ -2945,45 +3013,45 @@ function createSupervisorNode(config) {
2945
3013
  const { strategy, maxIterations = 10 } = config;
2946
3014
  return async (state) => {
2947
3015
  try {
2948
- logger2.info("Supervisor node executing", {
3016
+ logger3.info("Supervisor node executing", {
2949
3017
  iteration: state.iteration,
2950
3018
  maxIterations,
2951
3019
  activeAssignments: state.activeAssignments.length,
2952
3020
  completedTasks: state.completedTasks.length
2953
3021
  });
2954
- logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
3022
+ logger3.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2955
3023
  if (state.iteration >= maxIterations) {
2956
- logger2.warn("Max iterations reached", {
3024
+ logger3.warn("Max iterations reached", {
2957
3025
  iteration: state.iteration,
2958
3026
  maxIterations
2959
3027
  });
2960
- logger2.debug("Max iterations reached, moving to aggregation");
3028
+ logger3.debug("Max iterations reached, moving to aggregation");
2961
3029
  return {
2962
3030
  status: "aggregating",
2963
3031
  currentAgent: "aggregator"
2964
3032
  };
2965
3033
  }
2966
3034
  const allCompleted = allAssignmentsCompleted(state);
2967
- logger2.debug("Checking task completion", {
3035
+ logger3.debug("Checking task completion", {
2968
3036
  activeAssignments: state.activeAssignments.length,
2969
3037
  completedTasks: state.completedTasks.length,
2970
3038
  allCompleted
2971
3039
  });
2972
3040
  if (allCompleted && state.activeAssignments.length > 0) {
2973
- logger2.info("All tasks completed, moving to aggregation", {
3041
+ logger3.info("All tasks completed, moving to aggregation", {
2974
3042
  completedCount: state.completedTasks.length
2975
3043
  });
2976
- logger2.debug("All tasks completed, moving to aggregation");
3044
+ logger3.debug("All tasks completed, moving to aggregation");
2977
3045
  return {
2978
3046
  status: "aggregating",
2979
3047
  currentAgent: "aggregator"
2980
3048
  };
2981
3049
  }
2982
- logger2.debug("Getting routing strategy", { strategy });
3050
+ logger3.debug("Getting routing strategy", { strategy });
2983
3051
  const routingImpl = getRoutingStrategy(strategy);
2984
3052
  const decision = await routingImpl.route(state, config);
2985
3053
  const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
2986
- logger2.debug("Target agents determined", {
3054
+ logger3.debug("Target agents determined", {
2987
3055
  targetAgents,
2988
3056
  isParallel: targetAgents.length > 1,
2989
3057
  decision: {
@@ -2992,30 +3060,30 @@ function createSupervisorNode(config) {
2992
3060
  }
2993
3061
  });
2994
3062
  if (targetAgents.length === 0) {
2995
- logger2.error("No target agents specified in routing decision");
3063
+ logger3.error("No target agents specified in routing decision");
2996
3064
  throw new Error("Routing decision must specify at least one target agent");
2997
3065
  }
2998
3066
  if (targetAgents.length === 1) {
2999
- logger2.info("Routing to single agent", {
3067
+ logger3.info("Routing to single agent", {
3000
3068
  targetAgent: targetAgents[0],
3001
3069
  reasoning: decision.reasoning,
3002
3070
  confidence: decision.confidence
3003
3071
  });
3004
- logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
3072
+ logger3.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
3005
3073
  } else {
3006
- logger2.info("Routing to multiple agents in parallel", {
3074
+ logger3.info("Routing to multiple agents in parallel", {
3007
3075
  targetAgents,
3008
3076
  count: targetAgents.length,
3009
3077
  reasoning: decision.reasoning,
3010
3078
  confidence: decision.confidence
3011
3079
  });
3012
- logger2.debug(
3080
+ logger3.debug(
3013
3081
  `Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`
3014
3082
  );
3015
3083
  }
3016
3084
  const task = getLatestTaskContent(state);
3017
3085
  const assignments = createTaskAssignments(targetAgents, task);
3018
- logger2.debug("Created task assignments", {
3086
+ logger3.debug("Created task assignments", {
3019
3087
  assignmentCount: assignments.length,
3020
3088
  assignments: assignments.map((assignment) => ({
3021
3089
  id: assignment.id,
@@ -3025,7 +3093,7 @@ function createSupervisorNode(config) {
3025
3093
  });
3026
3094
  const messages = createAssignmentMessages(assignments);
3027
3095
  const updatedWorkers = incrementAssignedWorkerLoads(state, assignments);
3028
- logger2.info("Supervisor routing complete", {
3096
+ logger3.info("Supervisor routing complete", {
3029
3097
  currentAgent: targetAgents.join(","),
3030
3098
  status: "executing",
3031
3099
  assignmentCount: assignments.length,
@@ -3043,7 +3111,7 @@ function createSupervisorNode(config) {
3043
3111
  };
3044
3112
  } catch (error) {
3045
3113
  const errorMessage = handleNodeError(error, "supervisor", false);
3046
- logger2.error("Supervisor node error", {
3114
+ logger3.error("Supervisor node error", {
3047
3115
  error: errorMessage,
3048
3116
  ...error instanceof Error && error.stack ? { stack: error.stack } : {},
3049
3117
  iteration: state.iteration
@@ -3071,7 +3139,7 @@ async function invokeWorkerModel(model, config, assignment) {
3071
3139
  );
3072
3140
  let modelToUse = model;
3073
3141
  if (config.tools && config.tools.length > 0 && model.bindTools) {
3074
- logger2.debug("Binding tools to model", {
3142
+ logger3.debug("Binding tools to model", {
3075
3143
  workerId: config.id,
3076
3144
  toolCount: config.tools.length,
3077
3145
  toolNames: config.tools.map((tool) => tool.metadata.name)
@@ -3080,15 +3148,15 @@ async function invokeWorkerModel(model, config, assignment) {
3080
3148
  convertWorkerToolsForLangChain(config.tools)
3081
3149
  );
3082
3150
  }
3083
- logger2.debug("Invoking LLM", { workerId: config.id });
3151
+ logger3.debug("Invoking LLM", { workerId: config.id });
3084
3152
  const response = await modelToUse.invoke(messages);
3085
3153
  const result = serializeModelContent(response.content);
3086
- logger2.info("Worker task completed", {
3154
+ logger3.info("Worker task completed", {
3087
3155
  workerId: config.id,
3088
3156
  assignmentId: assignment.id,
3089
3157
  resultLength: result.length
3090
3158
  });
3091
- logger2.debug("Worker result details", {
3159
+ logger3.debug("Worker result details", {
3092
3160
  workerId: config.id,
3093
3161
  assignmentId: assignment.id,
3094
3162
  resultLength: result.length
@@ -3123,7 +3191,7 @@ async function invokeWorkerModel(model, config, assignment) {
3123
3191
  function getStateWorkerOrThrow(state, workerId) {
3124
3192
  const currentWorker = state.workers[workerId];
3125
3193
  if (!currentWorker) {
3126
- logger2.error("Attempted to decrement workload for unknown worker", {
3194
+ logger3.error("Attempted to decrement workload for unknown worker", {
3127
3195
  workerId,
3128
3196
  availableWorkers: Object.keys(state.workers)
3129
3197
  });
@@ -3139,7 +3207,7 @@ function resolvePreviousWorkload(workerId, currentWorker, workerFromExecution) {
3139
3207
  if (typeof currentWorker.currentWorkload === "number" && Number.isFinite(currentWorker.currentWorkload)) {
3140
3208
  return currentWorker.currentWorkload;
3141
3209
  }
3142
- logger2.error("Worker workload is not a valid number; cannot decrement", {
3210
+ logger3.error("Worker workload is not a valid number; cannot decrement", {
3143
3211
  workerId,
3144
3212
  workloadFromState: currentWorker.currentWorkload,
3145
3213
  ...typeof workloadFromWorker === "number" ? { workloadFromWorker } : {}
@@ -3174,7 +3242,7 @@ function mergeWorkersWithDecrement(state, workerId, executionResult) {
3174
3242
  ...baseWorkers,
3175
3243
  [workerId]: updatedWorker
3176
3244
  };
3177
- logger2.debug("Worker workload decremented", {
3245
+ logger3.debug("Worker workload decremented", {
3178
3246
  workerId,
3179
3247
  previousWorkload,
3180
3248
  newWorkload: updatedWorkers[workerId].currentWorkload,
@@ -3192,7 +3260,7 @@ function decrementWorkerOnError(state, workerId) {
3192
3260
  currentWorkload: Math.max(0, previousWorkload - 1)
3193
3261
  }
3194
3262
  };
3195
- logger2.debug("Worker workload decremented (error path)", {
3263
+ logger3.debug("Worker workload decremented (error path)", {
3196
3264
  workerId,
3197
3265
  previousWorkload,
3198
3266
  newWorkload: updatedWorkers[workerId].currentWorkload
@@ -3200,7 +3268,7 @@ function decrementWorkerOnError(state, workerId) {
3200
3268
  return updatedWorkers;
3201
3269
  }
3202
3270
  function createErrorTaskResult(assignment, workerId, errorMessage) {
3203
- logger2.warn("Creating error result for assignment", {
3271
+ logger3.warn("Creating error result for assignment", {
3204
3272
  workerId,
3205
3273
  assignmentId: assignment.id
3206
3274
  });
@@ -3217,47 +3285,47 @@ function createWorkerNode(config) {
3217
3285
  const { id, model, executeFn, agent } = config;
3218
3286
  return async (state, runConfig) => {
3219
3287
  try {
3220
- logger2.info("Worker node executing", {
3288
+ logger3.info("Worker node executing", {
3221
3289
  workerId: id,
3222
3290
  iteration: state.iteration,
3223
3291
  activeAssignments: state.activeAssignments.length
3224
3292
  });
3225
3293
  const currentAssignment = findCurrentAssignment(state, id);
3226
3294
  if (!currentAssignment) {
3227
- logger2.debug("No active assignment found for worker", {
3295
+ logger3.debug("No active assignment found for worker", {
3228
3296
  workerId: id,
3229
3297
  totalActiveAssignments: state.activeAssignments.length,
3230
3298
  completedTasks: state.completedTasks.length
3231
3299
  });
3232
3300
  return {};
3233
3301
  }
3234
- logger2.info("Worker processing assignment", {
3302
+ logger3.info("Worker processing assignment", {
3235
3303
  workerId: id,
3236
3304
  assignmentId: currentAssignment.id,
3237
3305
  taskLength: currentAssignment.task.length
3238
3306
  });
3239
- logger2.debug("Worker assignment details", {
3307
+ logger3.debug("Worker assignment details", {
3240
3308
  workerId: id,
3241
3309
  assignmentId: currentAssignment.id,
3242
3310
  taskLength: currentAssignment.task.length
3243
3311
  });
3244
3312
  let executionResult;
3245
3313
  if (executeFn) {
3246
- logger2.debug("Using custom execution function", { workerId: id });
3314
+ logger3.debug("Using custom execution function", { workerId: id });
3247
3315
  executionResult = await executeFn(state, runConfig);
3248
3316
  } else if (agent && isReActAgent(agent)) {
3249
- logger2.debug("Using ReAct agent", { workerId: id });
3317
+ logger3.debug("Using ReAct agent", { workerId: id });
3250
3318
  const wrappedFn = wrapReActAgent(id, agent, config.verbose ?? false);
3251
3319
  executionResult = await wrappedFn(state, runConfig);
3252
3320
  } else if (model) {
3253
- logger2.debug("Using default LLM execution", {
3321
+ logger3.debug("Using default LLM execution", {
3254
3322
  workerId: id,
3255
3323
  hasTools: (config.tools ?? []).length > 0,
3256
3324
  toolCount: (config.tools ?? []).length
3257
3325
  });
3258
3326
  executionResult = await invokeWorkerModel(model, config, currentAssignment);
3259
3327
  } else {
3260
- logger2.error("Worker missing required configuration", { workerId: id });
3328
+ logger3.error("Worker missing required configuration", { workerId: id });
3261
3329
  throw new Error(
3262
3330
  `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
3263
3331
  );
@@ -3269,7 +3337,7 @@ function createWorkerNode(config) {
3269
3337
  };
3270
3338
  } catch (error) {
3271
3339
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
3272
- logger2.error("Worker node error", {
3340
+ logger3.error("Worker node error", {
3273
3341
  workerId: id,
3274
3342
  error: errorMessage
3275
3343
  });
@@ -3278,7 +3346,7 @@ function createWorkerNode(config) {
3278
3346
  updatedWorkers = decrementWorkerOnError(state, id);
3279
3347
  } catch (workloadError) {
3280
3348
  const workloadErrorMessage = workloadError instanceof Error ? workloadError.message : String(workloadError);
3281
- logger2.error("Worker error handling failed", {
3349
+ logger3.error("Worker error handling failed", {
3282
3350
  workerId: id,
3283
3351
  error: workloadErrorMessage
3284
3352
  });
@@ -3298,7 +3366,7 @@ function createWorkerNode(config) {
3298
3366
  workers: updatedWorkers
3299
3367
  };
3300
3368
  }
3301
- logger2.error("No assignment found for error handling", { workerId: id });
3369
+ logger3.error("No assignment found for error handling", { workerId: id });
3302
3370
  return {
3303
3371
  status: "failed",
3304
3372
  error: errorMessage,
@@ -3310,7 +3378,7 @@ function createWorkerNode(config) {
3310
3378
 
3311
3379
  // src/multi-agent/agent.ts
3312
3380
  var import_langgraph4 = require("@langchain/langgraph");
3313
- var logger3 = createPatternLogger("agentforge:patterns:multi-agent:system");
3381
+ var logger4 = createPatternLogger("agentforge:patterns:multi-agent:system");
3314
3382
  function getToolName(tool) {
3315
3383
  if (!tool || typeof tool !== "object") {
3316
3384
  return "unknown";
@@ -3335,13 +3403,6 @@ function createMultiAgentSystem(config) {
3335
3403
  } = config;
3336
3404
  const workflow = new import_langgraph4.StateGraph(MultiAgentState);
3337
3405
  const supervisorConfig = { ...supervisor, maxIterations, verbose };
3338
- if (supervisor.model) {
3339
- let configuredModel = supervisor.model;
3340
- if (supervisor.strategy === "llm-based") {
3341
- configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
3342
- }
3343
- supervisorConfig.model = configuredModel;
3344
- }
3345
3406
  const supervisorNode = createSupervisorNode(supervisorConfig);
3346
3407
  workflow.addNode("supervisor", supervisorNode);
3347
3408
  const workerIds = [];
@@ -3361,46 +3422,46 @@ function createMultiAgentSystem(config) {
3361
3422
  });
3362
3423
  workflow.addNode("aggregator", aggregatorNode);
3363
3424
  const supervisorRouter = (state) => {
3364
- logger3.debug("Supervisor router executing", {
3425
+ logger4.debug("Supervisor router executing", {
3365
3426
  status: state.status,
3366
3427
  ...state.currentAgent ? { currentAgent: state.currentAgent } : {},
3367
3428
  iteration: state.iteration
3368
3429
  });
3369
3430
  if (state.status === "completed" || state.status === "failed") {
3370
- logger3.info("Supervisor router: ending workflow", { status: state.status });
3431
+ logger4.info("Supervisor router: ending workflow", { status: state.status });
3371
3432
  return import_langgraph4.END;
3372
3433
  }
3373
3434
  if (state.status === "aggregating") {
3374
- logger3.info("Supervisor router: routing to aggregator");
3435
+ logger4.info("Supervisor router: routing to aggregator");
3375
3436
  return "aggregator";
3376
3437
  }
3377
3438
  if (state.currentAgent && state.currentAgent !== "supervisor") {
3378
3439
  if (state.currentAgent.includes(",")) {
3379
3440
  const agents = state.currentAgent.split(",").map((a) => a.trim());
3380
- logger3.info("Supervisor router: parallel routing", {
3441
+ logger4.info("Supervisor router: parallel routing", {
3381
3442
  agents,
3382
3443
  count: agents.length
3383
3444
  });
3384
3445
  return agents;
3385
3446
  }
3386
- logger3.info("Supervisor router: single agent routing", {
3447
+ logger4.info("Supervisor router: single agent routing", {
3387
3448
  targetAgent: state.currentAgent
3388
3449
  });
3389
3450
  return state.currentAgent;
3390
3451
  }
3391
- logger3.debug("Supervisor router: staying at supervisor");
3452
+ logger4.debug("Supervisor router: staying at supervisor");
3392
3453
  return "supervisor";
3393
3454
  };
3394
3455
  const workerRouter = (state) => {
3395
- logger3.debug("Worker router executing", {
3456
+ logger4.debug("Worker router executing", {
3396
3457
  iteration: state.iteration,
3397
3458
  completedTasks: state.completedTasks.length
3398
3459
  });
3399
- logger3.debug("Worker router: returning to supervisor");
3460
+ logger4.debug("Worker router: returning to supervisor");
3400
3461
  return "supervisor";
3401
3462
  };
3402
3463
  const aggregatorRouter = (state) => {
3403
- logger3.info("Aggregator router: ending workflow", {
3464
+ logger4.info("Aggregator router: ending workflow", {
3404
3465
  completedTasks: state.completedTasks.length,
3405
3466
  status: state.status
3406
3467
  });