@agentforge/patterns 0.11.1 → 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/README.md +7 -0
- package/dist/index.cjs +123 -76
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +123 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -514,6 +514,13 @@ pnpm test:coverage
|
|
|
514
514
|
pnpm typecheck
|
|
515
515
|
```
|
|
516
516
|
|
|
517
|
+
## 🔗 Links
|
|
518
|
+
|
|
519
|
+
- [GitHub Repository](https://github.com/TVScoundrel/agentforge)
|
|
520
|
+
- [npm Package](https://www.npmjs.com/package/@agentforge/patterns)
|
|
521
|
+
- [Changelog](https://tvscoundrel.github.io/agentforge/changelog.html) - See what's new before upgrading
|
|
522
|
+
- [Report Issues](https://github.com/TVScoundrel/agentforge/issues)
|
|
523
|
+
|
|
517
524
|
## License
|
|
518
525
|
|
|
519
526
|
MIT © 2026 Tom Van Schoor
|
package/dist/index.cjs
CHANGED
|
@@ -2608,11 +2608,29 @@ function createSupervisorNode(config) {
|
|
|
2608
2608
|
priority: assignment.priority
|
|
2609
2609
|
}
|
|
2610
2610
|
}));
|
|
2611
|
+
const updatedWorkers = { ...state.workers };
|
|
2612
|
+
for (const assignment of assignments) {
|
|
2613
|
+
const worker = updatedWorkers[assignment.workerId];
|
|
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
|
+
);
|
|
2622
|
+
}
|
|
2623
|
+
updatedWorkers[assignment.workerId] = {
|
|
2624
|
+
...worker,
|
|
2625
|
+
currentWorkload: worker.currentWorkload + 1
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2611
2628
|
logger2.info("Supervisor routing complete", {
|
|
2612
2629
|
currentAgent: targetAgents.join(","),
|
|
2613
2630
|
status: "executing",
|
|
2614
2631
|
assignmentCount: assignments.length,
|
|
2615
|
-
nextIteration: state.iteration + 1
|
|
2632
|
+
nextIteration: state.iteration + 1,
|
|
2633
|
+
workloadUpdates: Object.entries(updatedWorkers).filter(([id]) => targetAgents.includes(id)).map(([id, caps]) => ({ workerId: id, newWorkload: caps.currentWorkload }))
|
|
2616
2634
|
});
|
|
2617
2635
|
return {
|
|
2618
2636
|
currentAgent: targetAgents.join(","),
|
|
@@ -2622,6 +2640,8 @@ function createSupervisorNode(config) {
|
|
|
2622
2640
|
activeAssignments: assignments,
|
|
2623
2641
|
// Multiple assignments for parallel execution!
|
|
2624
2642
|
messages,
|
|
2643
|
+
workers: updatedWorkers,
|
|
2644
|
+
// Include updated workload
|
|
2625
2645
|
// Add 1 to iteration counter (uses additive reducer)
|
|
2626
2646
|
iteration: 1
|
|
2627
2647
|
};
|
|
@@ -2673,94 +2693,104 @@ function createWorkerNode(config) {
|
|
|
2673
2693
|
taskLength: currentAssignment.task.length,
|
|
2674
2694
|
taskPreview: currentAssignment.task.substring(0, 100)
|
|
2675
2695
|
});
|
|
2676
|
-
|
|
2677
|
-
logger2.debug("Using
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2684
|
-
return await wrappedFn(state, runConfig);
|
|
2685
|
-
} else {
|
|
2686
|
-
logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
if (!model) {
|
|
2690
|
-
logger2.error("Worker missing required configuration", { workerId: id });
|
|
2691
|
-
throw new Error(
|
|
2692
|
-
`Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
|
|
2693
|
-
);
|
|
2694
|
-
}
|
|
2695
|
-
logger2.debug("Using default LLM execution", {
|
|
2696
|
-
workerId: id,
|
|
2697
|
-
hasTools: tools.length > 0,
|
|
2698
|
-
toolCount: tools.length
|
|
2699
|
-
});
|
|
2700
|
-
const defaultSystemPrompt = `You are a specialized worker agent with the following capabilities:
|
|
2696
|
+
async function executeWithLLM() {
|
|
2697
|
+
logger2.debug("Using default LLM execution", {
|
|
2698
|
+
workerId: id,
|
|
2699
|
+
hasTools: tools.length > 0,
|
|
2700
|
+
toolCount: tools.length
|
|
2701
|
+
});
|
|
2702
|
+
const defaultSystemPrompt = `You are a specialized worker agent with the following capabilities:
|
|
2701
2703
|
Skills: ${capabilities.skills.join(", ")}
|
|
2702
2704
|
Tools: ${capabilities.tools.join(", ")}
|
|
2703
2705
|
|
|
2704
2706
|
Execute the assigned task using your skills and tools. Provide a clear, actionable result.`;
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2707
|
+
const messages = [
|
|
2708
|
+
new import_messages5.SystemMessage(systemPrompt || defaultSystemPrompt),
|
|
2709
|
+
new import_messages5.HumanMessage(currentAssignment.task)
|
|
2710
|
+
];
|
|
2711
|
+
let modelToUse = model;
|
|
2712
|
+
if (tools.length > 0 && model.bindTools) {
|
|
2713
|
+
logger2.debug("Binding tools to model", {
|
|
2714
|
+
workerId: id,
|
|
2715
|
+
toolCount: tools.length,
|
|
2716
|
+
toolNames: tools.map((t) => t.metadata.name)
|
|
2717
|
+
});
|
|
2718
|
+
const langchainTools = (0, import_core9.toLangChainTools)(tools);
|
|
2719
|
+
modelToUse = model.bindTools(langchainTools);
|
|
2720
|
+
}
|
|
2721
|
+
logger2.debug("Invoking LLM", { workerId: id });
|
|
2722
|
+
const response = await modelToUse.invoke(messages);
|
|
2723
|
+
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2724
|
+
logger2.info("Worker task completed", {
|
|
2712
2725
|
workerId: id,
|
|
2713
|
-
|
|
2714
|
-
|
|
2726
|
+
assignmentId: currentAssignment.id,
|
|
2727
|
+
resultLength: result.length,
|
|
2728
|
+
resultPreview: result.substring(0, 100)
|
|
2715
2729
|
});
|
|
2716
|
-
const
|
|
2717
|
-
modelToUse = model.bindTools(langchainTools);
|
|
2718
|
-
}
|
|
2719
|
-
logger2.debug("Invoking LLM", { workerId: id });
|
|
2720
|
-
const response = await modelToUse.invoke(messages);
|
|
2721
|
-
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2722
|
-
logger2.info("Worker task completed", {
|
|
2723
|
-
workerId: id,
|
|
2724
|
-
assignmentId: currentAssignment.id,
|
|
2725
|
-
resultLength: result.length,
|
|
2726
|
-
resultPreview: result.substring(0, 100)
|
|
2727
|
-
});
|
|
2728
|
-
const taskResult = {
|
|
2729
|
-
assignmentId: currentAssignment.id,
|
|
2730
|
-
workerId: id,
|
|
2731
|
-
success: true,
|
|
2732
|
-
result,
|
|
2733
|
-
completedAt: Date.now(),
|
|
2734
|
-
metadata: {
|
|
2735
|
-
skills_used: capabilities.skills
|
|
2736
|
-
}
|
|
2737
|
-
};
|
|
2738
|
-
const message = {
|
|
2739
|
-
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2740
|
-
from: id,
|
|
2741
|
-
to: ["supervisor"],
|
|
2742
|
-
type: "task_result",
|
|
2743
|
-
content: result,
|
|
2744
|
-
timestamp: Date.now(),
|
|
2745
|
-
metadata: {
|
|
2730
|
+
const taskResult = {
|
|
2746
2731
|
assignmentId: currentAssignment.id,
|
|
2747
|
-
|
|
2748
|
-
|
|
2732
|
+
workerId: id,
|
|
2733
|
+
success: true,
|
|
2734
|
+
result,
|
|
2735
|
+
completedAt: Date.now(),
|
|
2736
|
+
metadata: {
|
|
2737
|
+
skills_used: capabilities.skills
|
|
2738
|
+
}
|
|
2739
|
+
};
|
|
2740
|
+
const message = {
|
|
2741
|
+
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2742
|
+
from: id,
|
|
2743
|
+
to: ["supervisor"],
|
|
2744
|
+
type: "task_result",
|
|
2745
|
+
content: result,
|
|
2746
|
+
timestamp: Date.now(),
|
|
2747
|
+
metadata: {
|
|
2748
|
+
assignmentId: currentAssignment.id,
|
|
2749
|
+
success: true
|
|
2750
|
+
}
|
|
2751
|
+
};
|
|
2752
|
+
return {
|
|
2753
|
+
completedTasks: [taskResult],
|
|
2754
|
+
messages: [message]
|
|
2755
|
+
};
|
|
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 || {}
|
|
2749
2777
|
};
|
|
2778
|
+
const workerToUpdate = baseWorkers[id] || currentWorker;
|
|
2750
2779
|
const updatedWorkers = {
|
|
2751
|
-
...
|
|
2780
|
+
...baseWorkers,
|
|
2752
2781
|
[id]: {
|
|
2753
|
-
...
|
|
2754
|
-
currentWorkload: Math.max(0,
|
|
2782
|
+
...workerToUpdate,
|
|
2783
|
+
currentWorkload: Math.max(0, workerToUpdate.currentWorkload - 1)
|
|
2755
2784
|
}
|
|
2756
2785
|
};
|
|
2757
|
-
logger2.debug("Worker
|
|
2786
|
+
logger2.debug("Worker workload decremented", {
|
|
2758
2787
|
workerId: id,
|
|
2759
|
-
|
|
2788
|
+
previousWorkload: workerToUpdate.currentWorkload,
|
|
2789
|
+
newWorkload: updatedWorkers[id].currentWorkload,
|
|
2790
|
+
hadExecutionResultWorkers: !!executionResult.workers
|
|
2760
2791
|
});
|
|
2761
2792
|
return {
|
|
2762
|
-
|
|
2763
|
-
messages: [message],
|
|
2793
|
+
...executionResult,
|
|
2764
2794
|
workers: updatedWorkers
|
|
2765
2795
|
};
|
|
2766
2796
|
} catch (error) {
|
|
@@ -2769,6 +2799,19 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2769
2799
|
workerId: id,
|
|
2770
2800
|
error: errorMessage
|
|
2771
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
|
+
});
|
|
2772
2815
|
const currentAssignment = state.activeAssignments.find(
|
|
2773
2816
|
(assignment) => assignment.workerId === id
|
|
2774
2817
|
);
|
|
@@ -2788,13 +2831,17 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2788
2831
|
return {
|
|
2789
2832
|
completedTasks: [errorResult],
|
|
2790
2833
|
currentAgent: "supervisor",
|
|
2791
|
-
status: "routing"
|
|
2834
|
+
status: "routing",
|
|
2835
|
+
workers: updatedWorkers
|
|
2836
|
+
// Include workload update
|
|
2792
2837
|
};
|
|
2793
2838
|
}
|
|
2794
2839
|
logger2.error("No assignment found for error handling", { workerId: id });
|
|
2795
2840
|
return {
|
|
2796
2841
|
status: "failed",
|
|
2797
|
-
error: errorMessage
|
|
2842
|
+
error: errorMessage,
|
|
2843
|
+
workers: updatedWorkers
|
|
2844
|
+
// Include workload update even on failure
|
|
2798
2845
|
};
|
|
2799
2846
|
}
|
|
2800
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
|
@@ -2505,11 +2505,29 @@ function createSupervisorNode(config) {
|
|
|
2505
2505
|
priority: assignment.priority
|
|
2506
2506
|
}
|
|
2507
2507
|
}));
|
|
2508
|
+
const updatedWorkers = { ...state.workers };
|
|
2509
|
+
for (const assignment of assignments) {
|
|
2510
|
+
const worker = updatedWorkers[assignment.workerId];
|
|
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
|
+
);
|
|
2519
|
+
}
|
|
2520
|
+
updatedWorkers[assignment.workerId] = {
|
|
2521
|
+
...worker,
|
|
2522
|
+
currentWorkload: worker.currentWorkload + 1
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2508
2525
|
logger2.info("Supervisor routing complete", {
|
|
2509
2526
|
currentAgent: targetAgents.join(","),
|
|
2510
2527
|
status: "executing",
|
|
2511
2528
|
assignmentCount: assignments.length,
|
|
2512
|
-
nextIteration: state.iteration + 1
|
|
2529
|
+
nextIteration: state.iteration + 1,
|
|
2530
|
+
workloadUpdates: Object.entries(updatedWorkers).filter(([id]) => targetAgents.includes(id)).map(([id, caps]) => ({ workerId: id, newWorkload: caps.currentWorkload }))
|
|
2513
2531
|
});
|
|
2514
2532
|
return {
|
|
2515
2533
|
currentAgent: targetAgents.join(","),
|
|
@@ -2519,6 +2537,8 @@ function createSupervisorNode(config) {
|
|
|
2519
2537
|
activeAssignments: assignments,
|
|
2520
2538
|
// Multiple assignments for parallel execution!
|
|
2521
2539
|
messages,
|
|
2540
|
+
workers: updatedWorkers,
|
|
2541
|
+
// Include updated workload
|
|
2522
2542
|
// Add 1 to iteration counter (uses additive reducer)
|
|
2523
2543
|
iteration: 1
|
|
2524
2544
|
};
|
|
@@ -2570,94 +2590,104 @@ function createWorkerNode(config) {
|
|
|
2570
2590
|
taskLength: currentAssignment.task.length,
|
|
2571
2591
|
taskPreview: currentAssignment.task.substring(0, 100)
|
|
2572
2592
|
});
|
|
2573
|
-
|
|
2574
|
-
logger2.debug("Using
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2581
|
-
return await wrappedFn(state, runConfig);
|
|
2582
|
-
} else {
|
|
2583
|
-
logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
if (!model) {
|
|
2587
|
-
logger2.error("Worker missing required configuration", { workerId: id });
|
|
2588
|
-
throw new Error(
|
|
2589
|
-
`Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
|
|
2590
|
-
);
|
|
2591
|
-
}
|
|
2592
|
-
logger2.debug("Using default LLM execution", {
|
|
2593
|
-
workerId: id,
|
|
2594
|
-
hasTools: tools.length > 0,
|
|
2595
|
-
toolCount: tools.length
|
|
2596
|
-
});
|
|
2597
|
-
const defaultSystemPrompt = `You are a specialized worker agent with the following capabilities:
|
|
2593
|
+
async function executeWithLLM() {
|
|
2594
|
+
logger2.debug("Using default LLM execution", {
|
|
2595
|
+
workerId: id,
|
|
2596
|
+
hasTools: tools.length > 0,
|
|
2597
|
+
toolCount: tools.length
|
|
2598
|
+
});
|
|
2599
|
+
const defaultSystemPrompt = `You are a specialized worker agent with the following capabilities:
|
|
2598
2600
|
Skills: ${capabilities.skills.join(", ")}
|
|
2599
2601
|
Tools: ${capabilities.tools.join(", ")}
|
|
2600
2602
|
|
|
2601
2603
|
Execute the assigned task using your skills and tools. Provide a clear, actionable result.`;
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2604
|
+
const messages = [
|
|
2605
|
+
new SystemMessage5(systemPrompt || defaultSystemPrompt),
|
|
2606
|
+
new HumanMessage5(currentAssignment.task)
|
|
2607
|
+
];
|
|
2608
|
+
let modelToUse = model;
|
|
2609
|
+
if (tools.length > 0 && model.bindTools) {
|
|
2610
|
+
logger2.debug("Binding tools to model", {
|
|
2611
|
+
workerId: id,
|
|
2612
|
+
toolCount: tools.length,
|
|
2613
|
+
toolNames: tools.map((t) => t.metadata.name)
|
|
2614
|
+
});
|
|
2615
|
+
const langchainTools = toLangChainTools2(tools);
|
|
2616
|
+
modelToUse = model.bindTools(langchainTools);
|
|
2617
|
+
}
|
|
2618
|
+
logger2.debug("Invoking LLM", { workerId: id });
|
|
2619
|
+
const response = await modelToUse.invoke(messages);
|
|
2620
|
+
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2621
|
+
logger2.info("Worker task completed", {
|
|
2609
2622
|
workerId: id,
|
|
2610
|
-
|
|
2611
|
-
|
|
2623
|
+
assignmentId: currentAssignment.id,
|
|
2624
|
+
resultLength: result.length,
|
|
2625
|
+
resultPreview: result.substring(0, 100)
|
|
2612
2626
|
});
|
|
2613
|
-
const
|
|
2614
|
-
modelToUse = model.bindTools(langchainTools);
|
|
2615
|
-
}
|
|
2616
|
-
logger2.debug("Invoking LLM", { workerId: id });
|
|
2617
|
-
const response = await modelToUse.invoke(messages);
|
|
2618
|
-
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2619
|
-
logger2.info("Worker task completed", {
|
|
2620
|
-
workerId: id,
|
|
2621
|
-
assignmentId: currentAssignment.id,
|
|
2622
|
-
resultLength: result.length,
|
|
2623
|
-
resultPreview: result.substring(0, 100)
|
|
2624
|
-
});
|
|
2625
|
-
const taskResult = {
|
|
2626
|
-
assignmentId: currentAssignment.id,
|
|
2627
|
-
workerId: id,
|
|
2628
|
-
success: true,
|
|
2629
|
-
result,
|
|
2630
|
-
completedAt: Date.now(),
|
|
2631
|
-
metadata: {
|
|
2632
|
-
skills_used: capabilities.skills
|
|
2633
|
-
}
|
|
2634
|
-
};
|
|
2635
|
-
const message = {
|
|
2636
|
-
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2637
|
-
from: id,
|
|
2638
|
-
to: ["supervisor"],
|
|
2639
|
-
type: "task_result",
|
|
2640
|
-
content: result,
|
|
2641
|
-
timestamp: Date.now(),
|
|
2642
|
-
metadata: {
|
|
2627
|
+
const taskResult = {
|
|
2643
2628
|
assignmentId: currentAssignment.id,
|
|
2644
|
-
|
|
2645
|
-
|
|
2629
|
+
workerId: id,
|
|
2630
|
+
success: true,
|
|
2631
|
+
result,
|
|
2632
|
+
completedAt: Date.now(),
|
|
2633
|
+
metadata: {
|
|
2634
|
+
skills_used: capabilities.skills
|
|
2635
|
+
}
|
|
2636
|
+
};
|
|
2637
|
+
const message = {
|
|
2638
|
+
id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
2639
|
+
from: id,
|
|
2640
|
+
to: ["supervisor"],
|
|
2641
|
+
type: "task_result",
|
|
2642
|
+
content: result,
|
|
2643
|
+
timestamp: Date.now(),
|
|
2644
|
+
metadata: {
|
|
2645
|
+
assignmentId: currentAssignment.id,
|
|
2646
|
+
success: true
|
|
2647
|
+
}
|
|
2648
|
+
};
|
|
2649
|
+
return {
|
|
2650
|
+
completedTasks: [taskResult],
|
|
2651
|
+
messages: [message]
|
|
2652
|
+
};
|
|
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 || {}
|
|
2646
2674
|
};
|
|
2675
|
+
const workerToUpdate = baseWorkers[id] || currentWorker;
|
|
2647
2676
|
const updatedWorkers = {
|
|
2648
|
-
...
|
|
2677
|
+
...baseWorkers,
|
|
2649
2678
|
[id]: {
|
|
2650
|
-
...
|
|
2651
|
-
currentWorkload: Math.max(0,
|
|
2679
|
+
...workerToUpdate,
|
|
2680
|
+
currentWorkload: Math.max(0, workerToUpdate.currentWorkload - 1)
|
|
2652
2681
|
}
|
|
2653
2682
|
};
|
|
2654
|
-
logger2.debug("Worker
|
|
2683
|
+
logger2.debug("Worker workload decremented", {
|
|
2655
2684
|
workerId: id,
|
|
2656
|
-
|
|
2685
|
+
previousWorkload: workerToUpdate.currentWorkload,
|
|
2686
|
+
newWorkload: updatedWorkers[id].currentWorkload,
|
|
2687
|
+
hadExecutionResultWorkers: !!executionResult.workers
|
|
2657
2688
|
});
|
|
2658
2689
|
return {
|
|
2659
|
-
|
|
2660
|
-
messages: [message],
|
|
2690
|
+
...executionResult,
|
|
2661
2691
|
workers: updatedWorkers
|
|
2662
2692
|
};
|
|
2663
2693
|
} catch (error) {
|
|
@@ -2666,6 +2696,19 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2666
2696
|
workerId: id,
|
|
2667
2697
|
error: errorMessage
|
|
2668
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
|
+
});
|
|
2669
2712
|
const currentAssignment = state.activeAssignments.find(
|
|
2670
2713
|
(assignment) => assignment.workerId === id
|
|
2671
2714
|
);
|
|
@@ -2685,13 +2728,17 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2685
2728
|
return {
|
|
2686
2729
|
completedTasks: [errorResult],
|
|
2687
2730
|
currentAgent: "supervisor",
|
|
2688
|
-
status: "routing"
|
|
2731
|
+
status: "routing",
|
|
2732
|
+
workers: updatedWorkers
|
|
2733
|
+
// Include workload update
|
|
2689
2734
|
};
|
|
2690
2735
|
}
|
|
2691
2736
|
logger2.error("No assignment found for error handling", { workerId: id });
|
|
2692
2737
|
return {
|
|
2693
2738
|
status: "failed",
|
|
2694
|
-
error: errorMessage
|
|
2739
|
+
error: errorMessage,
|
|
2740
|
+
workers: updatedWorkers
|
|
2741
|
+
// Include workload update even on failure
|
|
2695
2742
|
};
|
|
2696
2743
|
}
|
|
2697
2744
|
};
|