@agentforge/patterns 0.6.4 → 0.8.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 +280 -521
- package/dist/index.d.cts +0 -25
- package/dist/index.d.ts +0 -25
- package/dist/index.js +280 -521
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -35,15 +35,46 @@ var ScratchpadEntrySchema = z.object({
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
// src/react/state.ts
|
|
38
|
-
import { z as
|
|
38
|
+
import { z as z3 } from "zod";
|
|
39
39
|
import { createStateAnnotation } from "@agentforge/core";
|
|
40
|
+
|
|
41
|
+
// src/shared/state-fields.ts
|
|
42
|
+
import { z as z2 } from "zod";
|
|
43
|
+
var iterationField = {
|
|
44
|
+
schema: z2.number().int().nonnegative(),
|
|
45
|
+
reducer: (left, right) => left + right,
|
|
46
|
+
default: () => 0,
|
|
47
|
+
description: "Current iteration number"
|
|
48
|
+
};
|
|
49
|
+
function maxIterationsField(defaultValue) {
|
|
50
|
+
return {
|
|
51
|
+
schema: z2.number().int().positive(),
|
|
52
|
+
default: () => defaultValue,
|
|
53
|
+
description: "Maximum number of iterations allowed"
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
var errorField = {
|
|
57
|
+
schema: z2.string().optional(),
|
|
58
|
+
description: "Error message if execution failed"
|
|
59
|
+
};
|
|
60
|
+
var responseField = {
|
|
61
|
+
schema: z2.string().optional(),
|
|
62
|
+
description: "Final response after completion"
|
|
63
|
+
};
|
|
64
|
+
var inputField = {
|
|
65
|
+
schema: z2.string(),
|
|
66
|
+
default: () => "",
|
|
67
|
+
description: "Original user input or query"
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/react/state.ts
|
|
40
71
|
var ReActStateConfig = {
|
|
41
72
|
/**
|
|
42
73
|
* Conversation messages
|
|
43
74
|
* Accumulates all messages in the conversation
|
|
44
75
|
*/
|
|
45
76
|
messages: {
|
|
46
|
-
schema:
|
|
77
|
+
schema: z3.array(MessageSchema),
|
|
47
78
|
reducer: (left, right) => [...left, ...right],
|
|
48
79
|
default: () => [],
|
|
49
80
|
description: "Conversation message history"
|
|
@@ -53,7 +84,7 @@ var ReActStateConfig = {
|
|
|
53
84
|
* Accumulates all reasoning steps the agent takes
|
|
54
85
|
*/
|
|
55
86
|
thoughts: {
|
|
56
|
-
schema:
|
|
87
|
+
schema: z3.array(ThoughtSchema),
|
|
57
88
|
reducer: (left, right) => [...left, ...right],
|
|
58
89
|
default: () => [],
|
|
59
90
|
description: "Agent reasoning steps"
|
|
@@ -63,7 +94,7 @@ var ReActStateConfig = {
|
|
|
63
94
|
* Accumulates all tool calls made by the agent
|
|
64
95
|
*/
|
|
65
96
|
actions: {
|
|
66
|
-
schema:
|
|
97
|
+
schema: z3.array(ToolCallSchema),
|
|
67
98
|
reducer: (left, right) => [...left, ...right],
|
|
68
99
|
default: () => [],
|
|
69
100
|
description: "Tool calls made by the agent"
|
|
@@ -73,7 +104,7 @@ var ReActStateConfig = {
|
|
|
73
104
|
* Accumulates all observations from tool executions
|
|
74
105
|
*/
|
|
75
106
|
observations: {
|
|
76
|
-
schema:
|
|
107
|
+
schema: z3.array(ToolResultSchema),
|
|
77
108
|
reducer: (left, right) => [...left, ...right],
|
|
78
109
|
default: () => [],
|
|
79
110
|
description: "Results from tool executions"
|
|
@@ -83,7 +114,7 @@ var ReActStateConfig = {
|
|
|
83
114
|
* Accumulates step-by-step reasoning process
|
|
84
115
|
*/
|
|
85
116
|
scratchpad: {
|
|
86
|
-
schema:
|
|
117
|
+
schema: z3.array(ScratchpadEntrySchema),
|
|
87
118
|
reducer: (left, right) => [...left, ...right],
|
|
88
119
|
default: () => [],
|
|
89
120
|
description: "Intermediate reasoning scratchpad"
|
|
@@ -92,27 +123,19 @@ var ReActStateConfig = {
|
|
|
92
123
|
* Current iteration count
|
|
93
124
|
* Tracks how many thought-action-observation loops have been executed
|
|
94
125
|
*/
|
|
95
|
-
iteration:
|
|
96
|
-
schema: z2.number(),
|
|
97
|
-
reducer: (left, right) => left + right,
|
|
98
|
-
default: () => 0,
|
|
99
|
-
description: "Current iteration count"
|
|
100
|
-
},
|
|
126
|
+
iteration: iterationField,
|
|
101
127
|
/**
|
|
102
128
|
* Whether the agent should continue iterating
|
|
103
129
|
*/
|
|
104
130
|
shouldContinue: {
|
|
105
|
-
schema:
|
|
131
|
+
schema: z3.boolean().optional(),
|
|
106
132
|
default: () => true,
|
|
107
133
|
description: "Whether to continue the ReAct loop"
|
|
108
134
|
},
|
|
109
135
|
/**
|
|
110
136
|
* Final response (if any)
|
|
111
137
|
*/
|
|
112
|
-
response:
|
|
113
|
-
schema: z2.string().optional(),
|
|
114
|
-
description: "Final response from the agent"
|
|
115
|
-
}
|
|
138
|
+
response: responseField
|
|
116
139
|
};
|
|
117
140
|
var ReActState = createStateAnnotation(ReActStateConfig);
|
|
118
141
|
|
|
@@ -157,8 +180,8 @@ function generateToolCallCacheKey(toolName, args) {
|
|
|
157
180
|
return `${toolName}:${sortedArgs}`;
|
|
158
181
|
}
|
|
159
182
|
function createPatternLogger(name, defaultLevel = "info") {
|
|
160
|
-
const
|
|
161
|
-
return createLogger(name, { level:
|
|
183
|
+
const logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
|
|
184
|
+
return createLogger(name, { level: logLevel4 });
|
|
162
185
|
}
|
|
163
186
|
function calculateDeduplicationSavings(duplicatesSkipped, toolsExecuted) {
|
|
164
187
|
if (duplicatesSkipped === 0) {
|
|
@@ -176,6 +199,24 @@ function buildDeduplicationMetrics(toolsExecuted, duplicatesSkipped, totalObserv
|
|
|
176
199
|
};
|
|
177
200
|
}
|
|
178
201
|
|
|
202
|
+
// src/shared/error-handling.ts
|
|
203
|
+
function isGraphInterrupt(error) {
|
|
204
|
+
return error !== null && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt";
|
|
205
|
+
}
|
|
206
|
+
function handleNodeError(error, context, verbose = false) {
|
|
207
|
+
if (isGraphInterrupt(error)) {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
211
|
+
if (verbose) {
|
|
212
|
+
console.error(`[${context}] Error:`, errorMessage);
|
|
213
|
+
if (error instanceof Error && error.stack) {
|
|
214
|
+
console.error(`[${context}] Stack:`, error.stack);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return errorMessage;
|
|
218
|
+
}
|
|
219
|
+
|
|
179
220
|
// src/react/nodes.ts
|
|
180
221
|
var reasoningLogger = createPatternLogger("agentforge:patterns:react:reasoning");
|
|
181
222
|
var actionLogger = createPatternLogger("agentforge:patterns:react:action");
|
|
@@ -338,10 +379,7 @@ function createActionNode(tools, verbose = false, enableDeduplication = true) {
|
|
|
338
379
|
executionCache.set(cacheKey, observation);
|
|
339
380
|
}
|
|
340
381
|
} catch (error) {
|
|
341
|
-
|
|
342
|
-
throw error;
|
|
343
|
-
}
|
|
344
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
382
|
+
const errorMessage = handleNodeError(error, `action:${action.name}`, false);
|
|
345
383
|
actionLogger.error("Tool execution failed", {
|
|
346
384
|
toolName: action.name,
|
|
347
385
|
error: errorMessage,
|
|
@@ -580,34 +618,34 @@ function createReActAgentBuilder() {
|
|
|
580
618
|
import { StateGraph as StateGraph2, END as END2 } from "@langchain/langgraph";
|
|
581
619
|
|
|
582
620
|
// src/plan-execute/state.ts
|
|
583
|
-
import { z as
|
|
621
|
+
import { z as z5 } from "zod";
|
|
584
622
|
import { createStateAnnotation as createStateAnnotation2 } from "@agentforge/core";
|
|
585
623
|
|
|
586
624
|
// src/plan-execute/schemas.ts
|
|
587
|
-
import { z as
|
|
588
|
-
var PlanStepSchema =
|
|
625
|
+
import { z as z4 } from "zod";
|
|
626
|
+
var PlanStepSchema = z4.object({
|
|
589
627
|
/**
|
|
590
628
|
* Unique identifier for the step
|
|
591
629
|
*/
|
|
592
|
-
id:
|
|
630
|
+
id: z4.string().describe("Unique identifier for the step"),
|
|
593
631
|
/**
|
|
594
632
|
* Description of what this step should accomplish
|
|
595
633
|
*/
|
|
596
|
-
description:
|
|
634
|
+
description: z4.string().describe("Description of what this step should accomplish"),
|
|
597
635
|
/**
|
|
598
636
|
* Optional dependencies on other steps (by ID)
|
|
599
637
|
*/
|
|
600
|
-
dependencies:
|
|
638
|
+
dependencies: z4.array(z4.string()).optional().describe("IDs of steps that must complete before this one"),
|
|
601
639
|
/**
|
|
602
640
|
* Optional tool to use for this step
|
|
603
641
|
*/
|
|
604
|
-
tool:
|
|
642
|
+
tool: z4.string().optional().describe("Name of the tool to use for this step"),
|
|
605
643
|
/**
|
|
606
644
|
* Optional arguments for the tool
|
|
607
645
|
*/
|
|
608
|
-
args:
|
|
646
|
+
args: z4.record(z4.any()).optional().describe("Arguments to pass to the tool")
|
|
609
647
|
});
|
|
610
|
-
var CompletedStepSchema =
|
|
648
|
+
var CompletedStepSchema = z4.object({
|
|
611
649
|
/**
|
|
612
650
|
* The step that was executed
|
|
613
651
|
*/
|
|
@@ -615,53 +653,53 @@ var CompletedStepSchema = z3.object({
|
|
|
615
653
|
/**
|
|
616
654
|
* The result of executing the step
|
|
617
655
|
*/
|
|
618
|
-
result:
|
|
656
|
+
result: z4.any().describe("The result of executing the step"),
|
|
619
657
|
/**
|
|
620
658
|
* Whether the step succeeded
|
|
621
659
|
*/
|
|
622
|
-
success:
|
|
660
|
+
success: z4.boolean().describe("Whether the step succeeded"),
|
|
623
661
|
/**
|
|
624
662
|
* Optional error message if the step failed
|
|
625
663
|
*/
|
|
626
|
-
error:
|
|
664
|
+
error: z4.string().optional().describe("Error message if the step failed"),
|
|
627
665
|
/**
|
|
628
666
|
* Timestamp when the step was completed
|
|
629
667
|
*/
|
|
630
|
-
timestamp:
|
|
668
|
+
timestamp: z4.string().datetime().describe("ISO timestamp when the step was completed")
|
|
631
669
|
});
|
|
632
|
-
var PlanSchema =
|
|
670
|
+
var PlanSchema = z4.object({
|
|
633
671
|
/**
|
|
634
672
|
* List of steps in the plan
|
|
635
673
|
*/
|
|
636
|
-
steps:
|
|
674
|
+
steps: z4.array(PlanStepSchema).describe("List of steps in the plan"),
|
|
637
675
|
/**
|
|
638
676
|
* Overall goal of the plan
|
|
639
677
|
*/
|
|
640
|
-
goal:
|
|
678
|
+
goal: z4.string().describe("Overall goal of the plan"),
|
|
641
679
|
/**
|
|
642
680
|
* Timestamp when the plan was created
|
|
643
681
|
*/
|
|
644
|
-
createdAt:
|
|
682
|
+
createdAt: z4.string().datetime().describe("ISO timestamp when the plan was created"),
|
|
645
683
|
/**
|
|
646
684
|
* Optional confidence score (0-1)
|
|
647
685
|
*/
|
|
648
|
-
confidence:
|
|
686
|
+
confidence: z4.number().min(0).max(1).optional().describe("Confidence score for the plan (0-1)")
|
|
649
687
|
});
|
|
650
|
-
var ReplanDecisionSchema =
|
|
688
|
+
var ReplanDecisionSchema = z4.object({
|
|
651
689
|
/**
|
|
652
690
|
* Whether to replan
|
|
653
691
|
*/
|
|
654
|
-
shouldReplan:
|
|
692
|
+
shouldReplan: z4.boolean().describe("Whether to replan based on current results"),
|
|
655
693
|
/**
|
|
656
694
|
* Reason for the decision
|
|
657
695
|
*/
|
|
658
|
-
reason:
|
|
696
|
+
reason: z4.string().describe("Reason for the replan decision"),
|
|
659
697
|
/**
|
|
660
698
|
* Optional new goal if replanning
|
|
661
699
|
*/
|
|
662
|
-
newGoal:
|
|
700
|
+
newGoal: z4.string().optional().describe("Updated goal if replanning")
|
|
663
701
|
});
|
|
664
|
-
var ExecutionStatusSchema =
|
|
702
|
+
var ExecutionStatusSchema = z4.enum([
|
|
665
703
|
"planning",
|
|
666
704
|
"executing",
|
|
667
705
|
"replanning",
|
|
@@ -674,11 +712,7 @@ var PlanExecuteStateConfig = {
|
|
|
674
712
|
/**
|
|
675
713
|
* Original user input/query
|
|
676
714
|
*/
|
|
677
|
-
input:
|
|
678
|
-
schema: z4.string(),
|
|
679
|
-
default: () => "",
|
|
680
|
-
description: "Original user input or query"
|
|
681
|
-
},
|
|
715
|
+
input: inputField,
|
|
682
716
|
/**
|
|
683
717
|
* The current plan
|
|
684
718
|
*/
|
|
@@ -691,7 +725,7 @@ var PlanExecuteStateConfig = {
|
|
|
691
725
|
* Accumulates all completed steps
|
|
692
726
|
*/
|
|
693
727
|
pastSteps: {
|
|
694
|
-
schema:
|
|
728
|
+
schema: z5.array(CompletedStepSchema),
|
|
695
729
|
reducer: (left, right) => [...left, ...right],
|
|
696
730
|
default: () => [],
|
|
697
731
|
description: "Completed steps with their results"
|
|
@@ -700,7 +734,7 @@ var PlanExecuteStateConfig = {
|
|
|
700
734
|
* Index of the current step being executed
|
|
701
735
|
*/
|
|
702
736
|
currentStepIndex: {
|
|
703
|
-
schema:
|
|
737
|
+
schema: z5.number().int().nonnegative().optional(),
|
|
704
738
|
description: "Index of the current step being executed"
|
|
705
739
|
},
|
|
706
740
|
/**
|
|
@@ -714,34 +748,19 @@ var PlanExecuteStateConfig = {
|
|
|
714
748
|
/**
|
|
715
749
|
* Final response
|
|
716
750
|
*/
|
|
717
|
-
response:
|
|
718
|
-
schema: z4.string().optional(),
|
|
719
|
-
description: "Final response after plan execution"
|
|
720
|
-
},
|
|
751
|
+
response: responseField,
|
|
721
752
|
/**
|
|
722
753
|
* Error message if execution failed
|
|
723
754
|
*/
|
|
724
|
-
error:
|
|
725
|
-
schema: z4.string().optional(),
|
|
726
|
-
description: "Error message if execution failed"
|
|
727
|
-
},
|
|
755
|
+
error: errorField,
|
|
728
756
|
/**
|
|
729
757
|
* Iteration counter for replanning
|
|
730
758
|
*/
|
|
731
|
-
iteration:
|
|
732
|
-
schema: z4.number().int().nonnegative(),
|
|
733
|
-
reducer: (left, right) => left + right,
|
|
734
|
-
default: () => 0,
|
|
735
|
-
description: "Number of planning iterations"
|
|
736
|
-
},
|
|
759
|
+
iteration: iterationField,
|
|
737
760
|
/**
|
|
738
761
|
* Maximum iterations allowed
|
|
739
762
|
*/
|
|
740
|
-
maxIterations:
|
|
741
|
-
schema: z4.number().int().positive(),
|
|
742
|
-
default: () => 5,
|
|
743
|
-
description: "Maximum number of planning iterations allowed"
|
|
744
|
-
}
|
|
763
|
+
maxIterations: maxIterationsField(5)
|
|
745
764
|
};
|
|
746
765
|
var PlanExecuteState = createStateAnnotation2(PlanExecuteStateConfig);
|
|
747
766
|
|
|
@@ -974,11 +993,8 @@ function createExecutorNode(config) {
|
|
|
974
993
|
result = { message: "Step completed without tool execution" };
|
|
975
994
|
}
|
|
976
995
|
} catch (execError) {
|
|
977
|
-
|
|
978
|
-
throw execError;
|
|
979
|
-
}
|
|
996
|
+
error = handleNodeError(execError, `executor:${currentStep.description}`, false);
|
|
980
997
|
success = false;
|
|
981
|
-
error = execError instanceof Error ? execError.message : "Unknown execution error";
|
|
982
998
|
result = null;
|
|
983
999
|
executorLogger.warn("Step execution failed", {
|
|
984
1000
|
stepId: currentStep.id,
|
|
@@ -1181,46 +1197,46 @@ function createPlanExecuteAgent(config) {
|
|
|
1181
1197
|
}
|
|
1182
1198
|
|
|
1183
1199
|
// src/reflection/state.ts
|
|
1184
|
-
import { z as
|
|
1200
|
+
import { z as z7 } from "zod";
|
|
1185
1201
|
import { createStateAnnotation as createStateAnnotation3 } from "@agentforge/core";
|
|
1186
1202
|
|
|
1187
1203
|
// src/reflection/schemas.ts
|
|
1188
|
-
import { z as
|
|
1189
|
-
var ReflectionSchema =
|
|
1204
|
+
import { z as z6 } from "zod";
|
|
1205
|
+
var ReflectionSchema = z6.object({
|
|
1190
1206
|
/**
|
|
1191
1207
|
* The critique or feedback on the current response
|
|
1192
1208
|
*/
|
|
1193
|
-
critique:
|
|
1209
|
+
critique: z6.string().describe("Critique or feedback on the current response"),
|
|
1194
1210
|
/**
|
|
1195
1211
|
* Specific issues identified
|
|
1196
1212
|
*/
|
|
1197
|
-
issues:
|
|
1213
|
+
issues: z6.array(z6.string()).describe("Specific issues or problems identified"),
|
|
1198
1214
|
/**
|
|
1199
1215
|
* Suggestions for improvement
|
|
1200
1216
|
*/
|
|
1201
|
-
suggestions:
|
|
1217
|
+
suggestions: z6.array(z6.string()).describe("Suggestions for improving the response"),
|
|
1202
1218
|
/**
|
|
1203
1219
|
* Quality score (0-10)
|
|
1204
1220
|
*/
|
|
1205
|
-
score:
|
|
1221
|
+
score: z6.number().min(0).max(10).optional().describe("Quality score from 0 to 10"),
|
|
1206
1222
|
/**
|
|
1207
1223
|
* Whether the response meets quality standards
|
|
1208
1224
|
*/
|
|
1209
|
-
meetsStandards:
|
|
1225
|
+
meetsStandards: z6.boolean().describe("Whether the response meets quality standards"),
|
|
1210
1226
|
/**
|
|
1211
1227
|
* Timestamp of the reflection
|
|
1212
1228
|
*/
|
|
1213
|
-
timestamp:
|
|
1229
|
+
timestamp: z6.date().optional().describe("When this reflection was created")
|
|
1214
1230
|
});
|
|
1215
|
-
var RevisionSchema =
|
|
1231
|
+
var RevisionSchema = z6.object({
|
|
1216
1232
|
/**
|
|
1217
1233
|
* The revised content
|
|
1218
1234
|
*/
|
|
1219
|
-
content:
|
|
1235
|
+
content: z6.string().describe("The revised content"),
|
|
1220
1236
|
/**
|
|
1221
1237
|
* Which iteration this revision is from
|
|
1222
1238
|
*/
|
|
1223
|
-
iteration:
|
|
1239
|
+
iteration: z6.number().int().nonnegative().describe("Iteration number"),
|
|
1224
1240
|
/**
|
|
1225
1241
|
* The reflection that prompted this revision
|
|
1226
1242
|
*/
|
|
@@ -1228,9 +1244,9 @@ var RevisionSchema = z5.object({
|
|
|
1228
1244
|
/**
|
|
1229
1245
|
* Timestamp of the revision
|
|
1230
1246
|
*/
|
|
1231
|
-
timestamp:
|
|
1247
|
+
timestamp: z6.date().optional().describe("When this revision was created")
|
|
1232
1248
|
});
|
|
1233
|
-
var ReflectionStatusSchema =
|
|
1249
|
+
var ReflectionStatusSchema = z6.enum([
|
|
1234
1250
|
"generating",
|
|
1235
1251
|
// Initial generation
|
|
1236
1252
|
"reflecting",
|
|
@@ -1242,25 +1258,25 @@ var ReflectionStatusSchema = z5.enum([
|
|
|
1242
1258
|
"failed"
|
|
1243
1259
|
// Max iterations reached without meeting standards
|
|
1244
1260
|
]);
|
|
1245
|
-
var QualityCriteriaSchema =
|
|
1261
|
+
var QualityCriteriaSchema = z6.object({
|
|
1246
1262
|
/**
|
|
1247
1263
|
* Minimum quality score required (0-10)
|
|
1248
1264
|
*/
|
|
1249
|
-
minScore:
|
|
1265
|
+
minScore: z6.number().min(0).max(10).default(7).describe("Minimum quality score required"),
|
|
1250
1266
|
/**
|
|
1251
1267
|
* Specific criteria to evaluate
|
|
1252
1268
|
*/
|
|
1253
|
-
criteria:
|
|
1269
|
+
criteria: z6.array(z6.string()).optional().describe("Specific criteria to evaluate"),
|
|
1254
1270
|
/**
|
|
1255
1271
|
* Whether all criteria must be met
|
|
1256
1272
|
*/
|
|
1257
|
-
requireAll:
|
|
1273
|
+
requireAll: z6.boolean().default(true).describe("Whether all criteria must be met")
|
|
1258
1274
|
});
|
|
1259
|
-
var ReflectionConfigSchema =
|
|
1275
|
+
var ReflectionConfigSchema = z6.object({
|
|
1260
1276
|
/**
|
|
1261
1277
|
* Maximum number of reflection iterations
|
|
1262
1278
|
*/
|
|
1263
|
-
maxIterations:
|
|
1279
|
+
maxIterations: z6.number().int().positive().default(3).describe("Maximum reflection iterations"),
|
|
1264
1280
|
/**
|
|
1265
1281
|
* Quality criteria for completion
|
|
1266
1282
|
*/
|
|
@@ -1268,7 +1284,7 @@ var ReflectionConfigSchema = z5.object({
|
|
|
1268
1284
|
/**
|
|
1269
1285
|
* Whether to include previous reflections in context
|
|
1270
1286
|
*/
|
|
1271
|
-
includeHistory:
|
|
1287
|
+
includeHistory: z6.boolean().default(true).describe("Include previous reflections in context")
|
|
1272
1288
|
});
|
|
1273
1289
|
|
|
1274
1290
|
// src/reflection/state.ts
|
|
@@ -1276,16 +1292,12 @@ var ReflectionStateConfig = {
|
|
|
1276
1292
|
/**
|
|
1277
1293
|
* Original user input/task
|
|
1278
1294
|
*/
|
|
1279
|
-
input:
|
|
1280
|
-
schema: z6.string(),
|
|
1281
|
-
default: () => "",
|
|
1282
|
-
description: "Original user input or task"
|
|
1283
|
-
},
|
|
1295
|
+
input: inputField,
|
|
1284
1296
|
/**
|
|
1285
1297
|
* Current response/output
|
|
1286
1298
|
*/
|
|
1287
1299
|
currentResponse: {
|
|
1288
|
-
schema:
|
|
1300
|
+
schema: z7.string().optional(),
|
|
1289
1301
|
description: "Current response or output"
|
|
1290
1302
|
},
|
|
1291
1303
|
/**
|
|
@@ -1293,7 +1305,7 @@ var ReflectionStateConfig = {
|
|
|
1293
1305
|
* Accumulates all reflections
|
|
1294
1306
|
*/
|
|
1295
1307
|
reflections: {
|
|
1296
|
-
schema:
|
|
1308
|
+
schema: z7.array(ReflectionSchema),
|
|
1297
1309
|
reducer: (left, right) => [...left, ...right],
|
|
1298
1310
|
default: () => [],
|
|
1299
1311
|
description: "History of all reflections and critiques"
|
|
@@ -1303,7 +1315,7 @@ var ReflectionStateConfig = {
|
|
|
1303
1315
|
* Accumulates all revisions
|
|
1304
1316
|
*/
|
|
1305
1317
|
revisions: {
|
|
1306
|
-
schema:
|
|
1318
|
+
schema: z7.array(RevisionSchema),
|
|
1307
1319
|
reducer: (left, right) => [...left, ...right],
|
|
1308
1320
|
default: () => [],
|
|
1309
1321
|
description: "History of all revisions"
|
|
@@ -1311,12 +1323,7 @@ var ReflectionStateConfig = {
|
|
|
1311
1323
|
/**
|
|
1312
1324
|
* Current iteration number
|
|
1313
1325
|
*/
|
|
1314
|
-
iteration:
|
|
1315
|
-
schema: z6.number().int().nonnegative(),
|
|
1316
|
-
reducer: (left, right) => left + right,
|
|
1317
|
-
default: () => 0,
|
|
1318
|
-
description: "Current iteration number"
|
|
1319
|
-
},
|
|
1326
|
+
iteration: iterationField,
|
|
1320
1327
|
/**
|
|
1321
1328
|
* Current status
|
|
1322
1329
|
*/
|
|
@@ -1335,25 +1342,15 @@ var ReflectionStateConfig = {
|
|
|
1335
1342
|
/**
|
|
1336
1343
|
* Maximum iterations allowed
|
|
1337
1344
|
*/
|
|
1338
|
-
maxIterations:
|
|
1339
|
-
schema: z6.number().int().positive(),
|
|
1340
|
-
default: () => 3,
|
|
1341
|
-
description: "Maximum number of reflection iterations allowed"
|
|
1342
|
-
},
|
|
1345
|
+
maxIterations: maxIterationsField(3),
|
|
1343
1346
|
/**
|
|
1344
1347
|
* Final response (when completed)
|
|
1345
1348
|
*/
|
|
1346
|
-
response:
|
|
1347
|
-
schema: z6.string().optional(),
|
|
1348
|
-
description: "Final response after reflection process"
|
|
1349
|
-
},
|
|
1349
|
+
response: responseField,
|
|
1350
1350
|
/**
|
|
1351
1351
|
* Error message if failed
|
|
1352
1352
|
*/
|
|
1353
|
-
error:
|
|
1354
|
-
schema: z6.string().optional(),
|
|
1355
|
-
description: "Error message if reflection failed"
|
|
1356
|
-
}
|
|
1353
|
+
error: errorField
|
|
1357
1354
|
};
|
|
1358
1355
|
var ReflectionState = createStateAnnotation3(ReflectionStateConfig);
|
|
1359
1356
|
|
|
@@ -1502,14 +1499,15 @@ ${lastReflection.critique}`;
|
|
|
1502
1499
|
iteration: 1
|
|
1503
1500
|
};
|
|
1504
1501
|
} catch (error) {
|
|
1502
|
+
const errorMessage = handleNodeError(error, "generator", false);
|
|
1505
1503
|
generatorLogger.error("Response generation failed", {
|
|
1506
1504
|
attempt: state.iteration + 1,
|
|
1507
|
-
error:
|
|
1505
|
+
error: errorMessage,
|
|
1508
1506
|
duration: Date.now() - startTime
|
|
1509
1507
|
});
|
|
1510
1508
|
return {
|
|
1511
1509
|
status: "failed",
|
|
1512
|
-
error:
|
|
1510
|
+
error: errorMessage
|
|
1513
1511
|
};
|
|
1514
1512
|
}
|
|
1515
1513
|
};
|
|
@@ -1591,14 +1589,15 @@ function createReflectorNode(config) {
|
|
|
1591
1589
|
status: reflection.meetsStandards ? "completed" : "revising"
|
|
1592
1590
|
};
|
|
1593
1591
|
} catch (error) {
|
|
1592
|
+
const errorMessage = handleNodeError(error, "reflector", false);
|
|
1594
1593
|
reflectorLogger.error("Reflection failed", {
|
|
1595
1594
|
attempt: state.iteration,
|
|
1596
|
-
error:
|
|
1595
|
+
error: errorMessage,
|
|
1597
1596
|
duration: Date.now() - startTime
|
|
1598
1597
|
});
|
|
1599
1598
|
return {
|
|
1600
1599
|
status: "failed",
|
|
1601
|
-
error:
|
|
1600
|
+
error: errorMessage
|
|
1602
1601
|
};
|
|
1603
1602
|
}
|
|
1604
1603
|
};
|
|
@@ -1659,14 +1658,15 @@ ${revisionsText}`;
|
|
|
1659
1658
|
iteration: 1
|
|
1660
1659
|
};
|
|
1661
1660
|
} catch (error) {
|
|
1661
|
+
const errorMessage = handleNodeError(error, "reviser", false);
|
|
1662
1662
|
reviserLogger.error("Revision failed", {
|
|
1663
1663
|
attempt: state.iteration,
|
|
1664
|
-
error:
|
|
1664
|
+
error: errorMessage,
|
|
1665
1665
|
duration: Date.now() - startTime
|
|
1666
1666
|
});
|
|
1667
1667
|
return {
|
|
1668
1668
|
status: "failed",
|
|
1669
|
-
error:
|
|
1669
|
+
error: errorMessage
|
|
1670
1670
|
};
|
|
1671
1671
|
}
|
|
1672
1672
|
};
|
|
@@ -1752,13 +1752,13 @@ function createReflectionAgent(config) {
|
|
|
1752
1752
|
}
|
|
1753
1753
|
|
|
1754
1754
|
// src/multi-agent/state.ts
|
|
1755
|
-
import { z as
|
|
1755
|
+
import { z as z9 } from "zod";
|
|
1756
1756
|
import { createStateAnnotation as createStateAnnotation4 } from "@agentforge/core";
|
|
1757
1757
|
|
|
1758
1758
|
// src/multi-agent/schemas.ts
|
|
1759
|
-
import { z as
|
|
1760
|
-
var AgentRoleSchema =
|
|
1761
|
-
var MessageTypeSchema =
|
|
1759
|
+
import { z as z8 } from "zod";
|
|
1760
|
+
var AgentRoleSchema = z8.enum(["supervisor", "worker"]);
|
|
1761
|
+
var MessageTypeSchema = z8.enum([
|
|
1762
1762
|
"user_input",
|
|
1763
1763
|
// Initial user message
|
|
1764
1764
|
"task_assignment",
|
|
@@ -1772,11 +1772,11 @@ var MessageTypeSchema = z7.enum([
|
|
|
1772
1772
|
"completion"
|
|
1773
1773
|
// Final completion message
|
|
1774
1774
|
]);
|
|
1775
|
-
var AgentMessageSchema =
|
|
1775
|
+
var AgentMessageSchema = z8.object({
|
|
1776
1776
|
/**
|
|
1777
1777
|
* Unique identifier for the message
|
|
1778
1778
|
*/
|
|
1779
|
-
id:
|
|
1779
|
+
id: z8.string().describe("Unique message identifier"),
|
|
1780
1780
|
/**
|
|
1781
1781
|
* Type of message
|
|
1782
1782
|
*/
|
|
@@ -1784,25 +1784,25 @@ var AgentMessageSchema = z7.object({
|
|
|
1784
1784
|
/**
|
|
1785
1785
|
* Agent that sent the message
|
|
1786
1786
|
*/
|
|
1787
|
-
from:
|
|
1787
|
+
from: z8.string().describe("Agent identifier that sent the message"),
|
|
1788
1788
|
/**
|
|
1789
1789
|
* Agent(s) that should receive the message
|
|
1790
1790
|
*/
|
|
1791
|
-
to:
|
|
1791
|
+
to: z8.union([z8.string(), z8.array(z8.string())]).describe("Target agent(s)"),
|
|
1792
1792
|
/**
|
|
1793
1793
|
* Message content
|
|
1794
1794
|
*/
|
|
1795
|
-
content:
|
|
1795
|
+
content: z8.string().describe("Message content"),
|
|
1796
1796
|
/**
|
|
1797
1797
|
* Optional metadata
|
|
1798
1798
|
*/
|
|
1799
|
-
metadata:
|
|
1799
|
+
metadata: z8.record(z8.any()).optional().describe("Additional message metadata"),
|
|
1800
1800
|
/**
|
|
1801
1801
|
* Timestamp when message was created
|
|
1802
1802
|
*/
|
|
1803
|
-
timestamp:
|
|
1803
|
+
timestamp: z8.number().describe("Timestamp when message was created")
|
|
1804
1804
|
});
|
|
1805
|
-
var RoutingStrategySchema =
|
|
1805
|
+
var RoutingStrategySchema = z8.enum([
|
|
1806
1806
|
"llm-based",
|
|
1807
1807
|
// LLM decides which agent to route to
|
|
1808
1808
|
"rule-based",
|
|
@@ -1814,25 +1814,25 @@ var RoutingStrategySchema = z7.enum([
|
|
|
1814
1814
|
"load-balanced"
|
|
1815
1815
|
// Route based on agent workload
|
|
1816
1816
|
]);
|
|
1817
|
-
var RoutingDecisionSchema =
|
|
1817
|
+
var RoutingDecisionSchema = z8.object({
|
|
1818
1818
|
/**
|
|
1819
1819
|
* Target agent to route to (single agent routing)
|
|
1820
1820
|
* @deprecated Use targetAgents for parallel routing support
|
|
1821
1821
|
*/
|
|
1822
|
-
targetAgent:
|
|
1822
|
+
targetAgent: z8.string().nullable().default(null).describe("Agent to route the task to (single routing)"),
|
|
1823
1823
|
/**
|
|
1824
1824
|
* Target agents to route to (parallel routing)
|
|
1825
1825
|
* When multiple agents are specified, they execute in parallel
|
|
1826
1826
|
*/
|
|
1827
|
-
targetAgents:
|
|
1827
|
+
targetAgents: z8.array(z8.string()).nullable().default(null).describe("Agents to route the task to (parallel routing)"),
|
|
1828
1828
|
/**
|
|
1829
1829
|
* Reasoning for the routing decision
|
|
1830
1830
|
*/
|
|
1831
|
-
reasoning:
|
|
1831
|
+
reasoning: z8.string().default("").describe("Explanation for routing decision"),
|
|
1832
1832
|
/**
|
|
1833
1833
|
* Confidence in the routing decision (0-1)
|
|
1834
1834
|
*/
|
|
1835
|
-
confidence:
|
|
1835
|
+
confidence: z8.number().min(0).max(1).default(0.8).describe("Confidence score"),
|
|
1836
1836
|
/**
|
|
1837
1837
|
* Strategy used for routing
|
|
1838
1838
|
*/
|
|
@@ -1840,86 +1840,86 @@ var RoutingDecisionSchema = z7.object({
|
|
|
1840
1840
|
/**
|
|
1841
1841
|
* Timestamp of the routing decision
|
|
1842
1842
|
*/
|
|
1843
|
-
timestamp:
|
|
1843
|
+
timestamp: z8.number().default(() => Date.now()).describe("Timestamp of the decision")
|
|
1844
1844
|
}).refine(
|
|
1845
1845
|
(data) => data.targetAgent || data.targetAgents && data.targetAgents.length > 0,
|
|
1846
1846
|
{ message: "Either targetAgent or targetAgents must be provided" }
|
|
1847
1847
|
);
|
|
1848
|
-
var WorkerCapabilitiesSchema =
|
|
1848
|
+
var WorkerCapabilitiesSchema = z8.object({
|
|
1849
1849
|
/**
|
|
1850
1850
|
* Skills/capabilities the agent has
|
|
1851
1851
|
*/
|
|
1852
|
-
skills:
|
|
1852
|
+
skills: z8.array(z8.string()).describe("List of agent skills"),
|
|
1853
1853
|
/**
|
|
1854
1854
|
* Tools available to the agent
|
|
1855
1855
|
*/
|
|
1856
|
-
tools:
|
|
1856
|
+
tools: z8.array(z8.string()).describe("List of tool names available to agent"),
|
|
1857
1857
|
/**
|
|
1858
1858
|
* Whether the agent is currently available
|
|
1859
1859
|
*/
|
|
1860
|
-
available:
|
|
1860
|
+
available: z8.boolean().default(true).describe("Whether agent is available"),
|
|
1861
1861
|
/**
|
|
1862
1862
|
* Current workload (number of active tasks)
|
|
1863
1863
|
*/
|
|
1864
|
-
currentWorkload:
|
|
1864
|
+
currentWorkload: z8.number().int().nonnegative().default(0).describe("Current number of active tasks")
|
|
1865
1865
|
});
|
|
1866
|
-
var TaskAssignmentSchema =
|
|
1866
|
+
var TaskAssignmentSchema = z8.object({
|
|
1867
1867
|
/**
|
|
1868
1868
|
* Unique assignment identifier
|
|
1869
1869
|
*/
|
|
1870
|
-
id:
|
|
1870
|
+
id: z8.string().describe("Unique assignment identifier"),
|
|
1871
1871
|
/**
|
|
1872
1872
|
* Worker ID assigned to the task
|
|
1873
1873
|
*/
|
|
1874
|
-
workerId:
|
|
1874
|
+
workerId: z8.string().describe("Worker identifier assigned to task"),
|
|
1875
1875
|
/**
|
|
1876
1876
|
* Task description
|
|
1877
1877
|
*/
|
|
1878
|
-
task:
|
|
1878
|
+
task: z8.string().describe("Description of the task"),
|
|
1879
1879
|
/**
|
|
1880
1880
|
* Task priority (1-10, higher is more urgent)
|
|
1881
1881
|
*/
|
|
1882
|
-
priority:
|
|
1882
|
+
priority: z8.number().int().min(1).max(10).default(5).describe("Task priority"),
|
|
1883
1883
|
/**
|
|
1884
1884
|
* Timestamp when task was assigned
|
|
1885
1885
|
*/
|
|
1886
|
-
assignedAt:
|
|
1886
|
+
assignedAt: z8.number().describe("Timestamp when task was assigned"),
|
|
1887
1887
|
/**
|
|
1888
1888
|
* Optional deadline for task completion
|
|
1889
1889
|
*/
|
|
1890
|
-
deadline:
|
|
1890
|
+
deadline: z8.number().optional().describe("Optional task deadline timestamp")
|
|
1891
1891
|
});
|
|
1892
|
-
var TaskResultSchema =
|
|
1892
|
+
var TaskResultSchema = z8.object({
|
|
1893
1893
|
/**
|
|
1894
1894
|
* Assignment identifier
|
|
1895
1895
|
*/
|
|
1896
|
-
assignmentId:
|
|
1896
|
+
assignmentId: z8.string().describe("Assignment identifier"),
|
|
1897
1897
|
/**
|
|
1898
1898
|
* Worker that completed the task
|
|
1899
1899
|
*/
|
|
1900
|
-
workerId:
|
|
1900
|
+
workerId: z8.string().describe("Worker that completed the task"),
|
|
1901
1901
|
/**
|
|
1902
1902
|
* Whether the task succeeded
|
|
1903
1903
|
*/
|
|
1904
|
-
success:
|
|
1904
|
+
success: z8.boolean().describe("Whether the task succeeded"),
|
|
1905
1905
|
/**
|
|
1906
1906
|
* Task result/output
|
|
1907
1907
|
*/
|
|
1908
|
-
result:
|
|
1908
|
+
result: z8.string().describe("Task result or output"),
|
|
1909
1909
|
/**
|
|
1910
1910
|
* Optional error message if task failed
|
|
1911
1911
|
*/
|
|
1912
|
-
error:
|
|
1912
|
+
error: z8.string().optional().describe("Error message if task failed"),
|
|
1913
1913
|
/**
|
|
1914
1914
|
* Timestamp when task was completed
|
|
1915
1915
|
*/
|
|
1916
|
-
completedAt:
|
|
1916
|
+
completedAt: z8.number().describe("Timestamp when task was completed"),
|
|
1917
1917
|
/**
|
|
1918
1918
|
* Optional metadata about execution
|
|
1919
1919
|
*/
|
|
1920
|
-
metadata:
|
|
1920
|
+
metadata: z8.record(z8.any()).optional().describe("Execution metadata")
|
|
1921
1921
|
});
|
|
1922
|
-
var MultiAgentStatusSchema =
|
|
1922
|
+
var MultiAgentStatusSchema = z8.enum([
|
|
1923
1923
|
"initializing",
|
|
1924
1924
|
// System is initializing
|
|
1925
1925
|
"routing",
|
|
@@ -1935,27 +1935,27 @@ var MultiAgentStatusSchema = z7.enum([
|
|
|
1935
1935
|
"failed"
|
|
1936
1936
|
// Task failed
|
|
1937
1937
|
]);
|
|
1938
|
-
var HandoffRequestSchema =
|
|
1938
|
+
var HandoffRequestSchema = z8.object({
|
|
1939
1939
|
/**
|
|
1940
1940
|
* Agent requesting the handoff
|
|
1941
1941
|
*/
|
|
1942
|
-
from:
|
|
1942
|
+
from: z8.string().describe("Agent requesting handoff"),
|
|
1943
1943
|
/**
|
|
1944
1944
|
* Target agent for handoff
|
|
1945
1945
|
*/
|
|
1946
|
-
to:
|
|
1946
|
+
to: z8.string().describe("Target agent for handoff"),
|
|
1947
1947
|
/**
|
|
1948
1948
|
* Reason for handoff
|
|
1949
1949
|
*/
|
|
1950
|
-
reason:
|
|
1950
|
+
reason: z8.string().describe("Reason for requesting handoff"),
|
|
1951
1951
|
/**
|
|
1952
1952
|
* Context to pass to next agent
|
|
1953
1953
|
*/
|
|
1954
|
-
context:
|
|
1954
|
+
context: z8.any().describe("Context to pass to next agent"),
|
|
1955
1955
|
/**
|
|
1956
1956
|
* Timestamp of handoff request
|
|
1957
1957
|
*/
|
|
1958
|
-
timestamp:
|
|
1958
|
+
timestamp: z8.string().datetime().describe("ISO timestamp of handoff request")
|
|
1959
1959
|
});
|
|
1960
1960
|
|
|
1961
1961
|
// src/multi-agent/state.ts
|
|
@@ -1963,17 +1963,13 @@ var MultiAgentStateConfig = {
|
|
|
1963
1963
|
/**
|
|
1964
1964
|
* Original user input/query
|
|
1965
1965
|
*/
|
|
1966
|
-
input:
|
|
1967
|
-
schema: z8.string(),
|
|
1968
|
-
default: () => "",
|
|
1969
|
-
description: "Original user input or query"
|
|
1970
|
-
},
|
|
1966
|
+
input: inputField,
|
|
1971
1967
|
/**
|
|
1972
1968
|
* All messages in the multi-agent conversation
|
|
1973
1969
|
* Accumulates all messages between agents
|
|
1974
1970
|
*/
|
|
1975
1971
|
messages: {
|
|
1976
|
-
schema:
|
|
1972
|
+
schema: z9.array(AgentMessageSchema),
|
|
1977
1973
|
reducer: (left, right) => [...left, ...right],
|
|
1978
1974
|
default: () => [],
|
|
1979
1975
|
description: "All messages in the multi-agent conversation"
|
|
@@ -1982,7 +1978,7 @@ var MultiAgentStateConfig = {
|
|
|
1982
1978
|
* Available worker agents and their capabilities
|
|
1983
1979
|
*/
|
|
1984
1980
|
workers: {
|
|
1985
|
-
schema:
|
|
1981
|
+
schema: z9.record(z9.string(), WorkerCapabilitiesSchema),
|
|
1986
1982
|
reducer: (left, right) => ({
|
|
1987
1983
|
...left,
|
|
1988
1984
|
...right
|
|
@@ -1994,7 +1990,7 @@ var MultiAgentStateConfig = {
|
|
|
1994
1990
|
* Current active agent
|
|
1995
1991
|
*/
|
|
1996
1992
|
currentAgent: {
|
|
1997
|
-
schema:
|
|
1993
|
+
schema: z9.string().optional(),
|
|
1998
1994
|
description: "Identifier of the currently active agent"
|
|
1999
1995
|
},
|
|
2000
1996
|
/**
|
|
@@ -2002,7 +1998,7 @@ var MultiAgentStateConfig = {
|
|
|
2002
1998
|
* Accumulates all routing decisions
|
|
2003
1999
|
*/
|
|
2004
2000
|
routingHistory: {
|
|
2005
|
-
schema:
|
|
2001
|
+
schema: z9.array(RoutingDecisionSchema),
|
|
2006
2002
|
reducer: (left, right) => [...left, ...right],
|
|
2007
2003
|
default: () => [],
|
|
2008
2004
|
description: "History of routing decisions"
|
|
@@ -2011,7 +2007,7 @@ var MultiAgentStateConfig = {
|
|
|
2011
2007
|
* Active task assignments
|
|
2012
2008
|
*/
|
|
2013
2009
|
activeAssignments: {
|
|
2014
|
-
schema:
|
|
2010
|
+
schema: z9.array(TaskAssignmentSchema),
|
|
2015
2011
|
reducer: (left, right) => [...left, ...right],
|
|
2016
2012
|
default: () => [],
|
|
2017
2013
|
description: "Currently active task assignments"
|
|
@@ -2021,7 +2017,7 @@ var MultiAgentStateConfig = {
|
|
|
2021
2017
|
* Accumulates all completed tasks
|
|
2022
2018
|
*/
|
|
2023
2019
|
completedTasks: {
|
|
2024
|
-
schema:
|
|
2020
|
+
schema: z9.array(TaskResultSchema),
|
|
2025
2021
|
reducer: (left, right) => [...left, ...right],
|
|
2026
2022
|
default: () => [],
|
|
2027
2023
|
description: "Completed task results"
|
|
@@ -2031,7 +2027,7 @@ var MultiAgentStateConfig = {
|
|
|
2031
2027
|
* Accumulates all handoff requests
|
|
2032
2028
|
*/
|
|
2033
2029
|
handoffs: {
|
|
2034
|
-
schema:
|
|
2030
|
+
schema: z9.array(HandoffRequestSchema),
|
|
2035
2031
|
reducer: (left, right) => [...left, ...right],
|
|
2036
2032
|
default: () => [],
|
|
2037
2033
|
description: "Handoff requests between agents"
|
|
@@ -2047,99 +2043,24 @@ var MultiAgentStateConfig = {
|
|
|
2047
2043
|
/**
|
|
2048
2044
|
* Iteration counter
|
|
2049
2045
|
*/
|
|
2050
|
-
iteration:
|
|
2051
|
-
schema: z8.number().int().nonnegative(),
|
|
2052
|
-
reducer: (left, right) => left + right,
|
|
2053
|
-
default: () => 0,
|
|
2054
|
-
description: "Current iteration number"
|
|
2055
|
-
},
|
|
2046
|
+
iteration: iterationField,
|
|
2056
2047
|
/**
|
|
2057
2048
|
* Maximum iterations allowed
|
|
2058
2049
|
*/
|
|
2059
|
-
maxIterations:
|
|
2060
|
-
schema: z8.number().int().positive(),
|
|
2061
|
-
default: () => 10,
|
|
2062
|
-
description: "Maximum number of iterations allowed"
|
|
2063
|
-
},
|
|
2050
|
+
maxIterations: maxIterationsField(10),
|
|
2064
2051
|
/**
|
|
2065
2052
|
* Final aggregated response
|
|
2066
2053
|
*/
|
|
2067
|
-
response:
|
|
2068
|
-
schema: z8.string().optional(),
|
|
2069
|
-
description: "Final aggregated response"
|
|
2070
|
-
},
|
|
2054
|
+
response: responseField,
|
|
2071
2055
|
/**
|
|
2072
2056
|
* Error message if execution failed
|
|
2073
2057
|
*/
|
|
2074
|
-
error:
|
|
2075
|
-
schema: z8.string().optional(),
|
|
2076
|
-
description: "Error message if execution failed"
|
|
2077
|
-
}
|
|
2058
|
+
error: errorField
|
|
2078
2059
|
};
|
|
2079
2060
|
var MultiAgentState = createStateAnnotation4(MultiAgentStateConfig);
|
|
2080
2061
|
|
|
2081
2062
|
// src/multi-agent/routing.ts
|
|
2082
|
-
import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4
|
|
2083
|
-
import { createLogger as createLogger2, LogLevel } from "@agentforge/core";
|
|
2084
|
-
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
2085
|
-
var logger = createLogger2("multi-agent:routing", { level: logLevel });
|
|
2086
|
-
async function executeTools(toolCalls, tools) {
|
|
2087
|
-
const results = [];
|
|
2088
|
-
logger.debug("Executing tools", {
|
|
2089
|
-
toolCallCount: toolCalls.length,
|
|
2090
|
-
toolNames: toolCalls.map((tc) => tc.name)
|
|
2091
|
-
});
|
|
2092
|
-
for (const toolCall of toolCalls) {
|
|
2093
|
-
const tool = tools.find((t) => t.metadata.name === toolCall.name);
|
|
2094
|
-
if (!tool) {
|
|
2095
|
-
logger.warn("Tool not found", {
|
|
2096
|
-
toolName: toolCall.name,
|
|
2097
|
-
availableTools: tools.map((t) => t.metadata.name)
|
|
2098
|
-
});
|
|
2099
|
-
results.push(new ToolMessage2({
|
|
2100
|
-
content: `Error: Tool '${toolCall.name}' not found`,
|
|
2101
|
-
tool_call_id: toolCall.id
|
|
2102
|
-
}));
|
|
2103
|
-
continue;
|
|
2104
|
-
}
|
|
2105
|
-
try {
|
|
2106
|
-
logger.debug("Executing tool", {
|
|
2107
|
-
toolName: toolCall.name,
|
|
2108
|
-
args: toolCall.args
|
|
2109
|
-
});
|
|
2110
|
-
const result = await tool.execute(toolCall.args);
|
|
2111
|
-
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
2112
|
-
logger.debug("Tool execution successful", {
|
|
2113
|
-
toolName: toolCall.name,
|
|
2114
|
-
resultLength: content.length
|
|
2115
|
-
});
|
|
2116
|
-
results.push(new ToolMessage2({
|
|
2117
|
-
content,
|
|
2118
|
-
tool_call_id: toolCall.id
|
|
2119
|
-
}));
|
|
2120
|
-
} catch (error) {
|
|
2121
|
-
logger.error("Tool execution failed", {
|
|
2122
|
-
toolName: toolCall.name,
|
|
2123
|
-
error: error.message
|
|
2124
|
-
});
|
|
2125
|
-
results.push(new ToolMessage2({
|
|
2126
|
-
content: `Error executing tool: ${error.message}`,
|
|
2127
|
-
tool_call_id: toolCall.id
|
|
2128
|
-
}));
|
|
2129
|
-
}
|
|
2130
|
-
}
|
|
2131
|
-
logger.debug("Tool execution complete", {
|
|
2132
|
-
successCount: results.filter((r) => {
|
|
2133
|
-
const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
|
|
2134
|
-
return !content.startsWith("Error");
|
|
2135
|
-
}).length,
|
|
2136
|
-
errorCount: results.filter((r) => {
|
|
2137
|
-
const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
|
|
2138
|
-
return content.startsWith("Error");
|
|
2139
|
-
}).length
|
|
2140
|
-
});
|
|
2141
|
-
return results;
|
|
2142
|
-
}
|
|
2063
|
+
import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4 } from "@langchain/core/messages";
|
|
2143
2064
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
2144
2065
|
|
|
2145
2066
|
Your job is to:
|
|
@@ -2175,151 +2096,48 @@ Choose parallel routing when the task benefits from multiple perspectives or dat
|
|
|
2175
2096
|
var llmBasedRouting = {
|
|
2176
2097
|
name: "llm-based",
|
|
2177
2098
|
async route(state, config) {
|
|
2178
|
-
logger.info("Starting LLM-based routing", {
|
|
2179
|
-
iteration: state.iteration,
|
|
2180
|
-
availableWorkers: Object.keys(state.workers).length
|
|
2181
|
-
});
|
|
2182
2099
|
if (!config.model) {
|
|
2183
2100
|
throw new Error("LLM-based routing requires a model to be configured");
|
|
2184
2101
|
}
|
|
2185
2102
|
const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
|
|
2186
|
-
const maxRetries = config.maxToolRetries || 3;
|
|
2187
|
-
const tools = config.tools || [];
|
|
2188
2103
|
const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
|
|
2189
2104
|
const skills = caps.skills.join(", ");
|
|
2190
|
-
const
|
|
2105
|
+
const tools = caps.tools.join(", ");
|
|
2191
2106
|
const available = caps.available ? "available" : "busy";
|
|
2192
|
-
return `- ${id}: Skills: [${skills}], Tools: [${
|
|
2107
|
+
return `- ${id}: Skills: [${skills}], Tools: [${tools}], Status: ${available}, Workload: ${caps.currentWorkload}`;
|
|
2193
2108
|
}).join("\n");
|
|
2194
|
-
logger.debug("Worker capabilities", {
|
|
2195
|
-
workers: Object.entries(state.workers).map(([id, caps]) => ({
|
|
2196
|
-
id,
|
|
2197
|
-
skills: caps.skills,
|
|
2198
|
-
available: caps.available,
|
|
2199
|
-
workload: caps.currentWorkload
|
|
2200
|
-
}))
|
|
2201
|
-
});
|
|
2202
2109
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
2203
2110
|
const taskContext = lastMessage?.content || state.input;
|
|
2204
|
-
logger.debug("Task context", {
|
|
2205
|
-
taskLength: taskContext.length,
|
|
2206
|
-
taskPreview: taskContext.substring(0, 100)
|
|
2207
|
-
});
|
|
2208
2111
|
const userPrompt = `Current task: ${taskContext}
|
|
2209
2112
|
|
|
2210
2113
|
Available workers:
|
|
2211
2114
|
${workerInfo}
|
|
2212
2115
|
|
|
2213
2116
|
Select the best worker(s) for this task and explain your reasoning.`;
|
|
2214
|
-
const
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
const response = await config.model.invoke(messages);
|
|
2228
|
-
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
2229
|
-
logger.info("LLM requested tool calls", {
|
|
2230
|
-
toolCount: response.tool_calls.length,
|
|
2231
|
-
toolNames: response.tool_calls.map((tc) => tc.name)
|
|
2232
|
-
});
|
|
2233
|
-
if (tools.length === 0) {
|
|
2234
|
-
throw new Error("LLM requested tool calls but no tools are configured");
|
|
2235
|
-
}
|
|
2236
|
-
const toolResults = await executeTools(response.tool_calls, tools);
|
|
2237
|
-
conversationHistory.push(
|
|
2238
|
-
new AIMessage2({ content: response.content || "", tool_calls: response.tool_calls }),
|
|
2239
|
-
...toolResults
|
|
2240
|
-
);
|
|
2241
|
-
attempt++;
|
|
2242
|
-
logger.debug("Retrying routing with tool results", { attempt });
|
|
2243
|
-
continue;
|
|
2244
|
-
}
|
|
2245
|
-
logger.debug("Parsing routing decision from LLM response");
|
|
2246
|
-
let decision;
|
|
2247
|
-
if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
|
|
2248
|
-
logger.debug("Response is structured output", {
|
|
2249
|
-
hasTargetAgent: "targetAgent" in response,
|
|
2250
|
-
hasTargetAgents: "targetAgents" in response
|
|
2251
|
-
});
|
|
2252
|
-
decision = response;
|
|
2253
|
-
} else if (response.content) {
|
|
2254
|
-
if (typeof response.content === "string") {
|
|
2255
|
-
try {
|
|
2256
|
-
decision = JSON.parse(response.content);
|
|
2257
|
-
logger.debug("Parsed JSON from string response");
|
|
2258
|
-
} catch (error) {
|
|
2259
|
-
logger.error("Failed to parse routing decision", {
|
|
2260
|
-
content: response.content,
|
|
2261
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2262
|
-
});
|
|
2263
|
-
throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
|
|
2264
|
-
}
|
|
2265
|
-
} else if (typeof response.content === "object") {
|
|
2266
|
-
logger.debug("Response content is already an object");
|
|
2267
|
-
decision = response.content;
|
|
2268
|
-
} else {
|
|
2269
|
-
logger.error("Unexpected response content type", {
|
|
2270
|
-
type: typeof response.content
|
|
2271
|
-
});
|
|
2272
|
-
throw new Error(`Unexpected response content type: ${typeof response.content}`);
|
|
2273
|
-
}
|
|
2274
|
-
} else {
|
|
2275
|
-
logger.error("Unexpected response format", {
|
|
2276
|
-
response: JSON.stringify(response)
|
|
2277
|
-
});
|
|
2278
|
-
throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
|
|
2279
|
-
}
|
|
2280
|
-
const result = {
|
|
2281
|
-
targetAgent: decision.targetAgent,
|
|
2282
|
-
targetAgents: decision.targetAgents,
|
|
2283
|
-
reasoning: decision.reasoning,
|
|
2284
|
-
confidence: decision.confidence,
|
|
2285
|
-
strategy: "llm-based",
|
|
2286
|
-
timestamp: Date.now()
|
|
2287
|
-
};
|
|
2288
|
-
logger.info("LLM routing decision made", {
|
|
2289
|
-
targetAgent: result.targetAgent,
|
|
2290
|
-
targetAgents: result.targetAgents,
|
|
2291
|
-
isParallel: result.targetAgents && result.targetAgents.length > 1,
|
|
2292
|
-
confidence: result.confidence,
|
|
2293
|
-
reasoning: result.reasoning
|
|
2294
|
-
});
|
|
2295
|
-
return result;
|
|
2296
|
-
}
|
|
2297
|
-
logger.error("Max tool retries exceeded", { maxRetries });
|
|
2298
|
-
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
2117
|
+
const messages = [
|
|
2118
|
+
new SystemMessage4(systemPrompt),
|
|
2119
|
+
new HumanMessage4(userPrompt)
|
|
2120
|
+
];
|
|
2121
|
+
const decision = await config.model.invoke(messages);
|
|
2122
|
+
return {
|
|
2123
|
+
targetAgent: decision.targetAgent,
|
|
2124
|
+
targetAgents: decision.targetAgents,
|
|
2125
|
+
reasoning: decision.reasoning,
|
|
2126
|
+
confidence: decision.confidence,
|
|
2127
|
+
strategy: "llm-based",
|
|
2128
|
+
timestamp: Date.now()
|
|
2129
|
+
};
|
|
2299
2130
|
}
|
|
2300
2131
|
};
|
|
2301
2132
|
var roundRobinRouting = {
|
|
2302
2133
|
name: "round-robin",
|
|
2303
2134
|
async route(state, config) {
|
|
2304
|
-
logger.info("Starting round-robin routing", {
|
|
2305
|
-
iteration: state.iteration
|
|
2306
|
-
});
|
|
2307
2135
|
const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
|
|
2308
|
-
logger.debug("Available workers for round-robin", {
|
|
2309
|
-
count: availableWorkers.length,
|
|
2310
|
-
workers: availableWorkers
|
|
2311
|
-
});
|
|
2312
2136
|
if (availableWorkers.length === 0) {
|
|
2313
|
-
logger.error("No available workers for round-robin routing");
|
|
2314
2137
|
throw new Error("No available workers for round-robin routing");
|
|
2315
2138
|
}
|
|
2316
2139
|
const lastRoutingIndex = state.routingHistory.length % availableWorkers.length;
|
|
2317
2140
|
const targetAgent = availableWorkers[lastRoutingIndex];
|
|
2318
|
-
logger.info("Round-robin routing decision", {
|
|
2319
|
-
targetAgent,
|
|
2320
|
-
index: lastRoutingIndex + 1,
|
|
2321
|
-
totalWorkers: availableWorkers.length
|
|
2322
|
-
});
|
|
2323
2141
|
return {
|
|
2324
2142
|
targetAgent,
|
|
2325
2143
|
targetAgents: null,
|
|
@@ -2333,15 +2151,8 @@ var roundRobinRouting = {
|
|
|
2333
2151
|
var skillBasedRouting = {
|
|
2334
2152
|
name: "skill-based",
|
|
2335
2153
|
async route(state, config) {
|
|
2336
|
-
logger.info("Starting skill-based routing", {
|
|
2337
|
-
iteration: state.iteration
|
|
2338
|
-
});
|
|
2339
2154
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
2340
2155
|
const taskContent = (lastMessage?.content || state.input).toLowerCase();
|
|
2341
|
-
logger.debug("Task content for skill matching", {
|
|
2342
|
-
taskLength: taskContent.length,
|
|
2343
|
-
taskPreview: taskContent.substring(0, 100)
|
|
2344
|
-
});
|
|
2345
2156
|
const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
|
|
2346
2157
|
const skillMatches = caps.skills.filter(
|
|
2347
2158
|
(skill) => taskContent.includes(skill.toLowerCase())
|
|
@@ -2352,20 +2163,11 @@ var skillBasedRouting = {
|
|
|
2352
2163
|
const score = skillMatches * 2 + toolMatches;
|
|
2353
2164
|
return { id, score, skills: caps.skills, tools: caps.tools };
|
|
2354
2165
|
}).filter((w) => w.score > 0).sort((a, b) => b.score - a.score);
|
|
2355
|
-
logger.debug("Worker skill scores", {
|
|
2356
|
-
scoredWorkers: workerScores.map((w) => ({ id: w.id, score: w.score }))
|
|
2357
|
-
});
|
|
2358
2166
|
if (workerScores.length === 0) {
|
|
2359
|
-
logger.warn("No skill matches found, using fallback");
|
|
2360
2167
|
const firstAvailable = Object.entries(state.workers).find(([_, caps]) => caps.available);
|
|
2361
2168
|
if (!firstAvailable) {
|
|
2362
|
-
logger.error("No available workers for skill-based routing");
|
|
2363
2169
|
throw new Error("No available workers for skill-based routing");
|
|
2364
2170
|
}
|
|
2365
|
-
logger.info("Skill-based routing fallback decision", {
|
|
2366
|
-
targetAgent: firstAvailable[0],
|
|
2367
|
-
confidence: 0.5
|
|
2368
|
-
});
|
|
2369
2171
|
return {
|
|
2370
2172
|
targetAgent: firstAvailable[0],
|
|
2371
2173
|
targetAgents: null,
|
|
@@ -2377,12 +2179,6 @@ var skillBasedRouting = {
|
|
|
2377
2179
|
}
|
|
2378
2180
|
const best = workerScores[0];
|
|
2379
2181
|
const confidence = Math.min(best.score / 5, 1);
|
|
2380
|
-
logger.info("Skill-based routing decision", {
|
|
2381
|
-
targetAgent: best.id,
|
|
2382
|
-
score: best.score,
|
|
2383
|
-
confidence,
|
|
2384
|
-
matchedSkills: best.skills
|
|
2385
|
-
});
|
|
2386
2182
|
return {
|
|
2387
2183
|
targetAgent: best.id,
|
|
2388
2184
|
targetAgents: null,
|
|
@@ -2396,26 +2192,13 @@ var skillBasedRouting = {
|
|
|
2396
2192
|
var loadBalancedRouting = {
|
|
2397
2193
|
name: "load-balanced",
|
|
2398
2194
|
async route(state, config) {
|
|
2399
|
-
logger.info("Starting load-balanced routing", {
|
|
2400
|
-
iteration: state.iteration
|
|
2401
|
-
});
|
|
2402
2195
|
const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
|
|
2403
|
-
logger.debug("Worker workloads", {
|
|
2404
|
-
workers: availableWorkers.map((w) => ({ id: w.id, workload: w.workload }))
|
|
2405
|
-
});
|
|
2406
2196
|
if (availableWorkers.length === 0) {
|
|
2407
|
-
logger.error("No available workers for load-balanced routing");
|
|
2408
2197
|
throw new Error("No available workers for load-balanced routing");
|
|
2409
2198
|
}
|
|
2410
2199
|
const targetWorker = availableWorkers[0];
|
|
2411
2200
|
const avgWorkload = availableWorkers.reduce((sum, w) => sum + w.workload, 0) / availableWorkers.length;
|
|
2412
2201
|
const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
|
|
2413
|
-
logger.info("Load-balanced routing decision", {
|
|
2414
|
-
targetAgent: targetWorker.id,
|
|
2415
|
-
workload: targetWorker.workload,
|
|
2416
|
-
avgWorkload: avgWorkload.toFixed(1),
|
|
2417
|
-
confidence
|
|
2418
|
-
});
|
|
2419
2202
|
return {
|
|
2420
2203
|
targetAgent: targetWorker.id,
|
|
2421
2204
|
targetAgents: null,
|
|
@@ -2429,24 +2212,13 @@ var loadBalancedRouting = {
|
|
|
2429
2212
|
var ruleBasedRouting = {
|
|
2430
2213
|
name: "rule-based",
|
|
2431
2214
|
async route(state, config) {
|
|
2432
|
-
logger.info("Starting rule-based routing", {
|
|
2433
|
-
iteration: state.iteration
|
|
2434
|
-
});
|
|
2435
2215
|
if (!config.routingFn) {
|
|
2436
|
-
logger.error("Rule-based routing requires a custom routing function");
|
|
2437
2216
|
throw new Error("Rule-based routing requires a custom routing function");
|
|
2438
2217
|
}
|
|
2439
|
-
|
|
2440
|
-
logger.info("Rule-based routing decision", {
|
|
2441
|
-
targetAgent: decision.targetAgent,
|
|
2442
|
-
targetAgents: decision.targetAgents,
|
|
2443
|
-
confidence: decision.confidence
|
|
2444
|
-
});
|
|
2445
|
-
return decision;
|
|
2218
|
+
return await config.routingFn(state);
|
|
2446
2219
|
}
|
|
2447
2220
|
};
|
|
2448
2221
|
function getRoutingStrategy(name) {
|
|
2449
|
-
logger.debug("Getting routing strategy", { name });
|
|
2450
2222
|
switch (name) {
|
|
2451
2223
|
case "llm-based":
|
|
2452
2224
|
return llmBasedRouting;
|
|
@@ -2459,15 +2231,14 @@ function getRoutingStrategy(name) {
|
|
|
2459
2231
|
case "rule-based":
|
|
2460
2232
|
return ruleBasedRouting;
|
|
2461
2233
|
default:
|
|
2462
|
-
logger.error("Unknown routing strategy", { name });
|
|
2463
2234
|
throw new Error(`Unknown routing strategy: ${name}`);
|
|
2464
2235
|
}
|
|
2465
2236
|
}
|
|
2466
2237
|
|
|
2467
2238
|
// src/multi-agent/utils.ts
|
|
2468
|
-
import { createLogger as
|
|
2469
|
-
var
|
|
2470
|
-
var
|
|
2239
|
+
import { createLogger as createLogger2, LogLevel } from "@agentforge/core";
|
|
2240
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
2241
|
+
var logger = createLogger2("multi-agent", { level: logLevel });
|
|
2471
2242
|
function isReActAgent(obj) {
|
|
2472
2243
|
return obj && typeof obj === "object" && typeof obj.invoke === "function" && typeof obj.stream === "function" && // Additional check to ensure it's not just any object with invoke/stream
|
|
2473
2244
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
@@ -2475,9 +2246,9 @@ function isReActAgent(obj) {
|
|
|
2475
2246
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2476
2247
|
return async (state, config) => {
|
|
2477
2248
|
try {
|
|
2478
|
-
|
|
2249
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2479
2250
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2480
|
-
|
|
2251
|
+
logger.debug("Extracted task", {
|
|
2481
2252
|
workerId,
|
|
2482
2253
|
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2483
2254
|
});
|
|
@@ -2485,7 +2256,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2485
2256
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2486
2257
|
);
|
|
2487
2258
|
if (!currentAssignment) {
|
|
2488
|
-
|
|
2259
|
+
logger.debug("No active assignment found", { workerId });
|
|
2489
2260
|
return {};
|
|
2490
2261
|
}
|
|
2491
2262
|
const result = await agent.invoke(
|
|
@@ -2496,14 +2267,14 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2496
2267
|
// Pass through the config for checkpointing and interrupt support
|
|
2497
2268
|
);
|
|
2498
2269
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2499
|
-
|
|
2270
|
+
logger.debug("Received response from ReAct agent", {
|
|
2500
2271
|
workerId,
|
|
2501
2272
|
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2502
2273
|
});
|
|
2503
2274
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2504
2275
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2505
2276
|
if (uniqueTools.length > 0) {
|
|
2506
|
-
|
|
2277
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2507
2278
|
}
|
|
2508
2279
|
const taskResult = {
|
|
2509
2280
|
assignmentId: currentAssignment.id,
|
|
@@ -2521,14 +2292,10 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2521
2292
|
completedTasks: [taskResult]
|
|
2522
2293
|
};
|
|
2523
2294
|
} catch (error) {
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
throw error;
|
|
2527
|
-
}
|
|
2528
|
-
logger2.error("Error in ReAct agent execution", {
|
|
2295
|
+
const errorMessage = handleNodeError(error, `react-agent:${workerId}`, false);
|
|
2296
|
+
logger.error("Error in ReAct agent execution", {
|
|
2529
2297
|
workerId,
|
|
2530
|
-
error:
|
|
2531
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
2298
|
+
error: errorMessage
|
|
2532
2299
|
});
|
|
2533
2300
|
const currentAssignment = state.activeAssignments.find(
|
|
2534
2301
|
(assignment) => assignment.workerId === workerId
|
|
@@ -2539,7 +2306,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2539
2306
|
workerId,
|
|
2540
2307
|
success: false,
|
|
2541
2308
|
result: "",
|
|
2542
|
-
error:
|
|
2309
|
+
error: errorMessage,
|
|
2543
2310
|
completedAt: Date.now()
|
|
2544
2311
|
};
|
|
2545
2312
|
return {
|
|
@@ -2550,7 +2317,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2550
2317
|
}
|
|
2551
2318
|
return {
|
|
2552
2319
|
status: "failed",
|
|
2553
|
-
error:
|
|
2320
|
+
error: errorMessage
|
|
2554
2321
|
};
|
|
2555
2322
|
}
|
|
2556
2323
|
};
|
|
@@ -2558,9 +2325,9 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2558
2325
|
|
|
2559
2326
|
// src/multi-agent/nodes.ts
|
|
2560
2327
|
import { HumanMessage as HumanMessage5, SystemMessage as SystemMessage5 } from "@langchain/core/messages";
|
|
2561
|
-
import { toLangChainTools as toLangChainTools2, createLogger as
|
|
2562
|
-
var
|
|
2563
|
-
var
|
|
2328
|
+
import { toLangChainTools as toLangChainTools2, createLogger as createLogger3, LogLevel as LogLevel2 } from "@agentforge/core";
|
|
2329
|
+
var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel2.INFO;
|
|
2330
|
+
var logger2 = createLogger3("multi-agent:nodes", { level: logLevel2 });
|
|
2564
2331
|
var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
|
|
2565
2332
|
|
|
2566
2333
|
Your job is to:
|
|
@@ -2578,19 +2345,19 @@ function createSupervisorNode(config) {
|
|
|
2578
2345
|
} = config;
|
|
2579
2346
|
return async (state) => {
|
|
2580
2347
|
try {
|
|
2581
|
-
|
|
2348
|
+
logger2.info("Supervisor node executing", {
|
|
2582
2349
|
iteration: state.iteration,
|
|
2583
2350
|
maxIterations,
|
|
2584
2351
|
activeAssignments: state.activeAssignments.length,
|
|
2585
2352
|
completedTasks: state.completedTasks.length
|
|
2586
2353
|
});
|
|
2587
|
-
|
|
2354
|
+
logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
|
|
2588
2355
|
if (state.iteration >= maxIterations) {
|
|
2589
|
-
|
|
2356
|
+
logger2.warn("Max iterations reached", {
|
|
2590
2357
|
iteration: state.iteration,
|
|
2591
2358
|
maxIterations
|
|
2592
2359
|
});
|
|
2593
|
-
|
|
2360
|
+
logger2.debug("Max iterations reached, moving to aggregation");
|
|
2594
2361
|
return {
|
|
2595
2362
|
status: "aggregating",
|
|
2596
2363
|
currentAgent: "aggregator"
|
|
@@ -2599,26 +2366,26 @@ function createSupervisorNode(config) {
|
|
|
2599
2366
|
const allCompleted = state.activeAssignments.every(
|
|
2600
2367
|
(assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2601
2368
|
);
|
|
2602
|
-
|
|
2369
|
+
logger2.debug("Checking task completion", {
|
|
2603
2370
|
activeAssignments: state.activeAssignments.length,
|
|
2604
2371
|
completedTasks: state.completedTasks.length,
|
|
2605
2372
|
allCompleted
|
|
2606
2373
|
});
|
|
2607
2374
|
if (allCompleted && state.activeAssignments.length > 0) {
|
|
2608
|
-
|
|
2375
|
+
logger2.info("All tasks completed, moving to aggregation", {
|
|
2609
2376
|
completedCount: state.completedTasks.length
|
|
2610
2377
|
});
|
|
2611
|
-
|
|
2378
|
+
logger2.debug("All tasks completed, moving to aggregation");
|
|
2612
2379
|
return {
|
|
2613
2380
|
status: "aggregating",
|
|
2614
2381
|
currentAgent: "aggregator"
|
|
2615
2382
|
};
|
|
2616
2383
|
}
|
|
2617
|
-
|
|
2384
|
+
logger2.debug("Getting routing strategy", { strategy });
|
|
2618
2385
|
const routingImpl = getRoutingStrategy(strategy);
|
|
2619
2386
|
const decision = await routingImpl.route(state, config);
|
|
2620
2387
|
const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
|
|
2621
|
-
|
|
2388
|
+
logger2.debug("Target agents determined", {
|
|
2622
2389
|
targetAgents,
|
|
2623
2390
|
isParallel: targetAgents.length > 1,
|
|
2624
2391
|
decision: {
|
|
@@ -2627,17 +2394,17 @@ function createSupervisorNode(config) {
|
|
|
2627
2394
|
}
|
|
2628
2395
|
});
|
|
2629
2396
|
if (targetAgents.length === 0) {
|
|
2630
|
-
|
|
2397
|
+
logger2.error("No target agents specified in routing decision");
|
|
2631
2398
|
throw new Error("Routing decision must specify at least one target agent");
|
|
2632
2399
|
}
|
|
2633
2400
|
if (targetAgents.length === 1) {
|
|
2634
|
-
|
|
2401
|
+
logger2.info("Routing to single agent", {
|
|
2635
2402
|
targetAgent: targetAgents[0],
|
|
2636
2403
|
reasoning: decision.reasoning,
|
|
2637
2404
|
confidence: decision.confidence
|
|
2638
2405
|
});
|
|
2639
2406
|
} else {
|
|
2640
|
-
|
|
2407
|
+
logger2.info("Routing to multiple agents in parallel", {
|
|
2641
2408
|
targetAgents,
|
|
2642
2409
|
count: targetAgents.length,
|
|
2643
2410
|
reasoning: decision.reasoning,
|
|
@@ -2645,9 +2412,9 @@ function createSupervisorNode(config) {
|
|
|
2645
2412
|
});
|
|
2646
2413
|
}
|
|
2647
2414
|
if (targetAgents.length === 1) {
|
|
2648
|
-
|
|
2415
|
+
logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
|
|
2649
2416
|
} else {
|
|
2650
|
-
|
|
2417
|
+
logger2.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
|
|
2651
2418
|
}
|
|
2652
2419
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2653
2420
|
const assignments = targetAgents.map((workerId) => ({
|
|
@@ -2657,7 +2424,7 @@ function createSupervisorNode(config) {
|
|
|
2657
2424
|
priority: 5,
|
|
2658
2425
|
assignedAt: Date.now()
|
|
2659
2426
|
}));
|
|
2660
|
-
|
|
2427
|
+
logger2.debug("Created task assignments", {
|
|
2661
2428
|
assignmentCount: assignments.length,
|
|
2662
2429
|
assignments: assignments.map((a) => ({
|
|
2663
2430
|
id: a.id,
|
|
@@ -2677,7 +2444,7 @@ function createSupervisorNode(config) {
|
|
|
2677
2444
|
priority: assignment.priority
|
|
2678
2445
|
}
|
|
2679
2446
|
}));
|
|
2680
|
-
|
|
2447
|
+
logger2.info("Supervisor routing complete", {
|
|
2681
2448
|
currentAgent: targetAgents.join(","),
|
|
2682
2449
|
status: "executing",
|
|
2683
2450
|
assignmentCount: assignments.length,
|
|
@@ -2694,7 +2461,7 @@ function createSupervisorNode(config) {
|
|
|
2694
2461
|
iteration: state.iteration + 1
|
|
2695
2462
|
};
|
|
2696
2463
|
} catch (error) {
|
|
2697
|
-
|
|
2464
|
+
logger2.error("Supervisor node error", {
|
|
2698
2465
|
error: error instanceof Error ? error.message : String(error),
|
|
2699
2466
|
stack: error instanceof Error ? error.stack : void 0,
|
|
2700
2467
|
iteration: state.iteration
|
|
@@ -2719,7 +2486,7 @@ function createWorkerNode(config) {
|
|
|
2719
2486
|
} = config;
|
|
2720
2487
|
return async (state, runConfig) => {
|
|
2721
2488
|
try {
|
|
2722
|
-
|
|
2489
|
+
logger2.info("Worker node executing", {
|
|
2723
2490
|
workerId: id,
|
|
2724
2491
|
iteration: state.iteration,
|
|
2725
2492
|
activeAssignments: state.activeAssignments.length
|
|
@@ -2728,39 +2495,39 @@ function createWorkerNode(config) {
|
|
|
2728
2495
|
(assignment) => assignment.workerId === id && !state.completedTasks.some((task) => task.assignmentId === assignment.id)
|
|
2729
2496
|
);
|
|
2730
2497
|
if (!currentAssignment) {
|
|
2731
|
-
|
|
2498
|
+
logger2.debug("No active assignment found for worker", {
|
|
2732
2499
|
workerId: id,
|
|
2733
2500
|
totalActiveAssignments: state.activeAssignments.length,
|
|
2734
2501
|
completedTasks: state.completedTasks.length
|
|
2735
2502
|
});
|
|
2736
2503
|
return {};
|
|
2737
2504
|
}
|
|
2738
|
-
|
|
2505
|
+
logger2.info("Worker processing assignment", {
|
|
2739
2506
|
workerId: id,
|
|
2740
2507
|
assignmentId: currentAssignment.id,
|
|
2741
2508
|
taskLength: currentAssignment.task.length,
|
|
2742
2509
|
taskPreview: currentAssignment.task.substring(0, 100)
|
|
2743
2510
|
});
|
|
2744
2511
|
if (executeFn) {
|
|
2745
|
-
|
|
2512
|
+
logger2.debug("Using custom execution function", { workerId: id });
|
|
2746
2513
|
return await executeFn(state, runConfig);
|
|
2747
2514
|
}
|
|
2748
2515
|
if (agent) {
|
|
2749
2516
|
if (isReActAgent(agent)) {
|
|
2750
|
-
|
|
2517
|
+
logger2.debug("Using ReAct agent", { workerId: id });
|
|
2751
2518
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2752
2519
|
return await wrappedFn(state, runConfig);
|
|
2753
2520
|
} else {
|
|
2754
|
-
|
|
2521
|
+
logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
|
|
2755
2522
|
}
|
|
2756
2523
|
}
|
|
2757
2524
|
if (!model) {
|
|
2758
|
-
|
|
2525
|
+
logger2.error("Worker missing required configuration", { workerId: id });
|
|
2759
2526
|
throw new Error(
|
|
2760
2527
|
`Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
|
|
2761
2528
|
);
|
|
2762
2529
|
}
|
|
2763
|
-
|
|
2530
|
+
logger2.debug("Using default LLM execution", {
|
|
2764
2531
|
workerId: id,
|
|
2765
2532
|
hasTools: tools.length > 0,
|
|
2766
2533
|
toolCount: tools.length
|
|
@@ -2776,7 +2543,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2776
2543
|
];
|
|
2777
2544
|
let modelToUse = model;
|
|
2778
2545
|
if (tools.length > 0 && model.bindTools) {
|
|
2779
|
-
|
|
2546
|
+
logger2.debug("Binding tools to model", {
|
|
2780
2547
|
workerId: id,
|
|
2781
2548
|
toolCount: tools.length,
|
|
2782
2549
|
toolNames: tools.map((t) => t.metadata.name)
|
|
@@ -2784,10 +2551,10 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2784
2551
|
const langchainTools = toLangChainTools2(tools);
|
|
2785
2552
|
modelToUse = model.bindTools(langchainTools);
|
|
2786
2553
|
}
|
|
2787
|
-
|
|
2554
|
+
logger2.debug("Invoking LLM", { workerId: id });
|
|
2788
2555
|
const response = await modelToUse.invoke(messages);
|
|
2789
2556
|
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2790
|
-
|
|
2557
|
+
logger2.info("Worker task completed", {
|
|
2791
2558
|
workerId: id,
|
|
2792
2559
|
assignmentId: currentAssignment.id,
|
|
2793
2560
|
resultLength: result.length,
|
|
@@ -2822,7 +2589,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2822
2589
|
currentWorkload: Math.max(0, capabilities.currentWorkload - 1)
|
|
2823
2590
|
}
|
|
2824
2591
|
};
|
|
2825
|
-
|
|
2592
|
+
logger2.debug("Worker state update", {
|
|
2826
2593
|
workerId: id,
|
|
2827
2594
|
newWorkload: updatedWorkers[id].currentWorkload
|
|
2828
2595
|
});
|
|
@@ -2832,20 +2599,16 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2832
2599
|
workers: updatedWorkers
|
|
2833
2600
|
};
|
|
2834
2601
|
} catch (error) {
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
throw error;
|
|
2838
|
-
}
|
|
2839
|
-
logger3.error("Worker node error", {
|
|
2602
|
+
const errorMessage = handleNodeError(error, `worker:${id}`, false);
|
|
2603
|
+
logger2.error("Worker node error", {
|
|
2840
2604
|
workerId: id,
|
|
2841
|
-
error:
|
|
2842
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
2605
|
+
error: errorMessage
|
|
2843
2606
|
});
|
|
2844
2607
|
const currentAssignment = state.activeAssignments.find(
|
|
2845
2608
|
(assignment) => assignment.workerId === id
|
|
2846
2609
|
);
|
|
2847
2610
|
if (currentAssignment) {
|
|
2848
|
-
|
|
2611
|
+
logger2.warn("Creating error result for assignment", {
|
|
2849
2612
|
workerId: id,
|
|
2850
2613
|
assignmentId: currentAssignment.id
|
|
2851
2614
|
});
|
|
@@ -2854,7 +2617,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2854
2617
|
workerId: id,
|
|
2855
2618
|
success: false,
|
|
2856
2619
|
result: "",
|
|
2857
|
-
error:
|
|
2620
|
+
error: errorMessage,
|
|
2858
2621
|
completedAt: Date.now()
|
|
2859
2622
|
};
|
|
2860
2623
|
return {
|
|
@@ -2863,10 +2626,10 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2863
2626
|
status: "routing"
|
|
2864
2627
|
};
|
|
2865
2628
|
}
|
|
2866
|
-
|
|
2629
|
+
logger2.error("No assignment found for error handling", { workerId: id });
|
|
2867
2630
|
return {
|
|
2868
2631
|
status: "failed",
|
|
2869
|
-
error:
|
|
2632
|
+
error: errorMessage
|
|
2870
2633
|
};
|
|
2871
2634
|
}
|
|
2872
2635
|
};
|
|
@@ -2880,16 +2643,16 @@ function createAggregatorNode(config = {}) {
|
|
|
2880
2643
|
} = config;
|
|
2881
2644
|
return async (state) => {
|
|
2882
2645
|
try {
|
|
2883
|
-
|
|
2646
|
+
logger2.info("Aggregator node executing", {
|
|
2884
2647
|
completedTasks: state.completedTasks.length,
|
|
2885
2648
|
successfulTasks: state.completedTasks.filter((t) => t.success).length,
|
|
2886
2649
|
failedTasks: state.completedTasks.filter((t) => !t.success).length
|
|
2887
2650
|
});
|
|
2888
|
-
|
|
2651
|
+
logger2.debug("Combining results from workers");
|
|
2889
2652
|
if (aggregateFn) {
|
|
2890
|
-
|
|
2653
|
+
logger2.debug("Using custom aggregation function");
|
|
2891
2654
|
const response2 = await aggregateFn(state);
|
|
2892
|
-
|
|
2655
|
+
logger2.info("Custom aggregation complete", {
|
|
2893
2656
|
responseLength: response2.length
|
|
2894
2657
|
});
|
|
2895
2658
|
return {
|
|
@@ -2898,16 +2661,16 @@ function createAggregatorNode(config = {}) {
|
|
|
2898
2661
|
};
|
|
2899
2662
|
}
|
|
2900
2663
|
if (state.completedTasks.length === 0) {
|
|
2901
|
-
|
|
2664
|
+
logger2.warn("No completed tasks to aggregate");
|
|
2902
2665
|
return {
|
|
2903
2666
|
response: "No tasks were completed.",
|
|
2904
2667
|
status: "completed"
|
|
2905
2668
|
};
|
|
2906
2669
|
}
|
|
2907
2670
|
if (!model) {
|
|
2908
|
-
|
|
2671
|
+
logger2.debug("No model provided, concatenating results");
|
|
2909
2672
|
const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
|
|
2910
|
-
|
|
2673
|
+
logger2.info("Simple concatenation complete", {
|
|
2911
2674
|
resultLength: combinedResults.length
|
|
2912
2675
|
});
|
|
2913
2676
|
return {
|
|
@@ -2915,7 +2678,7 @@ function createAggregatorNode(config = {}) {
|
|
|
2915
2678
|
status: "completed"
|
|
2916
2679
|
};
|
|
2917
2680
|
}
|
|
2918
|
-
|
|
2681
|
+
logger2.debug("Using LLM for intelligent aggregation", {
|
|
2919
2682
|
taskCount: state.completedTasks.length
|
|
2920
2683
|
});
|
|
2921
2684
|
const taskResults = state.completedTasks.map((task, idx) => {
|
|
@@ -2934,20 +2697,20 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2934
2697
|
new SystemMessage5(systemPrompt),
|
|
2935
2698
|
new HumanMessage5(userPrompt)
|
|
2936
2699
|
];
|
|
2937
|
-
|
|
2700
|
+
logger2.debug("Invoking aggregation LLM");
|
|
2938
2701
|
const response = await model.invoke(messages);
|
|
2939
2702
|
const aggregatedResponse = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2940
|
-
|
|
2703
|
+
logger2.info("Aggregation complete", {
|
|
2941
2704
|
responseLength: aggregatedResponse.length,
|
|
2942
2705
|
responsePreview: aggregatedResponse.substring(0, 100)
|
|
2943
2706
|
});
|
|
2944
|
-
|
|
2707
|
+
logger2.debug("Aggregation complete");
|
|
2945
2708
|
return {
|
|
2946
2709
|
response: aggregatedResponse,
|
|
2947
2710
|
status: "completed"
|
|
2948
2711
|
};
|
|
2949
2712
|
} catch (error) {
|
|
2950
|
-
|
|
2713
|
+
logger2.error("Aggregator node error", {
|
|
2951
2714
|
error: error instanceof Error ? error.message : String(error),
|
|
2952
2715
|
stack: error instanceof Error ? error.stack : void 0,
|
|
2953
2716
|
completedTasks: state.completedTasks.length
|
|
@@ -2962,9 +2725,9 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2962
2725
|
|
|
2963
2726
|
// src/multi-agent/agent.ts
|
|
2964
2727
|
import { StateGraph as StateGraph4, END as END4 } from "@langchain/langgraph";
|
|
2965
|
-
import {
|
|
2966
|
-
var
|
|
2967
|
-
var
|
|
2728
|
+
import { createLogger as createLogger4, LogLevel as LogLevel3 } from "@agentforge/core";
|
|
2729
|
+
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel3.INFO;
|
|
2730
|
+
var logger3 = createLogger4("multi-agent:system", { level: logLevel3 });
|
|
2968
2731
|
function createMultiAgentSystem(config) {
|
|
2969
2732
|
const {
|
|
2970
2733
|
supervisor,
|
|
@@ -2981,10 +2744,6 @@ function createMultiAgentSystem(config) {
|
|
|
2981
2744
|
if (supervisor.strategy === "llm-based") {
|
|
2982
2745
|
configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
|
|
2983
2746
|
}
|
|
2984
|
-
if (supervisor.tools && supervisor.tools.length > 0) {
|
|
2985
|
-
const langchainTools = toLangChainTools3(supervisor.tools);
|
|
2986
|
-
configuredModel = configuredModel.bindTools(langchainTools);
|
|
2987
|
-
}
|
|
2988
2747
|
supervisorConfig.model = configuredModel;
|
|
2989
2748
|
}
|
|
2990
2749
|
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
@@ -3006,46 +2765,46 @@ function createMultiAgentSystem(config) {
|
|
|
3006
2765
|
});
|
|
3007
2766
|
workflow.addNode("aggregator", aggregatorNode);
|
|
3008
2767
|
const supervisorRouter = (state) => {
|
|
3009
|
-
|
|
2768
|
+
logger3.debug("Supervisor router executing", {
|
|
3010
2769
|
status: state.status,
|
|
3011
2770
|
currentAgent: state.currentAgent,
|
|
3012
2771
|
iteration: state.iteration
|
|
3013
2772
|
});
|
|
3014
2773
|
if (state.status === "completed" || state.status === "failed") {
|
|
3015
|
-
|
|
2774
|
+
logger3.info("Supervisor router: ending workflow", { status: state.status });
|
|
3016
2775
|
return END4;
|
|
3017
2776
|
}
|
|
3018
2777
|
if (state.status === "aggregating") {
|
|
3019
|
-
|
|
2778
|
+
logger3.info("Supervisor router: routing to aggregator");
|
|
3020
2779
|
return "aggregator";
|
|
3021
2780
|
}
|
|
3022
2781
|
if (state.currentAgent && state.currentAgent !== "supervisor") {
|
|
3023
2782
|
if (state.currentAgent.includes(",")) {
|
|
3024
2783
|
const agents = state.currentAgent.split(",").map((a) => a.trim());
|
|
3025
|
-
|
|
2784
|
+
logger3.info("Supervisor router: parallel routing", {
|
|
3026
2785
|
agents,
|
|
3027
2786
|
count: agents.length
|
|
3028
2787
|
});
|
|
3029
2788
|
return agents;
|
|
3030
2789
|
}
|
|
3031
|
-
|
|
2790
|
+
logger3.info("Supervisor router: single agent routing", {
|
|
3032
2791
|
targetAgent: state.currentAgent
|
|
3033
2792
|
});
|
|
3034
2793
|
return state.currentAgent;
|
|
3035
2794
|
}
|
|
3036
|
-
|
|
2795
|
+
logger3.debug("Supervisor router: staying at supervisor");
|
|
3037
2796
|
return "supervisor";
|
|
3038
2797
|
};
|
|
3039
2798
|
const workerRouter = (state) => {
|
|
3040
|
-
|
|
2799
|
+
logger3.debug("Worker router executing", {
|
|
3041
2800
|
iteration: state.iteration,
|
|
3042
2801
|
completedTasks: state.completedTasks.length
|
|
3043
2802
|
});
|
|
3044
|
-
|
|
2803
|
+
logger3.debug("Worker router: returning to supervisor");
|
|
3045
2804
|
return "supervisor";
|
|
3046
2805
|
};
|
|
3047
2806
|
const aggregatorRouter = (state) => {
|
|
3048
|
-
|
|
2807
|
+
logger3.info("Aggregator router: ending workflow", {
|
|
3049
2808
|
completedTasks: state.completedTasks.length,
|
|
3050
2809
|
status: state.status
|
|
3051
2810
|
});
|