@agentforge/patterns 0.11.2 → 0.11.3

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
@@ -2611,12 +2611,19 @@ function createSupervisorNode(config) {
2611
2611
  const updatedWorkers = { ...state.workers };
2612
2612
  for (const assignment of assignments) {
2613
2613
  const worker = updatedWorkers[assignment.workerId];
2614
- if (worker) {
2615
- updatedWorkers[assignment.workerId] = {
2616
- ...worker,
2617
- currentWorkload: worker.currentWorkload + 1
2618
- };
2614
+ if (!worker) {
2615
+ logger2.error("Worker not found in state", {
2616
+ workerId: assignment.workerId,
2617
+ availableWorkers: Object.keys(updatedWorkers)
2618
+ });
2619
+ throw new Error(
2620
+ `Worker ${assignment.workerId} not found in state.workers. Available workers: ${Object.keys(updatedWorkers).join(", ")}`
2621
+ );
2619
2622
  }
2623
+ updatedWorkers[assignment.workerId] = {
2624
+ ...worker,
2625
+ currentWorkload: worker.currentWorkload + 1
2626
+ };
2620
2627
  }
2621
2628
  logger2.info("Supervisor routing complete", {
2622
2629
  currentAgent: targetAgents.join(","),
@@ -2686,39 +2693,6 @@ function createWorkerNode(config) {
2686
2693
  taskLength: currentAssignment.task.length,
2687
2694
  taskPreview: currentAssignment.task.substring(0, 100)
2688
2695
  });
2689
- let executionResult;
2690
- if (executeFn) {
2691
- logger2.debug("Using custom execution function", { workerId: id });
2692
- executionResult = await executeFn(state, runConfig);
2693
- } else if (agent && isReActAgent(agent)) {
2694
- logger2.debug("Using ReAct agent", { workerId: id });
2695
- const wrappedFn = wrapReActAgent(id, agent, verbose);
2696
- executionResult = await wrappedFn(state, runConfig);
2697
- } else if (model) {
2698
- executionResult = await executeWithLLM();
2699
- } else {
2700
- logger2.error("Worker missing required configuration", { workerId: id });
2701
- throw new Error(
2702
- `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2703
- );
2704
- }
2705
- const currentWorker = state.workers[id];
2706
- const updatedWorkers = {
2707
- ...state.workers,
2708
- [id]: {
2709
- ...currentWorker,
2710
- currentWorkload: Math.max(0, currentWorker.currentWorkload - 1)
2711
- }
2712
- };
2713
- logger2.debug("Worker state update", {
2714
- workerId: id,
2715
- previousWorkload: currentWorker.currentWorkload,
2716
- newWorkload: updatedWorkers[id].currentWorkload
2717
- });
2718
- return {
2719
- ...executionResult,
2720
- workers: updatedWorkers
2721
- };
2722
2696
  async function executeWithLLM() {
2723
2697
  logger2.debug("Using default LLM execution", {
2724
2698
  workerId: id,
@@ -2780,12 +2754,64 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2780
2754
  messages: [message]
2781
2755
  };
2782
2756
  }
2757
+ let executionResult;
2758
+ if (executeFn) {
2759
+ logger2.debug("Using custom execution function", { workerId: id });
2760
+ executionResult = await executeFn(state, runConfig);
2761
+ } else if (agent && isReActAgent(agent)) {
2762
+ logger2.debug("Using ReAct agent", { workerId: id });
2763
+ const wrappedFn = wrapReActAgent(id, agent, verbose);
2764
+ executionResult = await wrappedFn(state, runConfig);
2765
+ } else if (model) {
2766
+ executionResult = await executeWithLLM();
2767
+ } else {
2768
+ logger2.error("Worker missing required configuration", { workerId: id });
2769
+ throw new Error(
2770
+ `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2771
+ );
2772
+ }
2773
+ const currentWorker = state.workers[id];
2774
+ const baseWorkers = {
2775
+ ...state.workers,
2776
+ ...executionResult.workers || {}
2777
+ };
2778
+ const workerToUpdate = baseWorkers[id] || currentWorker;
2779
+ const updatedWorkers = {
2780
+ ...baseWorkers,
2781
+ [id]: {
2782
+ ...workerToUpdate,
2783
+ currentWorkload: Math.max(0, workerToUpdate.currentWorkload - 1)
2784
+ }
2785
+ };
2786
+ logger2.debug("Worker workload decremented", {
2787
+ workerId: id,
2788
+ previousWorkload: workerToUpdate.currentWorkload,
2789
+ newWorkload: updatedWorkers[id].currentWorkload,
2790
+ hadExecutionResultWorkers: !!executionResult.workers
2791
+ });
2792
+ return {
2793
+ ...executionResult,
2794
+ workers: updatedWorkers
2795
+ };
2783
2796
  } catch (error) {
2784
2797
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
2785
2798
  logger2.error("Worker node error", {
2786
2799
  workerId: id,
2787
2800
  error: errorMessage
2788
2801
  });
2802
+ const currentWorker = state.workers[id];
2803
+ const updatedWorkers = {
2804
+ ...state.workers,
2805
+ [id]: {
2806
+ ...currentWorker,
2807
+ currentWorkload: Math.max(0, currentWorker.currentWorkload - 1)
2808
+ }
2809
+ };
2810
+ logger2.debug("Worker workload decremented (error path)", {
2811
+ workerId: id,
2812
+ previousWorkload: currentWorker.currentWorkload,
2813
+ newWorkload: updatedWorkers[id].currentWorkload
2814
+ });
2789
2815
  const currentAssignment = state.activeAssignments.find(
2790
2816
  (assignment) => assignment.workerId === id
2791
2817
  );
@@ -2805,13 +2831,17 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2805
2831
  return {
2806
2832
  completedTasks: [errorResult],
2807
2833
  currentAgent: "supervisor",
2808
- status: "routing"
2834
+ status: "routing",
2835
+ workers: updatedWorkers
2836
+ // Include workload update
2809
2837
  };
2810
2838
  }
2811
2839
  logger2.error("No assignment found for error handling", { workerId: id });
2812
2840
  return {
2813
2841
  status: "failed",
2814
- error: errorMessage
2842
+ error: errorMessage,
2843
+ workers: updatedWorkers
2844
+ // Include workload update even on failure
2815
2845
  };
2816
2846
  }
2817
2847
  };
package/dist/index.d.cts CHANGED
@@ -2817,6 +2817,33 @@ declare const DEFAULT_AGGREGATOR_SYSTEM_PROMPT = "You are an aggregator agent re
2817
2817
  declare function createSupervisorNode(config: SupervisorConfig): (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
2818
2818
  /**
2819
2819
  * Create a worker agent node
2820
+ *
2821
+ * **Workload Management Contract:**
2822
+ * The framework automatically manages `currentWorkload` for all workers:
2823
+ * - Incremented by supervisor when task is assigned
2824
+ * - Decremented by worker when task completes (success or failure)
2825
+ *
2826
+ * Custom `executeFn` implementations should NOT modify `currentWorkload`.
2827
+ * The framework will automatically decrement it after execution completes.
2828
+ *
2829
+ * Custom `executeFn` CAN modify other worker properties (skills, tools,
2830
+ * availability, etc.) and these changes will be preserved and merged with
2831
+ * the workload decrement.
2832
+ *
2833
+ * @example
2834
+ * ```typescript
2835
+ * // ✅ CORRECT: Custom executeFn modifies skills, framework handles workload
2836
+ * const executeFn = async (state) => ({
2837
+ * completedTasks: [...],
2838
+ * workers: {
2839
+ * 'worker1': {
2840
+ * ...state.workers['worker1'],
2841
+ * skills: [...state.workers['worker1'].skills, 'new-skill'], // ✅ OK
2842
+ * // currentWorkload: ... // ❌ DON'T - framework manages this
2843
+ * }
2844
+ * }
2845
+ * });
2846
+ * ```
2820
2847
  */
2821
2848
  declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType, runConfig?: any) => Promise<Partial<MultiAgentStateType>>;
2822
2849
  /**
package/dist/index.d.ts CHANGED
@@ -2817,6 +2817,33 @@ declare const DEFAULT_AGGREGATOR_SYSTEM_PROMPT = "You are an aggregator agent re
2817
2817
  declare function createSupervisorNode(config: SupervisorConfig): (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
2818
2818
  /**
2819
2819
  * Create a worker agent node
2820
+ *
2821
+ * **Workload Management Contract:**
2822
+ * The framework automatically manages `currentWorkload` for all workers:
2823
+ * - Incremented by supervisor when task is assigned
2824
+ * - Decremented by worker when task completes (success or failure)
2825
+ *
2826
+ * Custom `executeFn` implementations should NOT modify `currentWorkload`.
2827
+ * The framework will automatically decrement it after execution completes.
2828
+ *
2829
+ * Custom `executeFn` CAN modify other worker properties (skills, tools,
2830
+ * availability, etc.) and these changes will be preserved and merged with
2831
+ * the workload decrement.
2832
+ *
2833
+ * @example
2834
+ * ```typescript
2835
+ * // ✅ CORRECT: Custom executeFn modifies skills, framework handles workload
2836
+ * const executeFn = async (state) => ({
2837
+ * completedTasks: [...],
2838
+ * workers: {
2839
+ * 'worker1': {
2840
+ * ...state.workers['worker1'],
2841
+ * skills: [...state.workers['worker1'].skills, 'new-skill'], // ✅ OK
2842
+ * // currentWorkload: ... // ❌ DON'T - framework manages this
2843
+ * }
2844
+ * }
2845
+ * });
2846
+ * ```
2820
2847
  */
2821
2848
  declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType, runConfig?: any) => Promise<Partial<MultiAgentStateType>>;
2822
2849
  /**
package/dist/index.js CHANGED
@@ -2508,12 +2508,19 @@ function createSupervisorNode(config) {
2508
2508
  const updatedWorkers = { ...state.workers };
2509
2509
  for (const assignment of assignments) {
2510
2510
  const worker = updatedWorkers[assignment.workerId];
2511
- if (worker) {
2512
- updatedWorkers[assignment.workerId] = {
2513
- ...worker,
2514
- currentWorkload: worker.currentWorkload + 1
2515
- };
2511
+ if (!worker) {
2512
+ logger2.error("Worker not found in state", {
2513
+ workerId: assignment.workerId,
2514
+ availableWorkers: Object.keys(updatedWorkers)
2515
+ });
2516
+ throw new Error(
2517
+ `Worker ${assignment.workerId} not found in state.workers. Available workers: ${Object.keys(updatedWorkers).join(", ")}`
2518
+ );
2516
2519
  }
2520
+ updatedWorkers[assignment.workerId] = {
2521
+ ...worker,
2522
+ currentWorkload: worker.currentWorkload + 1
2523
+ };
2517
2524
  }
2518
2525
  logger2.info("Supervisor routing complete", {
2519
2526
  currentAgent: targetAgents.join(","),
@@ -2583,39 +2590,6 @@ function createWorkerNode(config) {
2583
2590
  taskLength: currentAssignment.task.length,
2584
2591
  taskPreview: currentAssignment.task.substring(0, 100)
2585
2592
  });
2586
- let executionResult;
2587
- if (executeFn) {
2588
- logger2.debug("Using custom execution function", { workerId: id });
2589
- executionResult = await executeFn(state, runConfig);
2590
- } else if (agent && isReActAgent(agent)) {
2591
- logger2.debug("Using ReAct agent", { workerId: id });
2592
- const wrappedFn = wrapReActAgent(id, agent, verbose);
2593
- executionResult = await wrappedFn(state, runConfig);
2594
- } else if (model) {
2595
- executionResult = await executeWithLLM();
2596
- } else {
2597
- logger2.error("Worker missing required configuration", { workerId: id });
2598
- throw new Error(
2599
- `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2600
- );
2601
- }
2602
- const currentWorker = state.workers[id];
2603
- const updatedWorkers = {
2604
- ...state.workers,
2605
- [id]: {
2606
- ...currentWorker,
2607
- currentWorkload: Math.max(0, currentWorker.currentWorkload - 1)
2608
- }
2609
- };
2610
- logger2.debug("Worker state update", {
2611
- workerId: id,
2612
- previousWorkload: currentWorker.currentWorkload,
2613
- newWorkload: updatedWorkers[id].currentWorkload
2614
- });
2615
- return {
2616
- ...executionResult,
2617
- workers: updatedWorkers
2618
- };
2619
2593
  async function executeWithLLM() {
2620
2594
  logger2.debug("Using default LLM execution", {
2621
2595
  workerId: id,
@@ -2677,12 +2651,64 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2677
2651
  messages: [message]
2678
2652
  };
2679
2653
  }
2654
+ let executionResult;
2655
+ if (executeFn) {
2656
+ logger2.debug("Using custom execution function", { workerId: id });
2657
+ executionResult = await executeFn(state, runConfig);
2658
+ } else if (agent && isReActAgent(agent)) {
2659
+ logger2.debug("Using ReAct agent", { workerId: id });
2660
+ const wrappedFn = wrapReActAgent(id, agent, verbose);
2661
+ executionResult = await wrappedFn(state, runConfig);
2662
+ } else if (model) {
2663
+ executionResult = await executeWithLLM();
2664
+ } else {
2665
+ logger2.error("Worker missing required configuration", { workerId: id });
2666
+ throw new Error(
2667
+ `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2668
+ );
2669
+ }
2670
+ const currentWorker = state.workers[id];
2671
+ const baseWorkers = {
2672
+ ...state.workers,
2673
+ ...executionResult.workers || {}
2674
+ };
2675
+ const workerToUpdate = baseWorkers[id] || currentWorker;
2676
+ const updatedWorkers = {
2677
+ ...baseWorkers,
2678
+ [id]: {
2679
+ ...workerToUpdate,
2680
+ currentWorkload: Math.max(0, workerToUpdate.currentWorkload - 1)
2681
+ }
2682
+ };
2683
+ logger2.debug("Worker workload decremented", {
2684
+ workerId: id,
2685
+ previousWorkload: workerToUpdate.currentWorkload,
2686
+ newWorkload: updatedWorkers[id].currentWorkload,
2687
+ hadExecutionResultWorkers: !!executionResult.workers
2688
+ });
2689
+ return {
2690
+ ...executionResult,
2691
+ workers: updatedWorkers
2692
+ };
2680
2693
  } catch (error) {
2681
2694
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
2682
2695
  logger2.error("Worker node error", {
2683
2696
  workerId: id,
2684
2697
  error: errorMessage
2685
2698
  });
2699
+ const currentWorker = state.workers[id];
2700
+ const updatedWorkers = {
2701
+ ...state.workers,
2702
+ [id]: {
2703
+ ...currentWorker,
2704
+ currentWorkload: Math.max(0, currentWorker.currentWorkload - 1)
2705
+ }
2706
+ };
2707
+ logger2.debug("Worker workload decremented (error path)", {
2708
+ workerId: id,
2709
+ previousWorkload: currentWorker.currentWorkload,
2710
+ newWorkload: updatedWorkers[id].currentWorkload
2711
+ });
2686
2712
  const currentAssignment = state.activeAssignments.find(
2687
2713
  (assignment) => assignment.workerId === id
2688
2714
  );
@@ -2702,13 +2728,17 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2702
2728
  return {
2703
2729
  completedTasks: [errorResult],
2704
2730
  currentAgent: "supervisor",
2705
- status: "routing"
2731
+ status: "routing",
2732
+ workers: updatedWorkers
2733
+ // Include workload update
2706
2734
  };
2707
2735
  }
2708
2736
  logger2.error("No assignment found for error handling", { workerId: id });
2709
2737
  return {
2710
2738
  status: "failed",
2711
- error: errorMessage
2739
+ error: errorMessage,
2740
+ workers: updatedWorkers
2741
+ // Include workload update even on failure
2712
2742
  };
2713
2743
  }
2714
2744
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge/patterns",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Agent patterns (ReAct, Planner-Executor) for AgentForge framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",