@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.cjs
CHANGED
|
@@ -138,15 +138,46 @@ var ScratchpadEntrySchema = import_zod.z.object({
|
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
// src/react/state.ts
|
|
141
|
-
var
|
|
141
|
+
var import_zod3 = require("zod");
|
|
142
142
|
var import_core = require("@agentforge/core");
|
|
143
|
+
|
|
144
|
+
// src/shared/state-fields.ts
|
|
145
|
+
var import_zod2 = require("zod");
|
|
146
|
+
var iterationField = {
|
|
147
|
+
schema: import_zod2.z.number().int().nonnegative(),
|
|
148
|
+
reducer: (left, right) => left + right,
|
|
149
|
+
default: () => 0,
|
|
150
|
+
description: "Current iteration number"
|
|
151
|
+
};
|
|
152
|
+
function maxIterationsField(defaultValue) {
|
|
153
|
+
return {
|
|
154
|
+
schema: import_zod2.z.number().int().positive(),
|
|
155
|
+
default: () => defaultValue,
|
|
156
|
+
description: "Maximum number of iterations allowed"
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
var errorField = {
|
|
160
|
+
schema: import_zod2.z.string().optional(),
|
|
161
|
+
description: "Error message if execution failed"
|
|
162
|
+
};
|
|
163
|
+
var responseField = {
|
|
164
|
+
schema: import_zod2.z.string().optional(),
|
|
165
|
+
description: "Final response after completion"
|
|
166
|
+
};
|
|
167
|
+
var inputField = {
|
|
168
|
+
schema: import_zod2.z.string(),
|
|
169
|
+
default: () => "",
|
|
170
|
+
description: "Original user input or query"
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/react/state.ts
|
|
143
174
|
var ReActStateConfig = {
|
|
144
175
|
/**
|
|
145
176
|
* Conversation messages
|
|
146
177
|
* Accumulates all messages in the conversation
|
|
147
178
|
*/
|
|
148
179
|
messages: {
|
|
149
|
-
schema:
|
|
180
|
+
schema: import_zod3.z.array(MessageSchema),
|
|
150
181
|
reducer: (left, right) => [...left, ...right],
|
|
151
182
|
default: () => [],
|
|
152
183
|
description: "Conversation message history"
|
|
@@ -156,7 +187,7 @@ var ReActStateConfig = {
|
|
|
156
187
|
* Accumulates all reasoning steps the agent takes
|
|
157
188
|
*/
|
|
158
189
|
thoughts: {
|
|
159
|
-
schema:
|
|
190
|
+
schema: import_zod3.z.array(ThoughtSchema),
|
|
160
191
|
reducer: (left, right) => [...left, ...right],
|
|
161
192
|
default: () => [],
|
|
162
193
|
description: "Agent reasoning steps"
|
|
@@ -166,7 +197,7 @@ var ReActStateConfig = {
|
|
|
166
197
|
* Accumulates all tool calls made by the agent
|
|
167
198
|
*/
|
|
168
199
|
actions: {
|
|
169
|
-
schema:
|
|
200
|
+
schema: import_zod3.z.array(ToolCallSchema),
|
|
170
201
|
reducer: (left, right) => [...left, ...right],
|
|
171
202
|
default: () => [],
|
|
172
203
|
description: "Tool calls made by the agent"
|
|
@@ -176,7 +207,7 @@ var ReActStateConfig = {
|
|
|
176
207
|
* Accumulates all observations from tool executions
|
|
177
208
|
*/
|
|
178
209
|
observations: {
|
|
179
|
-
schema:
|
|
210
|
+
schema: import_zod3.z.array(ToolResultSchema),
|
|
180
211
|
reducer: (left, right) => [...left, ...right],
|
|
181
212
|
default: () => [],
|
|
182
213
|
description: "Results from tool executions"
|
|
@@ -186,7 +217,7 @@ var ReActStateConfig = {
|
|
|
186
217
|
* Accumulates step-by-step reasoning process
|
|
187
218
|
*/
|
|
188
219
|
scratchpad: {
|
|
189
|
-
schema:
|
|
220
|
+
schema: import_zod3.z.array(ScratchpadEntrySchema),
|
|
190
221
|
reducer: (left, right) => [...left, ...right],
|
|
191
222
|
default: () => [],
|
|
192
223
|
description: "Intermediate reasoning scratchpad"
|
|
@@ -195,27 +226,19 @@ var ReActStateConfig = {
|
|
|
195
226
|
* Current iteration count
|
|
196
227
|
* Tracks how many thought-action-observation loops have been executed
|
|
197
228
|
*/
|
|
198
|
-
iteration:
|
|
199
|
-
schema: import_zod2.z.number(),
|
|
200
|
-
reducer: (left, right) => left + right,
|
|
201
|
-
default: () => 0,
|
|
202
|
-
description: "Current iteration count"
|
|
203
|
-
},
|
|
229
|
+
iteration: iterationField,
|
|
204
230
|
/**
|
|
205
231
|
* Whether the agent should continue iterating
|
|
206
232
|
*/
|
|
207
233
|
shouldContinue: {
|
|
208
|
-
schema:
|
|
234
|
+
schema: import_zod3.z.boolean().optional(),
|
|
209
235
|
default: () => true,
|
|
210
236
|
description: "Whether to continue the ReAct loop"
|
|
211
237
|
},
|
|
212
238
|
/**
|
|
213
239
|
* Final response (if any)
|
|
214
240
|
*/
|
|
215
|
-
response:
|
|
216
|
-
schema: import_zod2.z.string().optional(),
|
|
217
|
-
description: "Final response from the agent"
|
|
218
|
-
}
|
|
241
|
+
response: responseField
|
|
219
242
|
};
|
|
220
243
|
var ReActState = (0, import_core.createStateAnnotation)(ReActStateConfig);
|
|
221
244
|
|
|
@@ -260,8 +283,8 @@ function generateToolCallCacheKey(toolName, args) {
|
|
|
260
283
|
return `${toolName}:${sortedArgs}`;
|
|
261
284
|
}
|
|
262
285
|
function createPatternLogger(name, defaultLevel = "info") {
|
|
263
|
-
const
|
|
264
|
-
return (0, import_core2.createLogger)(name, { level:
|
|
286
|
+
const logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
|
|
287
|
+
return (0, import_core2.createLogger)(name, { level: logLevel4 });
|
|
265
288
|
}
|
|
266
289
|
function calculateDeduplicationSavings(duplicatesSkipped, toolsExecuted) {
|
|
267
290
|
if (duplicatesSkipped === 0) {
|
|
@@ -279,6 +302,24 @@ function buildDeduplicationMetrics(toolsExecuted, duplicatesSkipped, totalObserv
|
|
|
279
302
|
};
|
|
280
303
|
}
|
|
281
304
|
|
|
305
|
+
// src/shared/error-handling.ts
|
|
306
|
+
function isGraphInterrupt(error) {
|
|
307
|
+
return error !== null && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt";
|
|
308
|
+
}
|
|
309
|
+
function handleNodeError(error, context, verbose = false) {
|
|
310
|
+
if (isGraphInterrupt(error)) {
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
314
|
+
if (verbose) {
|
|
315
|
+
console.error(`[${context}] Error:`, errorMessage);
|
|
316
|
+
if (error instanceof Error && error.stack) {
|
|
317
|
+
console.error(`[${context}] Stack:`, error.stack);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return errorMessage;
|
|
321
|
+
}
|
|
322
|
+
|
|
282
323
|
// src/react/nodes.ts
|
|
283
324
|
var reasoningLogger = createPatternLogger("agentforge:patterns:react:reasoning");
|
|
284
325
|
var actionLogger = createPatternLogger("agentforge:patterns:react:action");
|
|
@@ -441,10 +482,7 @@ function createActionNode(tools, verbose = false, enableDeduplication = true) {
|
|
|
441
482
|
executionCache.set(cacheKey, observation);
|
|
442
483
|
}
|
|
443
484
|
} catch (error) {
|
|
444
|
-
|
|
445
|
-
throw error;
|
|
446
|
-
}
|
|
447
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
485
|
+
const errorMessage = handleNodeError(error, `action:${action.name}`, false);
|
|
448
486
|
actionLogger.error("Tool execution failed", {
|
|
449
487
|
toolName: action.name,
|
|
450
488
|
error: errorMessage,
|
|
@@ -683,34 +721,34 @@ function createReActAgentBuilder() {
|
|
|
683
721
|
var import_langgraph2 = require("@langchain/langgraph");
|
|
684
722
|
|
|
685
723
|
// src/plan-execute/state.ts
|
|
686
|
-
var
|
|
724
|
+
var import_zod5 = require("zod");
|
|
687
725
|
var import_core5 = require("@agentforge/core");
|
|
688
726
|
|
|
689
727
|
// src/plan-execute/schemas.ts
|
|
690
|
-
var
|
|
691
|
-
var PlanStepSchema =
|
|
728
|
+
var import_zod4 = require("zod");
|
|
729
|
+
var PlanStepSchema = import_zod4.z.object({
|
|
692
730
|
/**
|
|
693
731
|
* Unique identifier for the step
|
|
694
732
|
*/
|
|
695
|
-
id:
|
|
733
|
+
id: import_zod4.z.string().describe("Unique identifier for the step"),
|
|
696
734
|
/**
|
|
697
735
|
* Description of what this step should accomplish
|
|
698
736
|
*/
|
|
699
|
-
description:
|
|
737
|
+
description: import_zod4.z.string().describe("Description of what this step should accomplish"),
|
|
700
738
|
/**
|
|
701
739
|
* Optional dependencies on other steps (by ID)
|
|
702
740
|
*/
|
|
703
|
-
dependencies:
|
|
741
|
+
dependencies: import_zod4.z.array(import_zod4.z.string()).optional().describe("IDs of steps that must complete before this one"),
|
|
704
742
|
/**
|
|
705
743
|
* Optional tool to use for this step
|
|
706
744
|
*/
|
|
707
|
-
tool:
|
|
745
|
+
tool: import_zod4.z.string().optional().describe("Name of the tool to use for this step"),
|
|
708
746
|
/**
|
|
709
747
|
* Optional arguments for the tool
|
|
710
748
|
*/
|
|
711
|
-
args:
|
|
749
|
+
args: import_zod4.z.record(import_zod4.z.any()).optional().describe("Arguments to pass to the tool")
|
|
712
750
|
});
|
|
713
|
-
var CompletedStepSchema =
|
|
751
|
+
var CompletedStepSchema = import_zod4.z.object({
|
|
714
752
|
/**
|
|
715
753
|
* The step that was executed
|
|
716
754
|
*/
|
|
@@ -718,53 +756,53 @@ var CompletedStepSchema = import_zod3.z.object({
|
|
|
718
756
|
/**
|
|
719
757
|
* The result of executing the step
|
|
720
758
|
*/
|
|
721
|
-
result:
|
|
759
|
+
result: import_zod4.z.any().describe("The result of executing the step"),
|
|
722
760
|
/**
|
|
723
761
|
* Whether the step succeeded
|
|
724
762
|
*/
|
|
725
|
-
success:
|
|
763
|
+
success: import_zod4.z.boolean().describe("Whether the step succeeded"),
|
|
726
764
|
/**
|
|
727
765
|
* Optional error message if the step failed
|
|
728
766
|
*/
|
|
729
|
-
error:
|
|
767
|
+
error: import_zod4.z.string().optional().describe("Error message if the step failed"),
|
|
730
768
|
/**
|
|
731
769
|
* Timestamp when the step was completed
|
|
732
770
|
*/
|
|
733
|
-
timestamp:
|
|
771
|
+
timestamp: import_zod4.z.string().datetime().describe("ISO timestamp when the step was completed")
|
|
734
772
|
});
|
|
735
|
-
var PlanSchema =
|
|
773
|
+
var PlanSchema = import_zod4.z.object({
|
|
736
774
|
/**
|
|
737
775
|
* List of steps in the plan
|
|
738
776
|
*/
|
|
739
|
-
steps:
|
|
777
|
+
steps: import_zod4.z.array(PlanStepSchema).describe("List of steps in the plan"),
|
|
740
778
|
/**
|
|
741
779
|
* Overall goal of the plan
|
|
742
780
|
*/
|
|
743
|
-
goal:
|
|
781
|
+
goal: import_zod4.z.string().describe("Overall goal of the plan"),
|
|
744
782
|
/**
|
|
745
783
|
* Timestamp when the plan was created
|
|
746
784
|
*/
|
|
747
|
-
createdAt:
|
|
785
|
+
createdAt: import_zod4.z.string().datetime().describe("ISO timestamp when the plan was created"),
|
|
748
786
|
/**
|
|
749
787
|
* Optional confidence score (0-1)
|
|
750
788
|
*/
|
|
751
|
-
confidence:
|
|
789
|
+
confidence: import_zod4.z.number().min(0).max(1).optional().describe("Confidence score for the plan (0-1)")
|
|
752
790
|
});
|
|
753
|
-
var ReplanDecisionSchema =
|
|
791
|
+
var ReplanDecisionSchema = import_zod4.z.object({
|
|
754
792
|
/**
|
|
755
793
|
* Whether to replan
|
|
756
794
|
*/
|
|
757
|
-
shouldReplan:
|
|
795
|
+
shouldReplan: import_zod4.z.boolean().describe("Whether to replan based on current results"),
|
|
758
796
|
/**
|
|
759
797
|
* Reason for the decision
|
|
760
798
|
*/
|
|
761
|
-
reason:
|
|
799
|
+
reason: import_zod4.z.string().describe("Reason for the replan decision"),
|
|
762
800
|
/**
|
|
763
801
|
* Optional new goal if replanning
|
|
764
802
|
*/
|
|
765
|
-
newGoal:
|
|
803
|
+
newGoal: import_zod4.z.string().optional().describe("Updated goal if replanning")
|
|
766
804
|
});
|
|
767
|
-
var ExecutionStatusSchema =
|
|
805
|
+
var ExecutionStatusSchema = import_zod4.z.enum([
|
|
768
806
|
"planning",
|
|
769
807
|
"executing",
|
|
770
808
|
"replanning",
|
|
@@ -777,11 +815,7 @@ var PlanExecuteStateConfig = {
|
|
|
777
815
|
/**
|
|
778
816
|
* Original user input/query
|
|
779
817
|
*/
|
|
780
|
-
input:
|
|
781
|
-
schema: import_zod4.z.string(),
|
|
782
|
-
default: () => "",
|
|
783
|
-
description: "Original user input or query"
|
|
784
|
-
},
|
|
818
|
+
input: inputField,
|
|
785
819
|
/**
|
|
786
820
|
* The current plan
|
|
787
821
|
*/
|
|
@@ -794,7 +828,7 @@ var PlanExecuteStateConfig = {
|
|
|
794
828
|
* Accumulates all completed steps
|
|
795
829
|
*/
|
|
796
830
|
pastSteps: {
|
|
797
|
-
schema:
|
|
831
|
+
schema: import_zod5.z.array(CompletedStepSchema),
|
|
798
832
|
reducer: (left, right) => [...left, ...right],
|
|
799
833
|
default: () => [],
|
|
800
834
|
description: "Completed steps with their results"
|
|
@@ -803,7 +837,7 @@ var PlanExecuteStateConfig = {
|
|
|
803
837
|
* Index of the current step being executed
|
|
804
838
|
*/
|
|
805
839
|
currentStepIndex: {
|
|
806
|
-
schema:
|
|
840
|
+
schema: import_zod5.z.number().int().nonnegative().optional(),
|
|
807
841
|
description: "Index of the current step being executed"
|
|
808
842
|
},
|
|
809
843
|
/**
|
|
@@ -817,34 +851,19 @@ var PlanExecuteStateConfig = {
|
|
|
817
851
|
/**
|
|
818
852
|
* Final response
|
|
819
853
|
*/
|
|
820
|
-
response:
|
|
821
|
-
schema: import_zod4.z.string().optional(),
|
|
822
|
-
description: "Final response after plan execution"
|
|
823
|
-
},
|
|
854
|
+
response: responseField,
|
|
824
855
|
/**
|
|
825
856
|
* Error message if execution failed
|
|
826
857
|
*/
|
|
827
|
-
error:
|
|
828
|
-
schema: import_zod4.z.string().optional(),
|
|
829
|
-
description: "Error message if execution failed"
|
|
830
|
-
},
|
|
858
|
+
error: errorField,
|
|
831
859
|
/**
|
|
832
860
|
* Iteration counter for replanning
|
|
833
861
|
*/
|
|
834
|
-
iteration:
|
|
835
|
-
schema: import_zod4.z.number().int().nonnegative(),
|
|
836
|
-
reducer: (left, right) => left + right,
|
|
837
|
-
default: () => 0,
|
|
838
|
-
description: "Number of planning iterations"
|
|
839
|
-
},
|
|
862
|
+
iteration: iterationField,
|
|
840
863
|
/**
|
|
841
864
|
* Maximum iterations allowed
|
|
842
865
|
*/
|
|
843
|
-
maxIterations:
|
|
844
|
-
schema: import_zod4.z.number().int().positive(),
|
|
845
|
-
default: () => 5,
|
|
846
|
-
description: "Maximum number of planning iterations allowed"
|
|
847
|
-
}
|
|
866
|
+
maxIterations: maxIterationsField(5)
|
|
848
867
|
};
|
|
849
868
|
var PlanExecuteState = (0, import_core5.createStateAnnotation)(PlanExecuteStateConfig);
|
|
850
869
|
|
|
@@ -1077,11 +1096,8 @@ function createExecutorNode(config) {
|
|
|
1077
1096
|
result = { message: "Step completed without tool execution" };
|
|
1078
1097
|
}
|
|
1079
1098
|
} catch (execError) {
|
|
1080
|
-
|
|
1081
|
-
throw execError;
|
|
1082
|
-
}
|
|
1099
|
+
error = handleNodeError(execError, `executor:${currentStep.description}`, false);
|
|
1083
1100
|
success = false;
|
|
1084
|
-
error = execError instanceof Error ? execError.message : "Unknown execution error";
|
|
1085
1101
|
result = null;
|
|
1086
1102
|
executorLogger.warn("Step execution failed", {
|
|
1087
1103
|
stepId: currentStep.id,
|
|
@@ -1284,46 +1300,46 @@ function createPlanExecuteAgent(config) {
|
|
|
1284
1300
|
}
|
|
1285
1301
|
|
|
1286
1302
|
// src/reflection/state.ts
|
|
1287
|
-
var
|
|
1303
|
+
var import_zod7 = require("zod");
|
|
1288
1304
|
var import_core6 = require("@agentforge/core");
|
|
1289
1305
|
|
|
1290
1306
|
// src/reflection/schemas.ts
|
|
1291
|
-
var
|
|
1292
|
-
var ReflectionSchema =
|
|
1307
|
+
var import_zod6 = require("zod");
|
|
1308
|
+
var ReflectionSchema = import_zod6.z.object({
|
|
1293
1309
|
/**
|
|
1294
1310
|
* The critique or feedback on the current response
|
|
1295
1311
|
*/
|
|
1296
|
-
critique:
|
|
1312
|
+
critique: import_zod6.z.string().describe("Critique or feedback on the current response"),
|
|
1297
1313
|
/**
|
|
1298
1314
|
* Specific issues identified
|
|
1299
1315
|
*/
|
|
1300
|
-
issues:
|
|
1316
|
+
issues: import_zod6.z.array(import_zod6.z.string()).describe("Specific issues or problems identified"),
|
|
1301
1317
|
/**
|
|
1302
1318
|
* Suggestions for improvement
|
|
1303
1319
|
*/
|
|
1304
|
-
suggestions:
|
|
1320
|
+
suggestions: import_zod6.z.array(import_zod6.z.string()).describe("Suggestions for improving the response"),
|
|
1305
1321
|
/**
|
|
1306
1322
|
* Quality score (0-10)
|
|
1307
1323
|
*/
|
|
1308
|
-
score:
|
|
1324
|
+
score: import_zod6.z.number().min(0).max(10).optional().describe("Quality score from 0 to 10"),
|
|
1309
1325
|
/**
|
|
1310
1326
|
* Whether the response meets quality standards
|
|
1311
1327
|
*/
|
|
1312
|
-
meetsStandards:
|
|
1328
|
+
meetsStandards: import_zod6.z.boolean().describe("Whether the response meets quality standards"),
|
|
1313
1329
|
/**
|
|
1314
1330
|
* Timestamp of the reflection
|
|
1315
1331
|
*/
|
|
1316
|
-
timestamp:
|
|
1332
|
+
timestamp: import_zod6.z.date().optional().describe("When this reflection was created")
|
|
1317
1333
|
});
|
|
1318
|
-
var RevisionSchema =
|
|
1334
|
+
var RevisionSchema = import_zod6.z.object({
|
|
1319
1335
|
/**
|
|
1320
1336
|
* The revised content
|
|
1321
1337
|
*/
|
|
1322
|
-
content:
|
|
1338
|
+
content: import_zod6.z.string().describe("The revised content"),
|
|
1323
1339
|
/**
|
|
1324
1340
|
* Which iteration this revision is from
|
|
1325
1341
|
*/
|
|
1326
|
-
iteration:
|
|
1342
|
+
iteration: import_zod6.z.number().int().nonnegative().describe("Iteration number"),
|
|
1327
1343
|
/**
|
|
1328
1344
|
* The reflection that prompted this revision
|
|
1329
1345
|
*/
|
|
@@ -1331,9 +1347,9 @@ var RevisionSchema = import_zod5.z.object({
|
|
|
1331
1347
|
/**
|
|
1332
1348
|
* Timestamp of the revision
|
|
1333
1349
|
*/
|
|
1334
|
-
timestamp:
|
|
1350
|
+
timestamp: import_zod6.z.date().optional().describe("When this revision was created")
|
|
1335
1351
|
});
|
|
1336
|
-
var ReflectionStatusSchema =
|
|
1352
|
+
var ReflectionStatusSchema = import_zod6.z.enum([
|
|
1337
1353
|
"generating",
|
|
1338
1354
|
// Initial generation
|
|
1339
1355
|
"reflecting",
|
|
@@ -1345,25 +1361,25 @@ var ReflectionStatusSchema = import_zod5.z.enum([
|
|
|
1345
1361
|
"failed"
|
|
1346
1362
|
// Max iterations reached without meeting standards
|
|
1347
1363
|
]);
|
|
1348
|
-
var QualityCriteriaSchema =
|
|
1364
|
+
var QualityCriteriaSchema = import_zod6.z.object({
|
|
1349
1365
|
/**
|
|
1350
1366
|
* Minimum quality score required (0-10)
|
|
1351
1367
|
*/
|
|
1352
|
-
minScore:
|
|
1368
|
+
minScore: import_zod6.z.number().min(0).max(10).default(7).describe("Minimum quality score required"),
|
|
1353
1369
|
/**
|
|
1354
1370
|
* Specific criteria to evaluate
|
|
1355
1371
|
*/
|
|
1356
|
-
criteria:
|
|
1372
|
+
criteria: import_zod6.z.array(import_zod6.z.string()).optional().describe("Specific criteria to evaluate"),
|
|
1357
1373
|
/**
|
|
1358
1374
|
* Whether all criteria must be met
|
|
1359
1375
|
*/
|
|
1360
|
-
requireAll:
|
|
1376
|
+
requireAll: import_zod6.z.boolean().default(true).describe("Whether all criteria must be met")
|
|
1361
1377
|
});
|
|
1362
|
-
var ReflectionConfigSchema =
|
|
1378
|
+
var ReflectionConfigSchema = import_zod6.z.object({
|
|
1363
1379
|
/**
|
|
1364
1380
|
* Maximum number of reflection iterations
|
|
1365
1381
|
*/
|
|
1366
|
-
maxIterations:
|
|
1382
|
+
maxIterations: import_zod6.z.number().int().positive().default(3).describe("Maximum reflection iterations"),
|
|
1367
1383
|
/**
|
|
1368
1384
|
* Quality criteria for completion
|
|
1369
1385
|
*/
|
|
@@ -1371,7 +1387,7 @@ var ReflectionConfigSchema = import_zod5.z.object({
|
|
|
1371
1387
|
/**
|
|
1372
1388
|
* Whether to include previous reflections in context
|
|
1373
1389
|
*/
|
|
1374
|
-
includeHistory:
|
|
1390
|
+
includeHistory: import_zod6.z.boolean().default(true).describe("Include previous reflections in context")
|
|
1375
1391
|
});
|
|
1376
1392
|
|
|
1377
1393
|
// src/reflection/state.ts
|
|
@@ -1379,16 +1395,12 @@ var ReflectionStateConfig = {
|
|
|
1379
1395
|
/**
|
|
1380
1396
|
* Original user input/task
|
|
1381
1397
|
*/
|
|
1382
|
-
input:
|
|
1383
|
-
schema: import_zod6.z.string(),
|
|
1384
|
-
default: () => "",
|
|
1385
|
-
description: "Original user input or task"
|
|
1386
|
-
},
|
|
1398
|
+
input: inputField,
|
|
1387
1399
|
/**
|
|
1388
1400
|
* Current response/output
|
|
1389
1401
|
*/
|
|
1390
1402
|
currentResponse: {
|
|
1391
|
-
schema:
|
|
1403
|
+
schema: import_zod7.z.string().optional(),
|
|
1392
1404
|
description: "Current response or output"
|
|
1393
1405
|
},
|
|
1394
1406
|
/**
|
|
@@ -1396,7 +1408,7 @@ var ReflectionStateConfig = {
|
|
|
1396
1408
|
* Accumulates all reflections
|
|
1397
1409
|
*/
|
|
1398
1410
|
reflections: {
|
|
1399
|
-
schema:
|
|
1411
|
+
schema: import_zod7.z.array(ReflectionSchema),
|
|
1400
1412
|
reducer: (left, right) => [...left, ...right],
|
|
1401
1413
|
default: () => [],
|
|
1402
1414
|
description: "History of all reflections and critiques"
|
|
@@ -1406,7 +1418,7 @@ var ReflectionStateConfig = {
|
|
|
1406
1418
|
* Accumulates all revisions
|
|
1407
1419
|
*/
|
|
1408
1420
|
revisions: {
|
|
1409
|
-
schema:
|
|
1421
|
+
schema: import_zod7.z.array(RevisionSchema),
|
|
1410
1422
|
reducer: (left, right) => [...left, ...right],
|
|
1411
1423
|
default: () => [],
|
|
1412
1424
|
description: "History of all revisions"
|
|
@@ -1414,12 +1426,7 @@ var ReflectionStateConfig = {
|
|
|
1414
1426
|
/**
|
|
1415
1427
|
* Current iteration number
|
|
1416
1428
|
*/
|
|
1417
|
-
iteration:
|
|
1418
|
-
schema: import_zod6.z.number().int().nonnegative(),
|
|
1419
|
-
reducer: (left, right) => left + right,
|
|
1420
|
-
default: () => 0,
|
|
1421
|
-
description: "Current iteration number"
|
|
1422
|
-
},
|
|
1429
|
+
iteration: iterationField,
|
|
1423
1430
|
/**
|
|
1424
1431
|
* Current status
|
|
1425
1432
|
*/
|
|
@@ -1438,25 +1445,15 @@ var ReflectionStateConfig = {
|
|
|
1438
1445
|
/**
|
|
1439
1446
|
* Maximum iterations allowed
|
|
1440
1447
|
*/
|
|
1441
|
-
maxIterations:
|
|
1442
|
-
schema: import_zod6.z.number().int().positive(),
|
|
1443
|
-
default: () => 3,
|
|
1444
|
-
description: "Maximum number of reflection iterations allowed"
|
|
1445
|
-
},
|
|
1448
|
+
maxIterations: maxIterationsField(3),
|
|
1446
1449
|
/**
|
|
1447
1450
|
* Final response (when completed)
|
|
1448
1451
|
*/
|
|
1449
|
-
response:
|
|
1450
|
-
schema: import_zod6.z.string().optional(),
|
|
1451
|
-
description: "Final response after reflection process"
|
|
1452
|
-
},
|
|
1452
|
+
response: responseField,
|
|
1453
1453
|
/**
|
|
1454
1454
|
* Error message if failed
|
|
1455
1455
|
*/
|
|
1456
|
-
error:
|
|
1457
|
-
schema: import_zod6.z.string().optional(),
|
|
1458
|
-
description: "Error message if reflection failed"
|
|
1459
|
-
}
|
|
1456
|
+
error: errorField
|
|
1460
1457
|
};
|
|
1461
1458
|
var ReflectionState = (0, import_core6.createStateAnnotation)(ReflectionStateConfig);
|
|
1462
1459
|
|
|
@@ -1605,14 +1602,15 @@ ${lastReflection.critique}`;
|
|
|
1605
1602
|
iteration: 1
|
|
1606
1603
|
};
|
|
1607
1604
|
} catch (error) {
|
|
1605
|
+
const errorMessage = handleNodeError(error, "generator", false);
|
|
1608
1606
|
generatorLogger.error("Response generation failed", {
|
|
1609
1607
|
attempt: state.iteration + 1,
|
|
1610
|
-
error:
|
|
1608
|
+
error: errorMessage,
|
|
1611
1609
|
duration: Date.now() - startTime
|
|
1612
1610
|
});
|
|
1613
1611
|
return {
|
|
1614
1612
|
status: "failed",
|
|
1615
|
-
error:
|
|
1613
|
+
error: errorMessage
|
|
1616
1614
|
};
|
|
1617
1615
|
}
|
|
1618
1616
|
};
|
|
@@ -1694,14 +1692,15 @@ function createReflectorNode(config) {
|
|
|
1694
1692
|
status: reflection.meetsStandards ? "completed" : "revising"
|
|
1695
1693
|
};
|
|
1696
1694
|
} catch (error) {
|
|
1695
|
+
const errorMessage = handleNodeError(error, "reflector", false);
|
|
1697
1696
|
reflectorLogger.error("Reflection failed", {
|
|
1698
1697
|
attempt: state.iteration,
|
|
1699
|
-
error:
|
|
1698
|
+
error: errorMessage,
|
|
1700
1699
|
duration: Date.now() - startTime
|
|
1701
1700
|
});
|
|
1702
1701
|
return {
|
|
1703
1702
|
status: "failed",
|
|
1704
|
-
error:
|
|
1703
|
+
error: errorMessage
|
|
1705
1704
|
};
|
|
1706
1705
|
}
|
|
1707
1706
|
};
|
|
@@ -1762,14 +1761,15 @@ ${revisionsText}`;
|
|
|
1762
1761
|
iteration: 1
|
|
1763
1762
|
};
|
|
1764
1763
|
} catch (error) {
|
|
1764
|
+
const errorMessage = handleNodeError(error, "reviser", false);
|
|
1765
1765
|
reviserLogger.error("Revision failed", {
|
|
1766
1766
|
attempt: state.iteration,
|
|
1767
|
-
error:
|
|
1767
|
+
error: errorMessage,
|
|
1768
1768
|
duration: Date.now() - startTime
|
|
1769
1769
|
});
|
|
1770
1770
|
return {
|
|
1771
1771
|
status: "failed",
|
|
1772
|
-
error:
|
|
1772
|
+
error: errorMessage
|
|
1773
1773
|
};
|
|
1774
1774
|
}
|
|
1775
1775
|
};
|
|
@@ -1855,13 +1855,13 @@ function createReflectionAgent(config) {
|
|
|
1855
1855
|
}
|
|
1856
1856
|
|
|
1857
1857
|
// src/multi-agent/state.ts
|
|
1858
|
-
var
|
|
1858
|
+
var import_zod9 = require("zod");
|
|
1859
1859
|
var import_core7 = require("@agentforge/core");
|
|
1860
1860
|
|
|
1861
1861
|
// src/multi-agent/schemas.ts
|
|
1862
|
-
var
|
|
1863
|
-
var AgentRoleSchema =
|
|
1864
|
-
var MessageTypeSchema =
|
|
1862
|
+
var import_zod8 = require("zod");
|
|
1863
|
+
var AgentRoleSchema = import_zod8.z.enum(["supervisor", "worker"]);
|
|
1864
|
+
var MessageTypeSchema = import_zod8.z.enum([
|
|
1865
1865
|
"user_input",
|
|
1866
1866
|
// Initial user message
|
|
1867
1867
|
"task_assignment",
|
|
@@ -1875,11 +1875,11 @@ var MessageTypeSchema = import_zod7.z.enum([
|
|
|
1875
1875
|
"completion"
|
|
1876
1876
|
// Final completion message
|
|
1877
1877
|
]);
|
|
1878
|
-
var AgentMessageSchema =
|
|
1878
|
+
var AgentMessageSchema = import_zod8.z.object({
|
|
1879
1879
|
/**
|
|
1880
1880
|
* Unique identifier for the message
|
|
1881
1881
|
*/
|
|
1882
|
-
id:
|
|
1882
|
+
id: import_zod8.z.string().describe("Unique message identifier"),
|
|
1883
1883
|
/**
|
|
1884
1884
|
* Type of message
|
|
1885
1885
|
*/
|
|
@@ -1887,25 +1887,25 @@ var AgentMessageSchema = import_zod7.z.object({
|
|
|
1887
1887
|
/**
|
|
1888
1888
|
* Agent that sent the message
|
|
1889
1889
|
*/
|
|
1890
|
-
from:
|
|
1890
|
+
from: import_zod8.z.string().describe("Agent identifier that sent the message"),
|
|
1891
1891
|
/**
|
|
1892
1892
|
* Agent(s) that should receive the message
|
|
1893
1893
|
*/
|
|
1894
|
-
to:
|
|
1894
|
+
to: import_zod8.z.union([import_zod8.z.string(), import_zod8.z.array(import_zod8.z.string())]).describe("Target agent(s)"),
|
|
1895
1895
|
/**
|
|
1896
1896
|
* Message content
|
|
1897
1897
|
*/
|
|
1898
|
-
content:
|
|
1898
|
+
content: import_zod8.z.string().describe("Message content"),
|
|
1899
1899
|
/**
|
|
1900
1900
|
* Optional metadata
|
|
1901
1901
|
*/
|
|
1902
|
-
metadata:
|
|
1902
|
+
metadata: import_zod8.z.record(import_zod8.z.any()).optional().describe("Additional message metadata"),
|
|
1903
1903
|
/**
|
|
1904
1904
|
* Timestamp when message was created
|
|
1905
1905
|
*/
|
|
1906
|
-
timestamp:
|
|
1906
|
+
timestamp: import_zod8.z.number().describe("Timestamp when message was created")
|
|
1907
1907
|
});
|
|
1908
|
-
var RoutingStrategySchema =
|
|
1908
|
+
var RoutingStrategySchema = import_zod8.z.enum([
|
|
1909
1909
|
"llm-based",
|
|
1910
1910
|
// LLM decides which agent to route to
|
|
1911
1911
|
"rule-based",
|
|
@@ -1917,25 +1917,25 @@ var RoutingStrategySchema = import_zod7.z.enum([
|
|
|
1917
1917
|
"load-balanced"
|
|
1918
1918
|
// Route based on agent workload
|
|
1919
1919
|
]);
|
|
1920
|
-
var RoutingDecisionSchema =
|
|
1920
|
+
var RoutingDecisionSchema = import_zod8.z.object({
|
|
1921
1921
|
/**
|
|
1922
1922
|
* Target agent to route to (single agent routing)
|
|
1923
1923
|
* @deprecated Use targetAgents for parallel routing support
|
|
1924
1924
|
*/
|
|
1925
|
-
targetAgent:
|
|
1925
|
+
targetAgent: import_zod8.z.string().nullable().default(null).describe("Agent to route the task to (single routing)"),
|
|
1926
1926
|
/**
|
|
1927
1927
|
* Target agents to route to (parallel routing)
|
|
1928
1928
|
* When multiple agents are specified, they execute in parallel
|
|
1929
1929
|
*/
|
|
1930
|
-
targetAgents:
|
|
1930
|
+
targetAgents: import_zod8.z.array(import_zod8.z.string()).nullable().default(null).describe("Agents to route the task to (parallel routing)"),
|
|
1931
1931
|
/**
|
|
1932
1932
|
* Reasoning for the routing decision
|
|
1933
1933
|
*/
|
|
1934
|
-
reasoning:
|
|
1934
|
+
reasoning: import_zod8.z.string().default("").describe("Explanation for routing decision"),
|
|
1935
1935
|
/**
|
|
1936
1936
|
* Confidence in the routing decision (0-1)
|
|
1937
1937
|
*/
|
|
1938
|
-
confidence:
|
|
1938
|
+
confidence: import_zod8.z.number().min(0).max(1).default(0.8).describe("Confidence score"),
|
|
1939
1939
|
/**
|
|
1940
1940
|
* Strategy used for routing
|
|
1941
1941
|
*/
|
|
@@ -1943,86 +1943,86 @@ var RoutingDecisionSchema = import_zod7.z.object({
|
|
|
1943
1943
|
/**
|
|
1944
1944
|
* Timestamp of the routing decision
|
|
1945
1945
|
*/
|
|
1946
|
-
timestamp:
|
|
1946
|
+
timestamp: import_zod8.z.number().default(() => Date.now()).describe("Timestamp of the decision")
|
|
1947
1947
|
}).refine(
|
|
1948
1948
|
(data) => data.targetAgent || data.targetAgents && data.targetAgents.length > 0,
|
|
1949
1949
|
{ message: "Either targetAgent or targetAgents must be provided" }
|
|
1950
1950
|
);
|
|
1951
|
-
var WorkerCapabilitiesSchema =
|
|
1951
|
+
var WorkerCapabilitiesSchema = import_zod8.z.object({
|
|
1952
1952
|
/**
|
|
1953
1953
|
* Skills/capabilities the agent has
|
|
1954
1954
|
*/
|
|
1955
|
-
skills:
|
|
1955
|
+
skills: import_zod8.z.array(import_zod8.z.string()).describe("List of agent skills"),
|
|
1956
1956
|
/**
|
|
1957
1957
|
* Tools available to the agent
|
|
1958
1958
|
*/
|
|
1959
|
-
tools:
|
|
1959
|
+
tools: import_zod8.z.array(import_zod8.z.string()).describe("List of tool names available to agent"),
|
|
1960
1960
|
/**
|
|
1961
1961
|
* Whether the agent is currently available
|
|
1962
1962
|
*/
|
|
1963
|
-
available:
|
|
1963
|
+
available: import_zod8.z.boolean().default(true).describe("Whether agent is available"),
|
|
1964
1964
|
/**
|
|
1965
1965
|
* Current workload (number of active tasks)
|
|
1966
1966
|
*/
|
|
1967
|
-
currentWorkload:
|
|
1967
|
+
currentWorkload: import_zod8.z.number().int().nonnegative().default(0).describe("Current number of active tasks")
|
|
1968
1968
|
});
|
|
1969
|
-
var TaskAssignmentSchema =
|
|
1969
|
+
var TaskAssignmentSchema = import_zod8.z.object({
|
|
1970
1970
|
/**
|
|
1971
1971
|
* Unique assignment identifier
|
|
1972
1972
|
*/
|
|
1973
|
-
id:
|
|
1973
|
+
id: import_zod8.z.string().describe("Unique assignment identifier"),
|
|
1974
1974
|
/**
|
|
1975
1975
|
* Worker ID assigned to the task
|
|
1976
1976
|
*/
|
|
1977
|
-
workerId:
|
|
1977
|
+
workerId: import_zod8.z.string().describe("Worker identifier assigned to task"),
|
|
1978
1978
|
/**
|
|
1979
1979
|
* Task description
|
|
1980
1980
|
*/
|
|
1981
|
-
task:
|
|
1981
|
+
task: import_zod8.z.string().describe("Description of the task"),
|
|
1982
1982
|
/**
|
|
1983
1983
|
* Task priority (1-10, higher is more urgent)
|
|
1984
1984
|
*/
|
|
1985
|
-
priority:
|
|
1985
|
+
priority: import_zod8.z.number().int().min(1).max(10).default(5).describe("Task priority"),
|
|
1986
1986
|
/**
|
|
1987
1987
|
* Timestamp when task was assigned
|
|
1988
1988
|
*/
|
|
1989
|
-
assignedAt:
|
|
1989
|
+
assignedAt: import_zod8.z.number().describe("Timestamp when task was assigned"),
|
|
1990
1990
|
/**
|
|
1991
1991
|
* Optional deadline for task completion
|
|
1992
1992
|
*/
|
|
1993
|
-
deadline:
|
|
1993
|
+
deadline: import_zod8.z.number().optional().describe("Optional task deadline timestamp")
|
|
1994
1994
|
});
|
|
1995
|
-
var TaskResultSchema =
|
|
1995
|
+
var TaskResultSchema = import_zod8.z.object({
|
|
1996
1996
|
/**
|
|
1997
1997
|
* Assignment identifier
|
|
1998
1998
|
*/
|
|
1999
|
-
assignmentId:
|
|
1999
|
+
assignmentId: import_zod8.z.string().describe("Assignment identifier"),
|
|
2000
2000
|
/**
|
|
2001
2001
|
* Worker that completed the task
|
|
2002
2002
|
*/
|
|
2003
|
-
workerId:
|
|
2003
|
+
workerId: import_zod8.z.string().describe("Worker that completed the task"),
|
|
2004
2004
|
/**
|
|
2005
2005
|
* Whether the task succeeded
|
|
2006
2006
|
*/
|
|
2007
|
-
success:
|
|
2007
|
+
success: import_zod8.z.boolean().describe("Whether the task succeeded"),
|
|
2008
2008
|
/**
|
|
2009
2009
|
* Task result/output
|
|
2010
2010
|
*/
|
|
2011
|
-
result:
|
|
2011
|
+
result: import_zod8.z.string().describe("Task result or output"),
|
|
2012
2012
|
/**
|
|
2013
2013
|
* Optional error message if task failed
|
|
2014
2014
|
*/
|
|
2015
|
-
error:
|
|
2015
|
+
error: import_zod8.z.string().optional().describe("Error message if task failed"),
|
|
2016
2016
|
/**
|
|
2017
2017
|
* Timestamp when task was completed
|
|
2018
2018
|
*/
|
|
2019
|
-
completedAt:
|
|
2019
|
+
completedAt: import_zod8.z.number().describe("Timestamp when task was completed"),
|
|
2020
2020
|
/**
|
|
2021
2021
|
* Optional metadata about execution
|
|
2022
2022
|
*/
|
|
2023
|
-
metadata:
|
|
2023
|
+
metadata: import_zod8.z.record(import_zod8.z.any()).optional().describe("Execution metadata")
|
|
2024
2024
|
});
|
|
2025
|
-
var MultiAgentStatusSchema =
|
|
2025
|
+
var MultiAgentStatusSchema = import_zod8.z.enum([
|
|
2026
2026
|
"initializing",
|
|
2027
2027
|
// System is initializing
|
|
2028
2028
|
"routing",
|
|
@@ -2038,27 +2038,27 @@ var MultiAgentStatusSchema = import_zod7.z.enum([
|
|
|
2038
2038
|
"failed"
|
|
2039
2039
|
// Task failed
|
|
2040
2040
|
]);
|
|
2041
|
-
var HandoffRequestSchema =
|
|
2041
|
+
var HandoffRequestSchema = import_zod8.z.object({
|
|
2042
2042
|
/**
|
|
2043
2043
|
* Agent requesting the handoff
|
|
2044
2044
|
*/
|
|
2045
|
-
from:
|
|
2045
|
+
from: import_zod8.z.string().describe("Agent requesting handoff"),
|
|
2046
2046
|
/**
|
|
2047
2047
|
* Target agent for handoff
|
|
2048
2048
|
*/
|
|
2049
|
-
to:
|
|
2049
|
+
to: import_zod8.z.string().describe("Target agent for handoff"),
|
|
2050
2050
|
/**
|
|
2051
2051
|
* Reason for handoff
|
|
2052
2052
|
*/
|
|
2053
|
-
reason:
|
|
2053
|
+
reason: import_zod8.z.string().describe("Reason for requesting handoff"),
|
|
2054
2054
|
/**
|
|
2055
2055
|
* Context to pass to next agent
|
|
2056
2056
|
*/
|
|
2057
|
-
context:
|
|
2057
|
+
context: import_zod8.z.any().describe("Context to pass to next agent"),
|
|
2058
2058
|
/**
|
|
2059
2059
|
* Timestamp of handoff request
|
|
2060
2060
|
*/
|
|
2061
|
-
timestamp:
|
|
2061
|
+
timestamp: import_zod8.z.string().datetime().describe("ISO timestamp of handoff request")
|
|
2062
2062
|
});
|
|
2063
2063
|
|
|
2064
2064
|
// src/multi-agent/state.ts
|
|
@@ -2066,17 +2066,13 @@ var MultiAgentStateConfig = {
|
|
|
2066
2066
|
/**
|
|
2067
2067
|
* Original user input/query
|
|
2068
2068
|
*/
|
|
2069
|
-
input:
|
|
2070
|
-
schema: import_zod8.z.string(),
|
|
2071
|
-
default: () => "",
|
|
2072
|
-
description: "Original user input or query"
|
|
2073
|
-
},
|
|
2069
|
+
input: inputField,
|
|
2074
2070
|
/**
|
|
2075
2071
|
* All messages in the multi-agent conversation
|
|
2076
2072
|
* Accumulates all messages between agents
|
|
2077
2073
|
*/
|
|
2078
2074
|
messages: {
|
|
2079
|
-
schema:
|
|
2075
|
+
schema: import_zod9.z.array(AgentMessageSchema),
|
|
2080
2076
|
reducer: (left, right) => [...left, ...right],
|
|
2081
2077
|
default: () => [],
|
|
2082
2078
|
description: "All messages in the multi-agent conversation"
|
|
@@ -2085,7 +2081,7 @@ var MultiAgentStateConfig = {
|
|
|
2085
2081
|
* Available worker agents and their capabilities
|
|
2086
2082
|
*/
|
|
2087
2083
|
workers: {
|
|
2088
|
-
schema:
|
|
2084
|
+
schema: import_zod9.z.record(import_zod9.z.string(), WorkerCapabilitiesSchema),
|
|
2089
2085
|
reducer: (left, right) => ({
|
|
2090
2086
|
...left,
|
|
2091
2087
|
...right
|
|
@@ -2097,7 +2093,7 @@ var MultiAgentStateConfig = {
|
|
|
2097
2093
|
* Current active agent
|
|
2098
2094
|
*/
|
|
2099
2095
|
currentAgent: {
|
|
2100
|
-
schema:
|
|
2096
|
+
schema: import_zod9.z.string().optional(),
|
|
2101
2097
|
description: "Identifier of the currently active agent"
|
|
2102
2098
|
},
|
|
2103
2099
|
/**
|
|
@@ -2105,7 +2101,7 @@ var MultiAgentStateConfig = {
|
|
|
2105
2101
|
* Accumulates all routing decisions
|
|
2106
2102
|
*/
|
|
2107
2103
|
routingHistory: {
|
|
2108
|
-
schema:
|
|
2104
|
+
schema: import_zod9.z.array(RoutingDecisionSchema),
|
|
2109
2105
|
reducer: (left, right) => [...left, ...right],
|
|
2110
2106
|
default: () => [],
|
|
2111
2107
|
description: "History of routing decisions"
|
|
@@ -2114,7 +2110,7 @@ var MultiAgentStateConfig = {
|
|
|
2114
2110
|
* Active task assignments
|
|
2115
2111
|
*/
|
|
2116
2112
|
activeAssignments: {
|
|
2117
|
-
schema:
|
|
2113
|
+
schema: import_zod9.z.array(TaskAssignmentSchema),
|
|
2118
2114
|
reducer: (left, right) => [...left, ...right],
|
|
2119
2115
|
default: () => [],
|
|
2120
2116
|
description: "Currently active task assignments"
|
|
@@ -2124,7 +2120,7 @@ var MultiAgentStateConfig = {
|
|
|
2124
2120
|
* Accumulates all completed tasks
|
|
2125
2121
|
*/
|
|
2126
2122
|
completedTasks: {
|
|
2127
|
-
schema:
|
|
2123
|
+
schema: import_zod9.z.array(TaskResultSchema),
|
|
2128
2124
|
reducer: (left, right) => [...left, ...right],
|
|
2129
2125
|
default: () => [],
|
|
2130
2126
|
description: "Completed task results"
|
|
@@ -2134,7 +2130,7 @@ var MultiAgentStateConfig = {
|
|
|
2134
2130
|
* Accumulates all handoff requests
|
|
2135
2131
|
*/
|
|
2136
2132
|
handoffs: {
|
|
2137
|
-
schema:
|
|
2133
|
+
schema: import_zod9.z.array(HandoffRequestSchema),
|
|
2138
2134
|
reducer: (left, right) => [...left, ...right],
|
|
2139
2135
|
default: () => [],
|
|
2140
2136
|
description: "Handoff requests between agents"
|
|
@@ -2150,99 +2146,24 @@ var MultiAgentStateConfig = {
|
|
|
2150
2146
|
/**
|
|
2151
2147
|
* Iteration counter
|
|
2152
2148
|
*/
|
|
2153
|
-
iteration:
|
|
2154
|
-
schema: import_zod8.z.number().int().nonnegative(),
|
|
2155
|
-
reducer: (left, right) => left + right,
|
|
2156
|
-
default: () => 0,
|
|
2157
|
-
description: "Current iteration number"
|
|
2158
|
-
},
|
|
2149
|
+
iteration: iterationField,
|
|
2159
2150
|
/**
|
|
2160
2151
|
* Maximum iterations allowed
|
|
2161
2152
|
*/
|
|
2162
|
-
maxIterations:
|
|
2163
|
-
schema: import_zod8.z.number().int().positive(),
|
|
2164
|
-
default: () => 10,
|
|
2165
|
-
description: "Maximum number of iterations allowed"
|
|
2166
|
-
},
|
|
2153
|
+
maxIterations: maxIterationsField(10),
|
|
2167
2154
|
/**
|
|
2168
2155
|
* Final aggregated response
|
|
2169
2156
|
*/
|
|
2170
|
-
response:
|
|
2171
|
-
schema: import_zod8.z.string().optional(),
|
|
2172
|
-
description: "Final aggregated response"
|
|
2173
|
-
},
|
|
2157
|
+
response: responseField,
|
|
2174
2158
|
/**
|
|
2175
2159
|
* Error message if execution failed
|
|
2176
2160
|
*/
|
|
2177
|
-
error:
|
|
2178
|
-
schema: import_zod8.z.string().optional(),
|
|
2179
|
-
description: "Error message if execution failed"
|
|
2180
|
-
}
|
|
2161
|
+
error: errorField
|
|
2181
2162
|
};
|
|
2182
2163
|
var MultiAgentState = (0, import_core7.createStateAnnotation)(MultiAgentStateConfig);
|
|
2183
2164
|
|
|
2184
2165
|
// src/multi-agent/routing.ts
|
|
2185
2166
|
var import_messages4 = require("@langchain/core/messages");
|
|
2186
|
-
var import_core8 = require("@agentforge/core");
|
|
2187
|
-
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
|
|
2188
|
-
var logger = (0, import_core8.createLogger)("multi-agent:routing", { level: logLevel });
|
|
2189
|
-
async function executeTools(toolCalls, tools) {
|
|
2190
|
-
const results = [];
|
|
2191
|
-
logger.debug("Executing tools", {
|
|
2192
|
-
toolCallCount: toolCalls.length,
|
|
2193
|
-
toolNames: toolCalls.map((tc) => tc.name)
|
|
2194
|
-
});
|
|
2195
|
-
for (const toolCall of toolCalls) {
|
|
2196
|
-
const tool = tools.find((t) => t.metadata.name === toolCall.name);
|
|
2197
|
-
if (!tool) {
|
|
2198
|
-
logger.warn("Tool not found", {
|
|
2199
|
-
toolName: toolCall.name,
|
|
2200
|
-
availableTools: tools.map((t) => t.metadata.name)
|
|
2201
|
-
});
|
|
2202
|
-
results.push(new import_messages4.ToolMessage({
|
|
2203
|
-
content: `Error: Tool '${toolCall.name}' not found`,
|
|
2204
|
-
tool_call_id: toolCall.id
|
|
2205
|
-
}));
|
|
2206
|
-
continue;
|
|
2207
|
-
}
|
|
2208
|
-
try {
|
|
2209
|
-
logger.debug("Executing tool", {
|
|
2210
|
-
toolName: toolCall.name,
|
|
2211
|
-
args: toolCall.args
|
|
2212
|
-
});
|
|
2213
|
-
const result = await tool.execute(toolCall.args);
|
|
2214
|
-
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
2215
|
-
logger.debug("Tool execution successful", {
|
|
2216
|
-
toolName: toolCall.name,
|
|
2217
|
-
resultLength: content.length
|
|
2218
|
-
});
|
|
2219
|
-
results.push(new import_messages4.ToolMessage({
|
|
2220
|
-
content,
|
|
2221
|
-
tool_call_id: toolCall.id
|
|
2222
|
-
}));
|
|
2223
|
-
} catch (error) {
|
|
2224
|
-
logger.error("Tool execution failed", {
|
|
2225
|
-
toolName: toolCall.name,
|
|
2226
|
-
error: error.message
|
|
2227
|
-
});
|
|
2228
|
-
results.push(new import_messages4.ToolMessage({
|
|
2229
|
-
content: `Error executing tool: ${error.message}`,
|
|
2230
|
-
tool_call_id: toolCall.id
|
|
2231
|
-
}));
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
logger.debug("Tool execution complete", {
|
|
2235
|
-
successCount: results.filter((r) => {
|
|
2236
|
-
const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
|
|
2237
|
-
return !content.startsWith("Error");
|
|
2238
|
-
}).length,
|
|
2239
|
-
errorCount: results.filter((r) => {
|
|
2240
|
-
const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
|
|
2241
|
-
return content.startsWith("Error");
|
|
2242
|
-
}).length
|
|
2243
|
-
});
|
|
2244
|
-
return results;
|
|
2245
|
-
}
|
|
2246
2167
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
2247
2168
|
|
|
2248
2169
|
Your job is to:
|
|
@@ -2278,151 +2199,48 @@ Choose parallel routing when the task benefits from multiple perspectives or dat
|
|
|
2278
2199
|
var llmBasedRouting = {
|
|
2279
2200
|
name: "llm-based",
|
|
2280
2201
|
async route(state, config) {
|
|
2281
|
-
logger.info("Starting LLM-based routing", {
|
|
2282
|
-
iteration: state.iteration,
|
|
2283
|
-
availableWorkers: Object.keys(state.workers).length
|
|
2284
|
-
});
|
|
2285
2202
|
if (!config.model) {
|
|
2286
2203
|
throw new Error("LLM-based routing requires a model to be configured");
|
|
2287
2204
|
}
|
|
2288
2205
|
const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
|
|
2289
|
-
const maxRetries = config.maxToolRetries || 3;
|
|
2290
|
-
const tools = config.tools || [];
|
|
2291
2206
|
const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
|
|
2292
2207
|
const skills = caps.skills.join(", ");
|
|
2293
|
-
const
|
|
2208
|
+
const tools = caps.tools.join(", ");
|
|
2294
2209
|
const available = caps.available ? "available" : "busy";
|
|
2295
|
-
return `- ${id}: Skills: [${skills}], Tools: [${
|
|
2210
|
+
return `- ${id}: Skills: [${skills}], Tools: [${tools}], Status: ${available}, Workload: ${caps.currentWorkload}`;
|
|
2296
2211
|
}).join("\n");
|
|
2297
|
-
logger.debug("Worker capabilities", {
|
|
2298
|
-
workers: Object.entries(state.workers).map(([id, caps]) => ({
|
|
2299
|
-
id,
|
|
2300
|
-
skills: caps.skills,
|
|
2301
|
-
available: caps.available,
|
|
2302
|
-
workload: caps.currentWorkload
|
|
2303
|
-
}))
|
|
2304
|
-
});
|
|
2305
2212
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
2306
2213
|
const taskContext = lastMessage?.content || state.input;
|
|
2307
|
-
logger.debug("Task context", {
|
|
2308
|
-
taskLength: taskContext.length,
|
|
2309
|
-
taskPreview: taskContext.substring(0, 100)
|
|
2310
|
-
});
|
|
2311
2214
|
const userPrompt = `Current task: ${taskContext}
|
|
2312
2215
|
|
|
2313
2216
|
Available workers:
|
|
2314
2217
|
${workerInfo}
|
|
2315
2218
|
|
|
2316
2219
|
Select the best worker(s) for this task and explain your reasoning.`;
|
|
2317
|
-
const
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
const response = await config.model.invoke(messages);
|
|
2331
|
-
if (response.tool_calls && response.tool_calls.length > 0) {
|
|
2332
|
-
logger.info("LLM requested tool calls", {
|
|
2333
|
-
toolCount: response.tool_calls.length,
|
|
2334
|
-
toolNames: response.tool_calls.map((tc) => tc.name)
|
|
2335
|
-
});
|
|
2336
|
-
if (tools.length === 0) {
|
|
2337
|
-
throw new Error("LLM requested tool calls but no tools are configured");
|
|
2338
|
-
}
|
|
2339
|
-
const toolResults = await executeTools(response.tool_calls, tools);
|
|
2340
|
-
conversationHistory.push(
|
|
2341
|
-
new import_messages4.AIMessage({ content: response.content || "", tool_calls: response.tool_calls }),
|
|
2342
|
-
...toolResults
|
|
2343
|
-
);
|
|
2344
|
-
attempt++;
|
|
2345
|
-
logger.debug("Retrying routing with tool results", { attempt });
|
|
2346
|
-
continue;
|
|
2347
|
-
}
|
|
2348
|
-
logger.debug("Parsing routing decision from LLM response");
|
|
2349
|
-
let decision;
|
|
2350
|
-
if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
|
|
2351
|
-
logger.debug("Response is structured output", {
|
|
2352
|
-
hasTargetAgent: "targetAgent" in response,
|
|
2353
|
-
hasTargetAgents: "targetAgents" in response
|
|
2354
|
-
});
|
|
2355
|
-
decision = response;
|
|
2356
|
-
} else if (response.content) {
|
|
2357
|
-
if (typeof response.content === "string") {
|
|
2358
|
-
try {
|
|
2359
|
-
decision = JSON.parse(response.content);
|
|
2360
|
-
logger.debug("Parsed JSON from string response");
|
|
2361
|
-
} catch (error) {
|
|
2362
|
-
logger.error("Failed to parse routing decision", {
|
|
2363
|
-
content: response.content,
|
|
2364
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2365
|
-
});
|
|
2366
|
-
throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
|
|
2367
|
-
}
|
|
2368
|
-
} else if (typeof response.content === "object") {
|
|
2369
|
-
logger.debug("Response content is already an object");
|
|
2370
|
-
decision = response.content;
|
|
2371
|
-
} else {
|
|
2372
|
-
logger.error("Unexpected response content type", {
|
|
2373
|
-
type: typeof response.content
|
|
2374
|
-
});
|
|
2375
|
-
throw new Error(`Unexpected response content type: ${typeof response.content}`);
|
|
2376
|
-
}
|
|
2377
|
-
} else {
|
|
2378
|
-
logger.error("Unexpected response format", {
|
|
2379
|
-
response: JSON.stringify(response)
|
|
2380
|
-
});
|
|
2381
|
-
throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
|
|
2382
|
-
}
|
|
2383
|
-
const result = {
|
|
2384
|
-
targetAgent: decision.targetAgent,
|
|
2385
|
-
targetAgents: decision.targetAgents,
|
|
2386
|
-
reasoning: decision.reasoning,
|
|
2387
|
-
confidence: decision.confidence,
|
|
2388
|
-
strategy: "llm-based",
|
|
2389
|
-
timestamp: Date.now()
|
|
2390
|
-
};
|
|
2391
|
-
logger.info("LLM routing decision made", {
|
|
2392
|
-
targetAgent: result.targetAgent,
|
|
2393
|
-
targetAgents: result.targetAgents,
|
|
2394
|
-
isParallel: result.targetAgents && result.targetAgents.length > 1,
|
|
2395
|
-
confidence: result.confidence,
|
|
2396
|
-
reasoning: result.reasoning
|
|
2397
|
-
});
|
|
2398
|
-
return result;
|
|
2399
|
-
}
|
|
2400
|
-
logger.error("Max tool retries exceeded", { maxRetries });
|
|
2401
|
-
throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
|
|
2220
|
+
const messages = [
|
|
2221
|
+
new import_messages4.SystemMessage(systemPrompt),
|
|
2222
|
+
new import_messages4.HumanMessage(userPrompt)
|
|
2223
|
+
];
|
|
2224
|
+
const decision = await config.model.invoke(messages);
|
|
2225
|
+
return {
|
|
2226
|
+
targetAgent: decision.targetAgent,
|
|
2227
|
+
targetAgents: decision.targetAgents,
|
|
2228
|
+
reasoning: decision.reasoning,
|
|
2229
|
+
confidence: decision.confidence,
|
|
2230
|
+
strategy: "llm-based",
|
|
2231
|
+
timestamp: Date.now()
|
|
2232
|
+
};
|
|
2402
2233
|
}
|
|
2403
2234
|
};
|
|
2404
2235
|
var roundRobinRouting = {
|
|
2405
2236
|
name: "round-robin",
|
|
2406
2237
|
async route(state, config) {
|
|
2407
|
-
logger.info("Starting round-robin routing", {
|
|
2408
|
-
iteration: state.iteration
|
|
2409
|
-
});
|
|
2410
2238
|
const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
|
|
2411
|
-
logger.debug("Available workers for round-robin", {
|
|
2412
|
-
count: availableWorkers.length,
|
|
2413
|
-
workers: availableWorkers
|
|
2414
|
-
});
|
|
2415
2239
|
if (availableWorkers.length === 0) {
|
|
2416
|
-
logger.error("No available workers for round-robin routing");
|
|
2417
2240
|
throw new Error("No available workers for round-robin routing");
|
|
2418
2241
|
}
|
|
2419
2242
|
const lastRoutingIndex = state.routingHistory.length % availableWorkers.length;
|
|
2420
2243
|
const targetAgent = availableWorkers[lastRoutingIndex];
|
|
2421
|
-
logger.info("Round-robin routing decision", {
|
|
2422
|
-
targetAgent,
|
|
2423
|
-
index: lastRoutingIndex + 1,
|
|
2424
|
-
totalWorkers: availableWorkers.length
|
|
2425
|
-
});
|
|
2426
2244
|
return {
|
|
2427
2245
|
targetAgent,
|
|
2428
2246
|
targetAgents: null,
|
|
@@ -2436,15 +2254,8 @@ var roundRobinRouting = {
|
|
|
2436
2254
|
var skillBasedRouting = {
|
|
2437
2255
|
name: "skill-based",
|
|
2438
2256
|
async route(state, config) {
|
|
2439
|
-
logger.info("Starting skill-based routing", {
|
|
2440
|
-
iteration: state.iteration
|
|
2441
|
-
});
|
|
2442
2257
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
2443
2258
|
const taskContent = (lastMessage?.content || state.input).toLowerCase();
|
|
2444
|
-
logger.debug("Task content for skill matching", {
|
|
2445
|
-
taskLength: taskContent.length,
|
|
2446
|
-
taskPreview: taskContent.substring(0, 100)
|
|
2447
|
-
});
|
|
2448
2259
|
const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
|
|
2449
2260
|
const skillMatches = caps.skills.filter(
|
|
2450
2261
|
(skill) => taskContent.includes(skill.toLowerCase())
|
|
@@ -2455,20 +2266,11 @@ var skillBasedRouting = {
|
|
|
2455
2266
|
const score = skillMatches * 2 + toolMatches;
|
|
2456
2267
|
return { id, score, skills: caps.skills, tools: caps.tools };
|
|
2457
2268
|
}).filter((w) => w.score > 0).sort((a, b) => b.score - a.score);
|
|
2458
|
-
logger.debug("Worker skill scores", {
|
|
2459
|
-
scoredWorkers: workerScores.map((w) => ({ id: w.id, score: w.score }))
|
|
2460
|
-
});
|
|
2461
2269
|
if (workerScores.length === 0) {
|
|
2462
|
-
logger.warn("No skill matches found, using fallback");
|
|
2463
2270
|
const firstAvailable = Object.entries(state.workers).find(([_, caps]) => caps.available);
|
|
2464
2271
|
if (!firstAvailable) {
|
|
2465
|
-
logger.error("No available workers for skill-based routing");
|
|
2466
2272
|
throw new Error("No available workers for skill-based routing");
|
|
2467
2273
|
}
|
|
2468
|
-
logger.info("Skill-based routing fallback decision", {
|
|
2469
|
-
targetAgent: firstAvailable[0],
|
|
2470
|
-
confidence: 0.5
|
|
2471
|
-
});
|
|
2472
2274
|
return {
|
|
2473
2275
|
targetAgent: firstAvailable[0],
|
|
2474
2276
|
targetAgents: null,
|
|
@@ -2480,12 +2282,6 @@ var skillBasedRouting = {
|
|
|
2480
2282
|
}
|
|
2481
2283
|
const best = workerScores[0];
|
|
2482
2284
|
const confidence = Math.min(best.score / 5, 1);
|
|
2483
|
-
logger.info("Skill-based routing decision", {
|
|
2484
|
-
targetAgent: best.id,
|
|
2485
|
-
score: best.score,
|
|
2486
|
-
confidence,
|
|
2487
|
-
matchedSkills: best.skills
|
|
2488
|
-
});
|
|
2489
2285
|
return {
|
|
2490
2286
|
targetAgent: best.id,
|
|
2491
2287
|
targetAgents: null,
|
|
@@ -2499,26 +2295,13 @@ var skillBasedRouting = {
|
|
|
2499
2295
|
var loadBalancedRouting = {
|
|
2500
2296
|
name: "load-balanced",
|
|
2501
2297
|
async route(state, config) {
|
|
2502
|
-
logger.info("Starting load-balanced routing", {
|
|
2503
|
-
iteration: state.iteration
|
|
2504
|
-
});
|
|
2505
2298
|
const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
|
|
2506
|
-
logger.debug("Worker workloads", {
|
|
2507
|
-
workers: availableWorkers.map((w) => ({ id: w.id, workload: w.workload }))
|
|
2508
|
-
});
|
|
2509
2299
|
if (availableWorkers.length === 0) {
|
|
2510
|
-
logger.error("No available workers for load-balanced routing");
|
|
2511
2300
|
throw new Error("No available workers for load-balanced routing");
|
|
2512
2301
|
}
|
|
2513
2302
|
const targetWorker = availableWorkers[0];
|
|
2514
2303
|
const avgWorkload = availableWorkers.reduce((sum, w) => sum + w.workload, 0) / availableWorkers.length;
|
|
2515
2304
|
const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
|
|
2516
|
-
logger.info("Load-balanced routing decision", {
|
|
2517
|
-
targetAgent: targetWorker.id,
|
|
2518
|
-
workload: targetWorker.workload,
|
|
2519
|
-
avgWorkload: avgWorkload.toFixed(1),
|
|
2520
|
-
confidence
|
|
2521
|
-
});
|
|
2522
2305
|
return {
|
|
2523
2306
|
targetAgent: targetWorker.id,
|
|
2524
2307
|
targetAgents: null,
|
|
@@ -2532,24 +2315,13 @@ var loadBalancedRouting = {
|
|
|
2532
2315
|
var ruleBasedRouting = {
|
|
2533
2316
|
name: "rule-based",
|
|
2534
2317
|
async route(state, config) {
|
|
2535
|
-
logger.info("Starting rule-based routing", {
|
|
2536
|
-
iteration: state.iteration
|
|
2537
|
-
});
|
|
2538
2318
|
if (!config.routingFn) {
|
|
2539
|
-
logger.error("Rule-based routing requires a custom routing function");
|
|
2540
2319
|
throw new Error("Rule-based routing requires a custom routing function");
|
|
2541
2320
|
}
|
|
2542
|
-
|
|
2543
|
-
logger.info("Rule-based routing decision", {
|
|
2544
|
-
targetAgent: decision.targetAgent,
|
|
2545
|
-
targetAgents: decision.targetAgents,
|
|
2546
|
-
confidence: decision.confidence
|
|
2547
|
-
});
|
|
2548
|
-
return decision;
|
|
2321
|
+
return await config.routingFn(state);
|
|
2549
2322
|
}
|
|
2550
2323
|
};
|
|
2551
2324
|
function getRoutingStrategy(name) {
|
|
2552
|
-
logger.debug("Getting routing strategy", { name });
|
|
2553
2325
|
switch (name) {
|
|
2554
2326
|
case "llm-based":
|
|
2555
2327
|
return llmBasedRouting;
|
|
@@ -2562,15 +2334,14 @@ function getRoutingStrategy(name) {
|
|
|
2562
2334
|
case "rule-based":
|
|
2563
2335
|
return ruleBasedRouting;
|
|
2564
2336
|
default:
|
|
2565
|
-
logger.error("Unknown routing strategy", { name });
|
|
2566
2337
|
throw new Error(`Unknown routing strategy: ${name}`);
|
|
2567
2338
|
}
|
|
2568
2339
|
}
|
|
2569
2340
|
|
|
2570
2341
|
// src/multi-agent/utils.ts
|
|
2571
|
-
var
|
|
2572
|
-
var
|
|
2573
|
-
var
|
|
2342
|
+
var import_core8 = require("@agentforge/core");
|
|
2343
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
|
|
2344
|
+
var logger = (0, import_core8.createLogger)("multi-agent", { level: logLevel });
|
|
2574
2345
|
function isReActAgent(obj) {
|
|
2575
2346
|
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
|
|
2576
2347
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
@@ -2578,9 +2349,9 @@ function isReActAgent(obj) {
|
|
|
2578
2349
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2579
2350
|
return async (state, config) => {
|
|
2580
2351
|
try {
|
|
2581
|
-
|
|
2352
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2582
2353
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2583
|
-
|
|
2354
|
+
logger.debug("Extracted task", {
|
|
2584
2355
|
workerId,
|
|
2585
2356
|
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2586
2357
|
});
|
|
@@ -2588,7 +2359,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2588
2359
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2589
2360
|
);
|
|
2590
2361
|
if (!currentAssignment) {
|
|
2591
|
-
|
|
2362
|
+
logger.debug("No active assignment found", { workerId });
|
|
2592
2363
|
return {};
|
|
2593
2364
|
}
|
|
2594
2365
|
const result = await agent.invoke(
|
|
@@ -2599,14 +2370,14 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2599
2370
|
// Pass through the config for checkpointing and interrupt support
|
|
2600
2371
|
);
|
|
2601
2372
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2602
|
-
|
|
2373
|
+
logger.debug("Received response from ReAct agent", {
|
|
2603
2374
|
workerId,
|
|
2604
2375
|
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2605
2376
|
});
|
|
2606
2377
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2607
2378
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2608
2379
|
if (uniqueTools.length > 0) {
|
|
2609
|
-
|
|
2380
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2610
2381
|
}
|
|
2611
2382
|
const taskResult = {
|
|
2612
2383
|
assignmentId: currentAssignment.id,
|
|
@@ -2624,14 +2395,10 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2624
2395
|
completedTasks: [taskResult]
|
|
2625
2396
|
};
|
|
2626
2397
|
} catch (error) {
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
throw error;
|
|
2630
|
-
}
|
|
2631
|
-
logger2.error("Error in ReAct agent execution", {
|
|
2398
|
+
const errorMessage = handleNodeError(error, `react-agent:${workerId}`, false);
|
|
2399
|
+
logger.error("Error in ReAct agent execution", {
|
|
2632
2400
|
workerId,
|
|
2633
|
-
error:
|
|
2634
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
2401
|
+
error: errorMessage
|
|
2635
2402
|
});
|
|
2636
2403
|
const currentAssignment = state.activeAssignments.find(
|
|
2637
2404
|
(assignment) => assignment.workerId === workerId
|
|
@@ -2642,7 +2409,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2642
2409
|
workerId,
|
|
2643
2410
|
success: false,
|
|
2644
2411
|
result: "",
|
|
2645
|
-
error:
|
|
2412
|
+
error: errorMessage,
|
|
2646
2413
|
completedAt: Date.now()
|
|
2647
2414
|
};
|
|
2648
2415
|
return {
|
|
@@ -2653,7 +2420,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2653
2420
|
}
|
|
2654
2421
|
return {
|
|
2655
2422
|
status: "failed",
|
|
2656
|
-
error:
|
|
2423
|
+
error: errorMessage
|
|
2657
2424
|
};
|
|
2658
2425
|
}
|
|
2659
2426
|
};
|
|
@@ -2661,9 +2428,9 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2661
2428
|
|
|
2662
2429
|
// src/multi-agent/nodes.ts
|
|
2663
2430
|
var import_messages5 = require("@langchain/core/messages");
|
|
2664
|
-
var
|
|
2665
|
-
var
|
|
2666
|
-
var
|
|
2431
|
+
var import_core9 = require("@agentforge/core");
|
|
2432
|
+
var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || import_core9.LogLevel.INFO;
|
|
2433
|
+
var logger2 = (0, import_core9.createLogger)("multi-agent:nodes", { level: logLevel2 });
|
|
2667
2434
|
var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
|
|
2668
2435
|
|
|
2669
2436
|
Your job is to:
|
|
@@ -2681,19 +2448,19 @@ function createSupervisorNode(config) {
|
|
|
2681
2448
|
} = config;
|
|
2682
2449
|
return async (state) => {
|
|
2683
2450
|
try {
|
|
2684
|
-
|
|
2451
|
+
logger2.info("Supervisor node executing", {
|
|
2685
2452
|
iteration: state.iteration,
|
|
2686
2453
|
maxIterations,
|
|
2687
2454
|
activeAssignments: state.activeAssignments.length,
|
|
2688
2455
|
completedTasks: state.completedTasks.length
|
|
2689
2456
|
});
|
|
2690
|
-
|
|
2457
|
+
logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
|
|
2691
2458
|
if (state.iteration >= maxIterations) {
|
|
2692
|
-
|
|
2459
|
+
logger2.warn("Max iterations reached", {
|
|
2693
2460
|
iteration: state.iteration,
|
|
2694
2461
|
maxIterations
|
|
2695
2462
|
});
|
|
2696
|
-
|
|
2463
|
+
logger2.debug("Max iterations reached, moving to aggregation");
|
|
2697
2464
|
return {
|
|
2698
2465
|
status: "aggregating",
|
|
2699
2466
|
currentAgent: "aggregator"
|
|
@@ -2702,26 +2469,26 @@ function createSupervisorNode(config) {
|
|
|
2702
2469
|
const allCompleted = state.activeAssignments.every(
|
|
2703
2470
|
(assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2704
2471
|
);
|
|
2705
|
-
|
|
2472
|
+
logger2.debug("Checking task completion", {
|
|
2706
2473
|
activeAssignments: state.activeAssignments.length,
|
|
2707
2474
|
completedTasks: state.completedTasks.length,
|
|
2708
2475
|
allCompleted
|
|
2709
2476
|
});
|
|
2710
2477
|
if (allCompleted && state.activeAssignments.length > 0) {
|
|
2711
|
-
|
|
2478
|
+
logger2.info("All tasks completed, moving to aggregation", {
|
|
2712
2479
|
completedCount: state.completedTasks.length
|
|
2713
2480
|
});
|
|
2714
|
-
|
|
2481
|
+
logger2.debug("All tasks completed, moving to aggregation");
|
|
2715
2482
|
return {
|
|
2716
2483
|
status: "aggregating",
|
|
2717
2484
|
currentAgent: "aggregator"
|
|
2718
2485
|
};
|
|
2719
2486
|
}
|
|
2720
|
-
|
|
2487
|
+
logger2.debug("Getting routing strategy", { strategy });
|
|
2721
2488
|
const routingImpl = getRoutingStrategy(strategy);
|
|
2722
2489
|
const decision = await routingImpl.route(state, config);
|
|
2723
2490
|
const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
|
|
2724
|
-
|
|
2491
|
+
logger2.debug("Target agents determined", {
|
|
2725
2492
|
targetAgents,
|
|
2726
2493
|
isParallel: targetAgents.length > 1,
|
|
2727
2494
|
decision: {
|
|
@@ -2730,17 +2497,17 @@ function createSupervisorNode(config) {
|
|
|
2730
2497
|
}
|
|
2731
2498
|
});
|
|
2732
2499
|
if (targetAgents.length === 0) {
|
|
2733
|
-
|
|
2500
|
+
logger2.error("No target agents specified in routing decision");
|
|
2734
2501
|
throw new Error("Routing decision must specify at least one target agent");
|
|
2735
2502
|
}
|
|
2736
2503
|
if (targetAgents.length === 1) {
|
|
2737
|
-
|
|
2504
|
+
logger2.info("Routing to single agent", {
|
|
2738
2505
|
targetAgent: targetAgents[0],
|
|
2739
2506
|
reasoning: decision.reasoning,
|
|
2740
2507
|
confidence: decision.confidence
|
|
2741
2508
|
});
|
|
2742
2509
|
} else {
|
|
2743
|
-
|
|
2510
|
+
logger2.info("Routing to multiple agents in parallel", {
|
|
2744
2511
|
targetAgents,
|
|
2745
2512
|
count: targetAgents.length,
|
|
2746
2513
|
reasoning: decision.reasoning,
|
|
@@ -2748,9 +2515,9 @@ function createSupervisorNode(config) {
|
|
|
2748
2515
|
});
|
|
2749
2516
|
}
|
|
2750
2517
|
if (targetAgents.length === 1) {
|
|
2751
|
-
|
|
2518
|
+
logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
|
|
2752
2519
|
} else {
|
|
2753
|
-
|
|
2520
|
+
logger2.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
|
|
2754
2521
|
}
|
|
2755
2522
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2756
2523
|
const assignments = targetAgents.map((workerId) => ({
|
|
@@ -2760,7 +2527,7 @@ function createSupervisorNode(config) {
|
|
|
2760
2527
|
priority: 5,
|
|
2761
2528
|
assignedAt: Date.now()
|
|
2762
2529
|
}));
|
|
2763
|
-
|
|
2530
|
+
logger2.debug("Created task assignments", {
|
|
2764
2531
|
assignmentCount: assignments.length,
|
|
2765
2532
|
assignments: assignments.map((a) => ({
|
|
2766
2533
|
id: a.id,
|
|
@@ -2780,7 +2547,7 @@ function createSupervisorNode(config) {
|
|
|
2780
2547
|
priority: assignment.priority
|
|
2781
2548
|
}
|
|
2782
2549
|
}));
|
|
2783
|
-
|
|
2550
|
+
logger2.info("Supervisor routing complete", {
|
|
2784
2551
|
currentAgent: targetAgents.join(","),
|
|
2785
2552
|
status: "executing",
|
|
2786
2553
|
assignmentCount: assignments.length,
|
|
@@ -2797,7 +2564,7 @@ function createSupervisorNode(config) {
|
|
|
2797
2564
|
iteration: state.iteration + 1
|
|
2798
2565
|
};
|
|
2799
2566
|
} catch (error) {
|
|
2800
|
-
|
|
2567
|
+
logger2.error("Supervisor node error", {
|
|
2801
2568
|
error: error instanceof Error ? error.message : String(error),
|
|
2802
2569
|
stack: error instanceof Error ? error.stack : void 0,
|
|
2803
2570
|
iteration: state.iteration
|
|
@@ -2822,7 +2589,7 @@ function createWorkerNode(config) {
|
|
|
2822
2589
|
} = config;
|
|
2823
2590
|
return async (state, runConfig) => {
|
|
2824
2591
|
try {
|
|
2825
|
-
|
|
2592
|
+
logger2.info("Worker node executing", {
|
|
2826
2593
|
workerId: id,
|
|
2827
2594
|
iteration: state.iteration,
|
|
2828
2595
|
activeAssignments: state.activeAssignments.length
|
|
@@ -2831,39 +2598,39 @@ function createWorkerNode(config) {
|
|
|
2831
2598
|
(assignment) => assignment.workerId === id && !state.completedTasks.some((task) => task.assignmentId === assignment.id)
|
|
2832
2599
|
);
|
|
2833
2600
|
if (!currentAssignment) {
|
|
2834
|
-
|
|
2601
|
+
logger2.debug("No active assignment found for worker", {
|
|
2835
2602
|
workerId: id,
|
|
2836
2603
|
totalActiveAssignments: state.activeAssignments.length,
|
|
2837
2604
|
completedTasks: state.completedTasks.length
|
|
2838
2605
|
});
|
|
2839
2606
|
return {};
|
|
2840
2607
|
}
|
|
2841
|
-
|
|
2608
|
+
logger2.info("Worker processing assignment", {
|
|
2842
2609
|
workerId: id,
|
|
2843
2610
|
assignmentId: currentAssignment.id,
|
|
2844
2611
|
taskLength: currentAssignment.task.length,
|
|
2845
2612
|
taskPreview: currentAssignment.task.substring(0, 100)
|
|
2846
2613
|
});
|
|
2847
2614
|
if (executeFn) {
|
|
2848
|
-
|
|
2615
|
+
logger2.debug("Using custom execution function", { workerId: id });
|
|
2849
2616
|
return await executeFn(state, runConfig);
|
|
2850
2617
|
}
|
|
2851
2618
|
if (agent) {
|
|
2852
2619
|
if (isReActAgent(agent)) {
|
|
2853
|
-
|
|
2620
|
+
logger2.debug("Using ReAct agent", { workerId: id });
|
|
2854
2621
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2855
2622
|
return await wrappedFn(state, runConfig);
|
|
2856
2623
|
} else {
|
|
2857
|
-
|
|
2624
|
+
logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
|
|
2858
2625
|
}
|
|
2859
2626
|
}
|
|
2860
2627
|
if (!model) {
|
|
2861
|
-
|
|
2628
|
+
logger2.error("Worker missing required configuration", { workerId: id });
|
|
2862
2629
|
throw new Error(
|
|
2863
2630
|
`Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
|
|
2864
2631
|
);
|
|
2865
2632
|
}
|
|
2866
|
-
|
|
2633
|
+
logger2.debug("Using default LLM execution", {
|
|
2867
2634
|
workerId: id,
|
|
2868
2635
|
hasTools: tools.length > 0,
|
|
2869
2636
|
toolCount: tools.length
|
|
@@ -2879,18 +2646,18 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2879
2646
|
];
|
|
2880
2647
|
let modelToUse = model;
|
|
2881
2648
|
if (tools.length > 0 && model.bindTools) {
|
|
2882
|
-
|
|
2649
|
+
logger2.debug("Binding tools to model", {
|
|
2883
2650
|
workerId: id,
|
|
2884
2651
|
toolCount: tools.length,
|
|
2885
2652
|
toolNames: tools.map((t) => t.metadata.name)
|
|
2886
2653
|
});
|
|
2887
|
-
const langchainTools = (0,
|
|
2654
|
+
const langchainTools = (0, import_core9.toLangChainTools)(tools);
|
|
2888
2655
|
modelToUse = model.bindTools(langchainTools);
|
|
2889
2656
|
}
|
|
2890
|
-
|
|
2657
|
+
logger2.debug("Invoking LLM", { workerId: id });
|
|
2891
2658
|
const response = await modelToUse.invoke(messages);
|
|
2892
2659
|
const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
2893
|
-
|
|
2660
|
+
logger2.info("Worker task completed", {
|
|
2894
2661
|
workerId: id,
|
|
2895
2662
|
assignmentId: currentAssignment.id,
|
|
2896
2663
|
resultLength: result.length,
|
|
@@ -2925,7 +2692,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2925
2692
|
currentWorkload: Math.max(0, capabilities.currentWorkload - 1)
|
|
2926
2693
|
}
|
|
2927
2694
|
};
|
|
2928
|
-
|
|
2695
|
+
logger2.debug("Worker state update", {
|
|
2929
2696
|
workerId: id,
|
|
2930
2697
|
newWorkload: updatedWorkers[id].currentWorkload
|
|
2931
2698
|
});
|
|
@@ -2935,20 +2702,16 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2935
2702
|
workers: updatedWorkers
|
|
2936
2703
|
};
|
|
2937
2704
|
} catch (error) {
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
throw error;
|
|
2941
|
-
}
|
|
2942
|
-
logger3.error("Worker node error", {
|
|
2705
|
+
const errorMessage = handleNodeError(error, `worker:${id}`, false);
|
|
2706
|
+
logger2.error("Worker node error", {
|
|
2943
2707
|
workerId: id,
|
|
2944
|
-
error:
|
|
2945
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
2708
|
+
error: errorMessage
|
|
2946
2709
|
});
|
|
2947
2710
|
const currentAssignment = state.activeAssignments.find(
|
|
2948
2711
|
(assignment) => assignment.workerId === id
|
|
2949
2712
|
);
|
|
2950
2713
|
if (currentAssignment) {
|
|
2951
|
-
|
|
2714
|
+
logger2.warn("Creating error result for assignment", {
|
|
2952
2715
|
workerId: id,
|
|
2953
2716
|
assignmentId: currentAssignment.id
|
|
2954
2717
|
});
|
|
@@ -2957,7 +2720,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2957
2720
|
workerId: id,
|
|
2958
2721
|
success: false,
|
|
2959
2722
|
result: "",
|
|
2960
|
-
error:
|
|
2723
|
+
error: errorMessage,
|
|
2961
2724
|
completedAt: Date.now()
|
|
2962
2725
|
};
|
|
2963
2726
|
return {
|
|
@@ -2966,10 +2729,10 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2966
2729
|
status: "routing"
|
|
2967
2730
|
};
|
|
2968
2731
|
}
|
|
2969
|
-
|
|
2732
|
+
logger2.error("No assignment found for error handling", { workerId: id });
|
|
2970
2733
|
return {
|
|
2971
2734
|
status: "failed",
|
|
2972
|
-
error:
|
|
2735
|
+
error: errorMessage
|
|
2973
2736
|
};
|
|
2974
2737
|
}
|
|
2975
2738
|
};
|
|
@@ -2983,16 +2746,16 @@ function createAggregatorNode(config = {}) {
|
|
|
2983
2746
|
} = config;
|
|
2984
2747
|
return async (state) => {
|
|
2985
2748
|
try {
|
|
2986
|
-
|
|
2749
|
+
logger2.info("Aggregator node executing", {
|
|
2987
2750
|
completedTasks: state.completedTasks.length,
|
|
2988
2751
|
successfulTasks: state.completedTasks.filter((t) => t.success).length,
|
|
2989
2752
|
failedTasks: state.completedTasks.filter((t) => !t.success).length
|
|
2990
2753
|
});
|
|
2991
|
-
|
|
2754
|
+
logger2.debug("Combining results from workers");
|
|
2992
2755
|
if (aggregateFn) {
|
|
2993
|
-
|
|
2756
|
+
logger2.debug("Using custom aggregation function");
|
|
2994
2757
|
const response2 = await aggregateFn(state);
|
|
2995
|
-
|
|
2758
|
+
logger2.info("Custom aggregation complete", {
|
|
2996
2759
|
responseLength: response2.length
|
|
2997
2760
|
});
|
|
2998
2761
|
return {
|
|
@@ -3001,16 +2764,16 @@ function createAggregatorNode(config = {}) {
|
|
|
3001
2764
|
};
|
|
3002
2765
|
}
|
|
3003
2766
|
if (state.completedTasks.length === 0) {
|
|
3004
|
-
|
|
2767
|
+
logger2.warn("No completed tasks to aggregate");
|
|
3005
2768
|
return {
|
|
3006
2769
|
response: "No tasks were completed.",
|
|
3007
2770
|
status: "completed"
|
|
3008
2771
|
};
|
|
3009
2772
|
}
|
|
3010
2773
|
if (!model) {
|
|
3011
|
-
|
|
2774
|
+
logger2.debug("No model provided, concatenating results");
|
|
3012
2775
|
const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
|
|
3013
|
-
|
|
2776
|
+
logger2.info("Simple concatenation complete", {
|
|
3014
2777
|
resultLength: combinedResults.length
|
|
3015
2778
|
});
|
|
3016
2779
|
return {
|
|
@@ -3018,7 +2781,7 @@ function createAggregatorNode(config = {}) {
|
|
|
3018
2781
|
status: "completed"
|
|
3019
2782
|
};
|
|
3020
2783
|
}
|
|
3021
|
-
|
|
2784
|
+
logger2.debug("Using LLM for intelligent aggregation", {
|
|
3022
2785
|
taskCount: state.completedTasks.length
|
|
3023
2786
|
});
|
|
3024
2787
|
const taskResults = state.completedTasks.map((task, idx) => {
|
|
@@ -3037,20 +2800,20 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
3037
2800
|
new import_messages5.SystemMessage(systemPrompt),
|
|
3038
2801
|
new import_messages5.HumanMessage(userPrompt)
|
|
3039
2802
|
];
|
|
3040
|
-
|
|
2803
|
+
logger2.debug("Invoking aggregation LLM");
|
|
3041
2804
|
const response = await model.invoke(messages);
|
|
3042
2805
|
const aggregatedResponse = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
3043
|
-
|
|
2806
|
+
logger2.info("Aggregation complete", {
|
|
3044
2807
|
responseLength: aggregatedResponse.length,
|
|
3045
2808
|
responsePreview: aggregatedResponse.substring(0, 100)
|
|
3046
2809
|
});
|
|
3047
|
-
|
|
2810
|
+
logger2.debug("Aggregation complete");
|
|
3048
2811
|
return {
|
|
3049
2812
|
response: aggregatedResponse,
|
|
3050
2813
|
status: "completed"
|
|
3051
2814
|
};
|
|
3052
2815
|
} catch (error) {
|
|
3053
|
-
|
|
2816
|
+
logger2.error("Aggregator node error", {
|
|
3054
2817
|
error: error instanceof Error ? error.message : String(error),
|
|
3055
2818
|
stack: error instanceof Error ? error.stack : void 0,
|
|
3056
2819
|
completedTasks: state.completedTasks.length
|
|
@@ -3065,9 +2828,9 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
3065
2828
|
|
|
3066
2829
|
// src/multi-agent/agent.ts
|
|
3067
2830
|
var import_langgraph4 = require("@langchain/langgraph");
|
|
3068
|
-
var
|
|
3069
|
-
var
|
|
3070
|
-
var
|
|
2831
|
+
var import_core10 = require("@agentforge/core");
|
|
2832
|
+
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || import_core10.LogLevel.INFO;
|
|
2833
|
+
var logger3 = (0, import_core10.createLogger)("multi-agent:system", { level: logLevel3 });
|
|
3071
2834
|
function createMultiAgentSystem(config) {
|
|
3072
2835
|
const {
|
|
3073
2836
|
supervisor,
|
|
@@ -3084,10 +2847,6 @@ function createMultiAgentSystem(config) {
|
|
|
3084
2847
|
if (supervisor.strategy === "llm-based") {
|
|
3085
2848
|
configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
|
|
3086
2849
|
}
|
|
3087
|
-
if (supervisor.tools && supervisor.tools.length > 0) {
|
|
3088
|
-
const langchainTools = (0, import_core11.toLangChainTools)(supervisor.tools);
|
|
3089
|
-
configuredModel = configuredModel.bindTools(langchainTools);
|
|
3090
|
-
}
|
|
3091
2850
|
supervisorConfig.model = configuredModel;
|
|
3092
2851
|
}
|
|
3093
2852
|
const supervisorNode = createSupervisorNode(supervisorConfig);
|
|
@@ -3109,46 +2868,46 @@ function createMultiAgentSystem(config) {
|
|
|
3109
2868
|
});
|
|
3110
2869
|
workflow.addNode("aggregator", aggregatorNode);
|
|
3111
2870
|
const supervisorRouter = (state) => {
|
|
3112
|
-
|
|
2871
|
+
logger3.debug("Supervisor router executing", {
|
|
3113
2872
|
status: state.status,
|
|
3114
2873
|
currentAgent: state.currentAgent,
|
|
3115
2874
|
iteration: state.iteration
|
|
3116
2875
|
});
|
|
3117
2876
|
if (state.status === "completed" || state.status === "failed") {
|
|
3118
|
-
|
|
2877
|
+
logger3.info("Supervisor router: ending workflow", { status: state.status });
|
|
3119
2878
|
return import_langgraph4.END;
|
|
3120
2879
|
}
|
|
3121
2880
|
if (state.status === "aggregating") {
|
|
3122
|
-
|
|
2881
|
+
logger3.info("Supervisor router: routing to aggregator");
|
|
3123
2882
|
return "aggregator";
|
|
3124
2883
|
}
|
|
3125
2884
|
if (state.currentAgent && state.currentAgent !== "supervisor") {
|
|
3126
2885
|
if (state.currentAgent.includes(",")) {
|
|
3127
2886
|
const agents = state.currentAgent.split(",").map((a) => a.trim());
|
|
3128
|
-
|
|
2887
|
+
logger3.info("Supervisor router: parallel routing", {
|
|
3129
2888
|
agents,
|
|
3130
2889
|
count: agents.length
|
|
3131
2890
|
});
|
|
3132
2891
|
return agents;
|
|
3133
2892
|
}
|
|
3134
|
-
|
|
2893
|
+
logger3.info("Supervisor router: single agent routing", {
|
|
3135
2894
|
targetAgent: state.currentAgent
|
|
3136
2895
|
});
|
|
3137
2896
|
return state.currentAgent;
|
|
3138
2897
|
}
|
|
3139
|
-
|
|
2898
|
+
logger3.debug("Supervisor router: staying at supervisor");
|
|
3140
2899
|
return "supervisor";
|
|
3141
2900
|
};
|
|
3142
2901
|
const workerRouter = (state) => {
|
|
3143
|
-
|
|
2902
|
+
logger3.debug("Worker router executing", {
|
|
3144
2903
|
iteration: state.iteration,
|
|
3145
2904
|
completedTasks: state.completedTasks.length
|
|
3146
2905
|
});
|
|
3147
|
-
|
|
2906
|
+
logger3.debug("Worker router: returning to supervisor");
|
|
3148
2907
|
return "supervisor";
|
|
3149
2908
|
};
|
|
3150
2909
|
const aggregatorRouter = (state) => {
|
|
3151
|
-
|
|
2910
|
+
logger3.info("Aggregator router: ending workflow", {
|
|
3152
2911
|
completedTasks: state.completedTasks.length,
|
|
3153
2912
|
status: state.status
|
|
3154
2913
|
});
|