@agentforge/patterns 0.16.15 → 0.16.17
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 +94 -39
- package/dist/index.d.cts +3 -20
- package/dist/index.d.ts +3 -20
- package/dist/index.js +94 -39
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1012,7 +1012,7 @@ var PlanExecuteStateConfig = {
|
|
|
1012
1012
|
};
|
|
1013
1013
|
var PlanExecuteState = (0, import_core5.createStateAnnotation)(PlanExecuteStateConfig);
|
|
1014
1014
|
|
|
1015
|
-
// src/plan-execute/
|
|
1015
|
+
// src/plan-execute/planner-node.ts
|
|
1016
1016
|
var import_messages2 = require("@langchain/core/messages");
|
|
1017
1017
|
|
|
1018
1018
|
// src/plan-execute/prompts.ts
|
|
@@ -1074,13 +1074,61 @@ Status: {status}`;
|
|
|
1074
1074
|
var REMAINING_STEP_TEMPLATE = `Step {stepNumber}: {description}
|
|
1075
1075
|
{dependencies}`;
|
|
1076
1076
|
|
|
1077
|
-
// src/plan-execute/
|
|
1077
|
+
// src/plan-execute/node-loggers.ts
|
|
1078
1078
|
var plannerLogger = createPatternLogger("agentforge:patterns:plan-execute:planner");
|
|
1079
1079
|
var executorLogger = createPatternLogger("agentforge:patterns:plan-execute:executor");
|
|
1080
1080
|
var replannerLogger = createPatternLogger("agentforge:patterns:plan-execute:replanner");
|
|
1081
|
-
|
|
1082
|
-
|
|
1081
|
+
|
|
1082
|
+
// src/plan-execute/serialization.ts
|
|
1083
|
+
function hasTextContentPart(value) {
|
|
1084
|
+
return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
|
|
1085
|
+
}
|
|
1086
|
+
function stringifyWithFallback(value, fallbackLabel) {
|
|
1087
|
+
try {
|
|
1088
|
+
const serialized = JSON.stringify(value);
|
|
1089
|
+
if (serialized === void 0) {
|
|
1090
|
+
return "undefined";
|
|
1091
|
+
}
|
|
1092
|
+
return serialized;
|
|
1093
|
+
} catch (error) {
|
|
1094
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1095
|
+
return `[${fallbackLabel}: ${reason}]`;
|
|
1096
|
+
}
|
|
1083
1097
|
}
|
|
1098
|
+
function toJsonSafeValue(value) {
|
|
1099
|
+
try {
|
|
1100
|
+
const serialized = JSON.stringify(value);
|
|
1101
|
+
if (serialized === void 0) {
|
|
1102
|
+
return void 0;
|
|
1103
|
+
}
|
|
1104
|
+
return JSON.parse(serialized);
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1107
|
+
return `[Unserializable step result: ${reason}]`;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function normalizeModelContent(content) {
|
|
1111
|
+
if (typeof content === "string") {
|
|
1112
|
+
return content;
|
|
1113
|
+
}
|
|
1114
|
+
if (Array.isArray(content)) {
|
|
1115
|
+
const textParts = [];
|
|
1116
|
+
for (const part of content) {
|
|
1117
|
+
if (hasTextContentPart(part) && part.text.length > 0) {
|
|
1118
|
+
textParts.push(part.text);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (textParts.length > 0) {
|
|
1122
|
+
return textParts.join("\n");
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
return stringifyWithFallback(content, "Unserializable model content");
|
|
1126
|
+
}
|
|
1127
|
+
function serializePlanExecuteResult(result) {
|
|
1128
|
+
return stringifyWithFallback(result, "Unserializable step result");
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// src/plan-execute/planner-node.ts
|
|
1084
1132
|
function createPlannerNode(config) {
|
|
1085
1133
|
const {
|
|
1086
1134
|
model,
|
|
@@ -1106,13 +1154,12 @@ function createPlannerNode(config) {
|
|
|
1106
1154
|
new import_messages2.HumanMessage(userPrompt)
|
|
1107
1155
|
];
|
|
1108
1156
|
const response = await model.invoke(messages);
|
|
1109
|
-
const content = response.content
|
|
1157
|
+
const content = normalizeModelContent(response.content);
|
|
1110
1158
|
let plan;
|
|
1111
1159
|
try {
|
|
1112
1160
|
const parsed = JSON.parse(content);
|
|
1113
1161
|
plan = {
|
|
1114
1162
|
steps: parsed.steps.slice(0, maxSteps),
|
|
1115
|
-
// Limit to maxSteps
|
|
1116
1163
|
goal: parsed.goal || state.input || "",
|
|
1117
1164
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1118
1165
|
confidence: parsed.confidence
|
|
@@ -1144,6 +1191,11 @@ function createPlannerNode(config) {
|
|
|
1144
1191
|
}
|
|
1145
1192
|
};
|
|
1146
1193
|
}
|
|
1194
|
+
|
|
1195
|
+
// src/plan-execute/executor-node.ts
|
|
1196
|
+
function invokePlanExecuteTool(tool, args) {
|
|
1197
|
+
return tool.invoke.call(tool, args);
|
|
1198
|
+
}
|
|
1147
1199
|
function createExecutorNode(config) {
|
|
1148
1200
|
const {
|
|
1149
1201
|
tools,
|
|
@@ -1170,14 +1222,10 @@ function createExecutorNode(config) {
|
|
|
1170
1222
|
deduplicationEnabled: enableDeduplication
|
|
1171
1223
|
});
|
|
1172
1224
|
if (!plan || !plan.steps || plan.steps.length === 0) {
|
|
1173
|
-
return {
|
|
1174
|
-
status: "completed"
|
|
1175
|
-
};
|
|
1225
|
+
return { status: "completed" };
|
|
1176
1226
|
}
|
|
1177
1227
|
if (currentStepIndex >= plan.steps.length) {
|
|
1178
|
-
return {
|
|
1179
|
-
status: "completed"
|
|
1180
|
-
};
|
|
1228
|
+
return { status: "completed" };
|
|
1181
1229
|
}
|
|
1182
1230
|
const currentStep = plan.steps[currentStepIndex];
|
|
1183
1231
|
if (currentStep.dependencies && currentStep.dependencies.length > 0) {
|
|
@@ -1231,7 +1279,7 @@ function createExecutorNode(config) {
|
|
|
1231
1279
|
}
|
|
1232
1280
|
}
|
|
1233
1281
|
if (!isDuplicate) {
|
|
1234
|
-
const tool = tools.find((
|
|
1282
|
+
const tool = tools.find((candidate) => candidate.metadata.name === currentStep.tool);
|
|
1235
1283
|
if (!tool) {
|
|
1236
1284
|
throw new Error(`Tool not found: ${currentStep.tool}`);
|
|
1237
1285
|
}
|
|
@@ -1292,6 +1340,9 @@ function createExecutorNode(config) {
|
|
|
1292
1340
|
currentStepIndex: currentStepIndex + 1
|
|
1293
1341
|
};
|
|
1294
1342
|
} catch (error) {
|
|
1343
|
+
if (isGraphInterrupt(error)) {
|
|
1344
|
+
throw error;
|
|
1345
|
+
}
|
|
1295
1346
|
executorLogger.error("Executor node failed", {
|
|
1296
1347
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
1297
1348
|
iteration
|
|
@@ -1303,6 +1354,9 @@ function createExecutorNode(config) {
|
|
|
1303
1354
|
}
|
|
1304
1355
|
};
|
|
1305
1356
|
}
|
|
1357
|
+
|
|
1358
|
+
// src/plan-execute/replanner-node.ts
|
|
1359
|
+
var import_messages3 = require("@langchain/core/messages");
|
|
1306
1360
|
function createReplannerNode(config) {
|
|
1307
1361
|
const {
|
|
1308
1362
|
model,
|
|
@@ -1328,19 +1382,19 @@ function createReplannerNode(config) {
|
|
|
1328
1382
|
failedSteps: pastSteps.filter((ps) => !ps.success).length
|
|
1329
1383
|
});
|
|
1330
1384
|
const completedStepsText = pastSteps.map(
|
|
1331
|
-
(ps, idx) => COMPLETED_STEP_TEMPLATE.replace("{stepNumber}", String(idx + 1)).replace("{description}", ps.step.description).replace("{result}",
|
|
1385
|
+
(ps, idx) => COMPLETED_STEP_TEMPLATE.replace("{stepNumber}", String(idx + 1)).replace("{description}", ps.step.description).replace("{result}", serializePlanExecuteResult(ps.result)).replace("{status}", ps.success ? "Success" : `Failed: ${ps.error}`)
|
|
1332
1386
|
).join("\n\n");
|
|
1333
1387
|
const remainingSteps = plan.steps.slice(currentStepIndex);
|
|
1334
1388
|
const remainingStepsText = remainingSteps.map(
|
|
1335
|
-
(step, idx) => REMAINING_STEP_TEMPLATE.replace("{stepNumber}", String(currentStepIndex + idx + 1)).replace("{description}", step.description).replace("{dependencies}", step.dependencies ? `Dependencies: ${step.dependencies.join(", ")}` : "")
|
|
1389
|
+
(step, idx) => REMAINING_STEP_TEMPLATE.replace("{stepNumber}", String(currentStepIndex + idx + 1)).replace("{description}", step.description).replace("{dependencies}", step.dependencies?.length ? `Dependencies: ${step.dependencies.join(", ")}` : "")
|
|
1336
1390
|
).join("\n\n");
|
|
1337
1391
|
const userPrompt = REPLANNING_PROMPT_TEMPLATE.replace("{goal}", plan.goal).replace("{completedSteps}", completedStepsText || "None").replace("{remainingSteps}", remainingStepsText || "None");
|
|
1338
1392
|
const messages = [
|
|
1339
|
-
new
|
|
1340
|
-
new
|
|
1393
|
+
new import_messages3.SystemMessage(systemPrompt),
|
|
1394
|
+
new import_messages3.HumanMessage(userPrompt)
|
|
1341
1395
|
];
|
|
1342
1396
|
const response = await model.invoke(messages);
|
|
1343
|
-
const content = response.content
|
|
1397
|
+
const content = normalizeModelContent(response.content);
|
|
1344
1398
|
let decision;
|
|
1345
1399
|
try {
|
|
1346
1400
|
decision = JSON.parse(content);
|
|
@@ -1358,15 +1412,14 @@ function createReplannerNode(config) {
|
|
|
1358
1412
|
input: decision.newGoal || plan.goal,
|
|
1359
1413
|
iteration: 1
|
|
1360
1414
|
};
|
|
1361
|
-
} else {
|
|
1362
|
-
replannerLogger.info("Continuing with current plan", {
|
|
1363
|
-
reason: decision.reason,
|
|
1364
|
-
duration: Date.now() - startTime
|
|
1365
|
-
});
|
|
1366
|
-
return {
|
|
1367
|
-
status: "executing"
|
|
1368
|
-
};
|
|
1369
1415
|
}
|
|
1416
|
+
replannerLogger.info("Continuing with current plan", {
|
|
1417
|
+
reason: decision.reason,
|
|
1418
|
+
duration: Date.now() - startTime
|
|
1419
|
+
});
|
|
1420
|
+
return {
|
|
1421
|
+
status: "executing"
|
|
1422
|
+
};
|
|
1370
1423
|
} catch (error) {
|
|
1371
1424
|
replannerLogger.error("Replanning evaluation failed", {
|
|
1372
1425
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -1379,11 +1432,13 @@ function createReplannerNode(config) {
|
|
|
1379
1432
|
}
|
|
1380
1433
|
};
|
|
1381
1434
|
}
|
|
1435
|
+
|
|
1436
|
+
// src/plan-execute/finisher-node.ts
|
|
1382
1437
|
function createFinisherNode() {
|
|
1383
1438
|
return async (state) => {
|
|
1384
1439
|
const results = state.pastSteps?.map((ps) => ({
|
|
1385
1440
|
step: ps.step.description,
|
|
1386
|
-
result: ps.result,
|
|
1441
|
+
result: toJsonSafeValue(ps.result),
|
|
1387
1442
|
success: ps.success
|
|
1388
1443
|
})) || [];
|
|
1389
1444
|
const response = JSON.stringify({
|
|
@@ -1729,7 +1784,7 @@ var REVISION_ENTRY_TEMPLATE = `Iteration {iteration}:
|
|
|
1729
1784
|
{content}`;
|
|
1730
1785
|
|
|
1731
1786
|
// src/reflection/nodes.ts
|
|
1732
|
-
var
|
|
1787
|
+
var import_messages4 = require("@langchain/core/messages");
|
|
1733
1788
|
var generatorLogger = createPatternLogger("agentforge:patterns:reflection:generator");
|
|
1734
1789
|
var reflectorLogger = createPatternLogger("agentforge:patterns:reflection:reflector");
|
|
1735
1790
|
var reviserLogger = createPatternLogger("agentforge:patterns:reflection:reviser");
|
|
@@ -1756,8 +1811,8 @@ ${lastReflection.critique}`;
|
|
|
1756
1811
|
}
|
|
1757
1812
|
const userPrompt = GENERATION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{context}", context);
|
|
1758
1813
|
const messages = [
|
|
1759
|
-
new
|
|
1760
|
-
new
|
|
1814
|
+
new import_messages4.SystemMessage(systemPrompt),
|
|
1815
|
+
new import_messages4.HumanMessage(userPrompt)
|
|
1761
1816
|
];
|
|
1762
1817
|
const response = await model.invoke(messages);
|
|
1763
1818
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -1822,8 +1877,8 @@ function createReflectorNode(config) {
|
|
|
1822
1877
|
}
|
|
1823
1878
|
const userPrompt = REFLECTION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{currentResponse}", state.currentResponse).replace("{criteria}", criteriaSection).replace("{history}", historySection);
|
|
1824
1879
|
const messages = [
|
|
1825
|
-
new
|
|
1826
|
-
new
|
|
1880
|
+
new import_messages4.SystemMessage(systemPrompt),
|
|
1881
|
+
new import_messages4.HumanMessage(userPrompt)
|
|
1827
1882
|
];
|
|
1828
1883
|
const response = await model.invoke(messages);
|
|
1829
1884
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -1909,8 +1964,8 @@ ${revisionsText}`;
|
|
|
1909
1964
|
}
|
|
1910
1965
|
const userPrompt = REVISION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{currentResponse}", state.currentResponse).replace("{critique}", lastReflection.critique).replace("{issues}", lastReflection.issues.join("\n- ")).replace("{suggestions}", lastReflection.suggestions.join("\n- ")).replace("{history}", historySection);
|
|
1911
1966
|
const messages = [
|
|
1912
|
-
new
|
|
1913
|
-
new
|
|
1967
|
+
new import_messages4.SystemMessage(systemPrompt),
|
|
1968
|
+
new import_messages4.HumanMessage(userPrompt)
|
|
1914
1969
|
];
|
|
1915
1970
|
const response = await model.invoke(messages);
|
|
1916
1971
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -2337,7 +2392,7 @@ var MultiAgentStateConfig = {
|
|
|
2337
2392
|
var MultiAgentState = (0, import_core7.createStateAnnotation)(MultiAgentStateConfig);
|
|
2338
2393
|
|
|
2339
2394
|
// src/multi-agent/routing.ts
|
|
2340
|
-
var
|
|
2395
|
+
var import_messages5 = require("@langchain/core/messages");
|
|
2341
2396
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
2342
2397
|
|
|
2343
2398
|
Your job is to:
|
|
@@ -2392,8 +2447,8 @@ ${workerInfo}
|
|
|
2392
2447
|
|
|
2393
2448
|
Select the best worker(s) for this task and explain your reasoning.`;
|
|
2394
2449
|
const messages = [
|
|
2395
|
-
new
|
|
2396
|
-
new
|
|
2450
|
+
new import_messages5.SystemMessage(systemPrompt),
|
|
2451
|
+
new import_messages5.HumanMessage(userPrompt)
|
|
2397
2452
|
];
|
|
2398
2453
|
const decision = await config.model.invoke(messages);
|
|
2399
2454
|
return {
|
|
@@ -2686,7 +2741,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2686
2741
|
}
|
|
2687
2742
|
|
|
2688
2743
|
// src/multi-agent/nodes/shared.ts
|
|
2689
|
-
var
|
|
2744
|
+
var import_messages6 = require("@langchain/core/messages");
|
|
2690
2745
|
var import_core8 = require("@agentforge/core");
|
|
2691
2746
|
var logger2 = createPatternLogger("agentforge:patterns:multi-agent:nodes");
|
|
2692
2747
|
function createGeneratedId(prefix) {
|
|
@@ -2757,7 +2812,7 @@ function serializeModelContent(content) {
|
|
|
2757
2812
|
}
|
|
2758
2813
|
}
|
|
2759
2814
|
function createPromptMessages(systemPrompt, task) {
|
|
2760
|
-
return [new
|
|
2815
|
+
return [new import_messages6.SystemMessage(systemPrompt), new import_messages6.HumanMessage(task)];
|
|
2761
2816
|
}
|
|
2762
2817
|
|
|
2763
2818
|
// src/multi-agent/nodes/aggregator.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1426,29 +1426,12 @@ declare function createPlanExecuteAgent<TTool extends PlanExecuteTool = PlanExec
|
|
|
1426
1426
|
replanner: Partial<PlanExecuteStateType>;
|
|
1427
1427
|
}, unknown, unknown>;
|
|
1428
1428
|
|
|
1429
|
-
/**
|
|
1430
|
-
* Node Implementations for Plan-and-Execute Pattern
|
|
1431
|
-
*
|
|
1432
|
-
* This module implements the core nodes for the Plan-and-Execute agent pattern.
|
|
1433
|
-
*
|
|
1434
|
-
* @module patterns/plan-execute/nodes
|
|
1435
|
-
*/
|
|
1436
|
-
|
|
1437
|
-
/**
|
|
1438
|
-
* Create a planner node that generates a multi-step plan
|
|
1439
|
-
*/
|
|
1440
1429
|
declare function createPlannerNode(config: PlannerConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1441
|
-
|
|
1442
|
-
* Create an executor node that executes plan steps
|
|
1443
|
-
*/
|
|
1430
|
+
|
|
1444
1431
|
declare function createExecutorNode(config: ExecutorConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1445
|
-
|
|
1446
|
-
* Create a replanner node that decides whether to replan
|
|
1447
|
-
*/
|
|
1432
|
+
|
|
1448
1433
|
declare function createReplannerNode(config: ReplannerConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1449
|
-
|
|
1450
|
-
* Create a finisher node that sets the final status and response
|
|
1451
|
-
*/
|
|
1434
|
+
|
|
1452
1435
|
declare function createFinisherNode$1(): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1453
1436
|
|
|
1454
1437
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1426,29 +1426,12 @@ declare function createPlanExecuteAgent<TTool extends PlanExecuteTool = PlanExec
|
|
|
1426
1426
|
replanner: Partial<PlanExecuteStateType>;
|
|
1427
1427
|
}, unknown, unknown>;
|
|
1428
1428
|
|
|
1429
|
-
/**
|
|
1430
|
-
* Node Implementations for Plan-and-Execute Pattern
|
|
1431
|
-
*
|
|
1432
|
-
* This module implements the core nodes for the Plan-and-Execute agent pattern.
|
|
1433
|
-
*
|
|
1434
|
-
* @module patterns/plan-execute/nodes
|
|
1435
|
-
*/
|
|
1436
|
-
|
|
1437
|
-
/**
|
|
1438
|
-
* Create a planner node that generates a multi-step plan
|
|
1439
|
-
*/
|
|
1440
1429
|
declare function createPlannerNode(config: PlannerConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1441
|
-
|
|
1442
|
-
* Create an executor node that executes plan steps
|
|
1443
|
-
*/
|
|
1430
|
+
|
|
1444
1431
|
declare function createExecutorNode(config: ExecutorConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1445
|
-
|
|
1446
|
-
* Create a replanner node that decides whether to replan
|
|
1447
|
-
*/
|
|
1432
|
+
|
|
1448
1433
|
declare function createReplannerNode(config: ReplannerConfig): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1449
|
-
|
|
1450
|
-
* Create a finisher node that sets the final status and response
|
|
1451
|
-
*/
|
|
1434
|
+
|
|
1452
1435
|
declare function createFinisherNode$1(): (state: PlanExecuteStateType) => Promise<Partial<PlanExecuteStateType>>;
|
|
1453
1436
|
|
|
1454
1437
|
/**
|
package/dist/index.js
CHANGED
|
@@ -914,7 +914,7 @@ var PlanExecuteStateConfig = {
|
|
|
914
914
|
};
|
|
915
915
|
var PlanExecuteState = createStateAnnotation2(PlanExecuteStateConfig);
|
|
916
916
|
|
|
917
|
-
// src/plan-execute/
|
|
917
|
+
// src/plan-execute/planner-node.ts
|
|
918
918
|
import { HumanMessage as HumanMessage2, SystemMessage as SystemMessage2 } from "@langchain/core/messages";
|
|
919
919
|
|
|
920
920
|
// src/plan-execute/prompts.ts
|
|
@@ -976,13 +976,61 @@ Status: {status}`;
|
|
|
976
976
|
var REMAINING_STEP_TEMPLATE = `Step {stepNumber}: {description}
|
|
977
977
|
{dependencies}`;
|
|
978
978
|
|
|
979
|
-
// src/plan-execute/
|
|
979
|
+
// src/plan-execute/node-loggers.ts
|
|
980
980
|
var plannerLogger = createPatternLogger("agentforge:patterns:plan-execute:planner");
|
|
981
981
|
var executorLogger = createPatternLogger("agentforge:patterns:plan-execute:executor");
|
|
982
982
|
var replannerLogger = createPatternLogger("agentforge:patterns:plan-execute:replanner");
|
|
983
|
-
|
|
984
|
-
|
|
983
|
+
|
|
984
|
+
// src/plan-execute/serialization.ts
|
|
985
|
+
function hasTextContentPart(value) {
|
|
986
|
+
return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
|
|
987
|
+
}
|
|
988
|
+
function stringifyWithFallback(value, fallbackLabel) {
|
|
989
|
+
try {
|
|
990
|
+
const serialized = JSON.stringify(value);
|
|
991
|
+
if (serialized === void 0) {
|
|
992
|
+
return "undefined";
|
|
993
|
+
}
|
|
994
|
+
return serialized;
|
|
995
|
+
} catch (error) {
|
|
996
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
997
|
+
return `[${fallbackLabel}: ${reason}]`;
|
|
998
|
+
}
|
|
985
999
|
}
|
|
1000
|
+
function toJsonSafeValue(value) {
|
|
1001
|
+
try {
|
|
1002
|
+
const serialized = JSON.stringify(value);
|
|
1003
|
+
if (serialized === void 0) {
|
|
1004
|
+
return void 0;
|
|
1005
|
+
}
|
|
1006
|
+
return JSON.parse(serialized);
|
|
1007
|
+
} catch (error) {
|
|
1008
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1009
|
+
return `[Unserializable step result: ${reason}]`;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
function normalizeModelContent(content) {
|
|
1013
|
+
if (typeof content === "string") {
|
|
1014
|
+
return content;
|
|
1015
|
+
}
|
|
1016
|
+
if (Array.isArray(content)) {
|
|
1017
|
+
const textParts = [];
|
|
1018
|
+
for (const part of content) {
|
|
1019
|
+
if (hasTextContentPart(part) && part.text.length > 0) {
|
|
1020
|
+
textParts.push(part.text);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
if (textParts.length > 0) {
|
|
1024
|
+
return textParts.join("\n");
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return stringifyWithFallback(content, "Unserializable model content");
|
|
1028
|
+
}
|
|
1029
|
+
function serializePlanExecuteResult(result) {
|
|
1030
|
+
return stringifyWithFallback(result, "Unserializable step result");
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// src/plan-execute/planner-node.ts
|
|
986
1034
|
function createPlannerNode(config) {
|
|
987
1035
|
const {
|
|
988
1036
|
model,
|
|
@@ -1008,13 +1056,12 @@ function createPlannerNode(config) {
|
|
|
1008
1056
|
new HumanMessage2(userPrompt)
|
|
1009
1057
|
];
|
|
1010
1058
|
const response = await model.invoke(messages);
|
|
1011
|
-
const content = response.content
|
|
1059
|
+
const content = normalizeModelContent(response.content);
|
|
1012
1060
|
let plan;
|
|
1013
1061
|
try {
|
|
1014
1062
|
const parsed = JSON.parse(content);
|
|
1015
1063
|
plan = {
|
|
1016
1064
|
steps: parsed.steps.slice(0, maxSteps),
|
|
1017
|
-
// Limit to maxSteps
|
|
1018
1065
|
goal: parsed.goal || state.input || "",
|
|
1019
1066
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1020
1067
|
confidence: parsed.confidence
|
|
@@ -1046,6 +1093,11 @@ function createPlannerNode(config) {
|
|
|
1046
1093
|
}
|
|
1047
1094
|
};
|
|
1048
1095
|
}
|
|
1096
|
+
|
|
1097
|
+
// src/plan-execute/executor-node.ts
|
|
1098
|
+
function invokePlanExecuteTool(tool, args) {
|
|
1099
|
+
return tool.invoke.call(tool, args);
|
|
1100
|
+
}
|
|
1049
1101
|
function createExecutorNode(config) {
|
|
1050
1102
|
const {
|
|
1051
1103
|
tools,
|
|
@@ -1072,14 +1124,10 @@ function createExecutorNode(config) {
|
|
|
1072
1124
|
deduplicationEnabled: enableDeduplication
|
|
1073
1125
|
});
|
|
1074
1126
|
if (!plan || !plan.steps || plan.steps.length === 0) {
|
|
1075
|
-
return {
|
|
1076
|
-
status: "completed"
|
|
1077
|
-
};
|
|
1127
|
+
return { status: "completed" };
|
|
1078
1128
|
}
|
|
1079
1129
|
if (currentStepIndex >= plan.steps.length) {
|
|
1080
|
-
return {
|
|
1081
|
-
status: "completed"
|
|
1082
|
-
};
|
|
1130
|
+
return { status: "completed" };
|
|
1083
1131
|
}
|
|
1084
1132
|
const currentStep = plan.steps[currentStepIndex];
|
|
1085
1133
|
if (currentStep.dependencies && currentStep.dependencies.length > 0) {
|
|
@@ -1133,7 +1181,7 @@ function createExecutorNode(config) {
|
|
|
1133
1181
|
}
|
|
1134
1182
|
}
|
|
1135
1183
|
if (!isDuplicate) {
|
|
1136
|
-
const tool = tools.find((
|
|
1184
|
+
const tool = tools.find((candidate) => candidate.metadata.name === currentStep.tool);
|
|
1137
1185
|
if (!tool) {
|
|
1138
1186
|
throw new Error(`Tool not found: ${currentStep.tool}`);
|
|
1139
1187
|
}
|
|
@@ -1194,6 +1242,9 @@ function createExecutorNode(config) {
|
|
|
1194
1242
|
currentStepIndex: currentStepIndex + 1
|
|
1195
1243
|
};
|
|
1196
1244
|
} catch (error) {
|
|
1245
|
+
if (isGraphInterrupt(error)) {
|
|
1246
|
+
throw error;
|
|
1247
|
+
}
|
|
1197
1248
|
executorLogger.error("Executor node failed", {
|
|
1198
1249
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
1199
1250
|
iteration
|
|
@@ -1205,6 +1256,9 @@ function createExecutorNode(config) {
|
|
|
1205
1256
|
}
|
|
1206
1257
|
};
|
|
1207
1258
|
}
|
|
1259
|
+
|
|
1260
|
+
// src/plan-execute/replanner-node.ts
|
|
1261
|
+
import { HumanMessage as HumanMessage3, SystemMessage as SystemMessage3 } from "@langchain/core/messages";
|
|
1208
1262
|
function createReplannerNode(config) {
|
|
1209
1263
|
const {
|
|
1210
1264
|
model,
|
|
@@ -1230,19 +1284,19 @@ function createReplannerNode(config) {
|
|
|
1230
1284
|
failedSteps: pastSteps.filter((ps) => !ps.success).length
|
|
1231
1285
|
});
|
|
1232
1286
|
const completedStepsText = pastSteps.map(
|
|
1233
|
-
(ps, idx) => COMPLETED_STEP_TEMPLATE.replace("{stepNumber}", String(idx + 1)).replace("{description}", ps.step.description).replace("{result}",
|
|
1287
|
+
(ps, idx) => COMPLETED_STEP_TEMPLATE.replace("{stepNumber}", String(idx + 1)).replace("{description}", ps.step.description).replace("{result}", serializePlanExecuteResult(ps.result)).replace("{status}", ps.success ? "Success" : `Failed: ${ps.error}`)
|
|
1234
1288
|
).join("\n\n");
|
|
1235
1289
|
const remainingSteps = plan.steps.slice(currentStepIndex);
|
|
1236
1290
|
const remainingStepsText = remainingSteps.map(
|
|
1237
|
-
(step, idx) => REMAINING_STEP_TEMPLATE.replace("{stepNumber}", String(currentStepIndex + idx + 1)).replace("{description}", step.description).replace("{dependencies}", step.dependencies ? `Dependencies: ${step.dependencies.join(", ")}` : "")
|
|
1291
|
+
(step, idx) => REMAINING_STEP_TEMPLATE.replace("{stepNumber}", String(currentStepIndex + idx + 1)).replace("{description}", step.description).replace("{dependencies}", step.dependencies?.length ? `Dependencies: ${step.dependencies.join(", ")}` : "")
|
|
1238
1292
|
).join("\n\n");
|
|
1239
1293
|
const userPrompt = REPLANNING_PROMPT_TEMPLATE.replace("{goal}", plan.goal).replace("{completedSteps}", completedStepsText || "None").replace("{remainingSteps}", remainingStepsText || "None");
|
|
1240
1294
|
const messages = [
|
|
1241
|
-
new
|
|
1242
|
-
new
|
|
1295
|
+
new SystemMessage3(systemPrompt),
|
|
1296
|
+
new HumanMessage3(userPrompt)
|
|
1243
1297
|
];
|
|
1244
1298
|
const response = await model.invoke(messages);
|
|
1245
|
-
const content = response.content
|
|
1299
|
+
const content = normalizeModelContent(response.content);
|
|
1246
1300
|
let decision;
|
|
1247
1301
|
try {
|
|
1248
1302
|
decision = JSON.parse(content);
|
|
@@ -1260,15 +1314,14 @@ function createReplannerNode(config) {
|
|
|
1260
1314
|
input: decision.newGoal || plan.goal,
|
|
1261
1315
|
iteration: 1
|
|
1262
1316
|
};
|
|
1263
|
-
} else {
|
|
1264
|
-
replannerLogger.info("Continuing with current plan", {
|
|
1265
|
-
reason: decision.reason,
|
|
1266
|
-
duration: Date.now() - startTime
|
|
1267
|
-
});
|
|
1268
|
-
return {
|
|
1269
|
-
status: "executing"
|
|
1270
|
-
};
|
|
1271
1317
|
}
|
|
1318
|
+
replannerLogger.info("Continuing with current plan", {
|
|
1319
|
+
reason: decision.reason,
|
|
1320
|
+
duration: Date.now() - startTime
|
|
1321
|
+
});
|
|
1322
|
+
return {
|
|
1323
|
+
status: "executing"
|
|
1324
|
+
};
|
|
1272
1325
|
} catch (error) {
|
|
1273
1326
|
replannerLogger.error("Replanning evaluation failed", {
|
|
1274
1327
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -1281,11 +1334,13 @@ function createReplannerNode(config) {
|
|
|
1281
1334
|
}
|
|
1282
1335
|
};
|
|
1283
1336
|
}
|
|
1337
|
+
|
|
1338
|
+
// src/plan-execute/finisher-node.ts
|
|
1284
1339
|
function createFinisherNode() {
|
|
1285
1340
|
return async (state) => {
|
|
1286
1341
|
const results = state.pastSteps?.map((ps) => ({
|
|
1287
1342
|
step: ps.step.description,
|
|
1288
|
-
result: ps.result,
|
|
1343
|
+
result: toJsonSafeValue(ps.result),
|
|
1289
1344
|
success: ps.success
|
|
1290
1345
|
})) || [];
|
|
1291
1346
|
const response = JSON.stringify({
|
|
@@ -1631,7 +1686,7 @@ var REVISION_ENTRY_TEMPLATE = `Iteration {iteration}:
|
|
|
1631
1686
|
{content}`;
|
|
1632
1687
|
|
|
1633
1688
|
// src/reflection/nodes.ts
|
|
1634
|
-
import { HumanMessage as
|
|
1689
|
+
import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4 } from "@langchain/core/messages";
|
|
1635
1690
|
var generatorLogger = createPatternLogger("agentforge:patterns:reflection:generator");
|
|
1636
1691
|
var reflectorLogger = createPatternLogger("agentforge:patterns:reflection:reflector");
|
|
1637
1692
|
var reviserLogger = createPatternLogger("agentforge:patterns:reflection:reviser");
|
|
@@ -1658,8 +1713,8 @@ ${lastReflection.critique}`;
|
|
|
1658
1713
|
}
|
|
1659
1714
|
const userPrompt = GENERATION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{context}", context);
|
|
1660
1715
|
const messages = [
|
|
1661
|
-
new
|
|
1662
|
-
new
|
|
1716
|
+
new SystemMessage4(systemPrompt),
|
|
1717
|
+
new HumanMessage4(userPrompt)
|
|
1663
1718
|
];
|
|
1664
1719
|
const response = await model.invoke(messages);
|
|
1665
1720
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -1724,8 +1779,8 @@ function createReflectorNode(config) {
|
|
|
1724
1779
|
}
|
|
1725
1780
|
const userPrompt = REFLECTION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{currentResponse}", state.currentResponse).replace("{criteria}", criteriaSection).replace("{history}", historySection);
|
|
1726
1781
|
const messages = [
|
|
1727
|
-
new
|
|
1728
|
-
new
|
|
1782
|
+
new SystemMessage4(systemPrompt),
|
|
1783
|
+
new HumanMessage4(userPrompt)
|
|
1729
1784
|
];
|
|
1730
1785
|
const response = await model.invoke(messages);
|
|
1731
1786
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -1811,8 +1866,8 @@ ${revisionsText}`;
|
|
|
1811
1866
|
}
|
|
1812
1867
|
const userPrompt = REVISION_PROMPT_TEMPLATE.replace("{input}", state.input || "").replace("{currentResponse}", state.currentResponse).replace("{critique}", lastReflection.critique).replace("{issues}", lastReflection.issues.join("\n- ")).replace("{suggestions}", lastReflection.suggestions.join("\n- ")).replace("{history}", historySection);
|
|
1813
1868
|
const messages = [
|
|
1814
|
-
new
|
|
1815
|
-
new
|
|
1869
|
+
new SystemMessage4(systemPrompt),
|
|
1870
|
+
new HumanMessage4(userPrompt)
|
|
1816
1871
|
];
|
|
1817
1872
|
const response = await model.invoke(messages);
|
|
1818
1873
|
const content = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
|
|
@@ -2239,7 +2294,7 @@ var MultiAgentStateConfig = {
|
|
|
2239
2294
|
var MultiAgentState = createStateAnnotation4(MultiAgentStateConfig);
|
|
2240
2295
|
|
|
2241
2296
|
// src/multi-agent/routing.ts
|
|
2242
|
-
import { HumanMessage as
|
|
2297
|
+
import { HumanMessage as HumanMessage5, SystemMessage as SystemMessage5 } from "@langchain/core/messages";
|
|
2243
2298
|
var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
|
|
2244
2299
|
|
|
2245
2300
|
Your job is to:
|
|
@@ -2294,8 +2349,8 @@ ${workerInfo}
|
|
|
2294
2349
|
|
|
2295
2350
|
Select the best worker(s) for this task and explain your reasoning.`;
|
|
2296
2351
|
const messages = [
|
|
2297
|
-
new
|
|
2298
|
-
new
|
|
2352
|
+
new SystemMessage5(systemPrompt),
|
|
2353
|
+
new HumanMessage5(userPrompt)
|
|
2299
2354
|
];
|
|
2300
2355
|
const decision = await config.model.invoke(messages);
|
|
2301
2356
|
return {
|
|
@@ -2588,7 +2643,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2588
2643
|
}
|
|
2589
2644
|
|
|
2590
2645
|
// src/multi-agent/nodes/shared.ts
|
|
2591
|
-
import { HumanMessage as
|
|
2646
|
+
import { HumanMessage as HumanMessage6, SystemMessage as SystemMessage6 } from "@langchain/core/messages";
|
|
2592
2647
|
import { toLangChainTools as toLangChainTools2 } from "@agentforge/core";
|
|
2593
2648
|
var logger2 = createPatternLogger("agentforge:patterns:multi-agent:nodes");
|
|
2594
2649
|
function createGeneratedId(prefix) {
|
|
@@ -2659,7 +2714,7 @@ function serializeModelContent(content) {
|
|
|
2659
2714
|
}
|
|
2660
2715
|
}
|
|
2661
2716
|
function createPromptMessages(systemPrompt, task) {
|
|
2662
|
-
return [new
|
|
2717
|
+
return [new SystemMessage6(systemPrompt), new HumanMessage6(task)];
|
|
2663
2718
|
}
|
|
2664
2719
|
|
|
2665
2720
|
// src/multi-agent/nodes/aggregator.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/patterns",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.17",
|
|
4
4
|
"description": "Production-ready agent workflow patterns for TypeScript including ReAct and Planner-Executor, built on LangGraph.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"url": "https://github.com/TVScoundrel/agentforge/issues"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@agentforge/core": "0.16.
|
|
44
|
+
"@agentforge/core": "0.16.17",
|
|
45
45
|
"@langchain/core": "^1.1.17",
|
|
46
46
|
"@langchain/langgraph": "^1.1.2",
|
|
47
47
|
"zod": "^3.23.8"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@agentforge/testing": "0.16.
|
|
50
|
+
"@agentforge/testing": "0.16.17",
|
|
51
51
|
"@eslint/js": "^9.17.0",
|
|
52
52
|
"@types/node": "^22.10.2",
|
|
53
53
|
"eslint": "^9.17.0",
|