@agentforge/patterns 0.18.6 → 0.18.8
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 +66 -82
- package/dist/index.js +66 -82
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -298,6 +298,37 @@ function formatScratchpad(scratchpad) {
|
|
|
298
298
|
// src/react/nodes/reasoning.ts
|
|
299
299
|
var import_core3 = require("@agentforge/core");
|
|
300
300
|
|
|
301
|
+
// src/shared/model-response-content.ts
|
|
302
|
+
function getModelResponseText(content) {
|
|
303
|
+
return typeof content === "string" ? content : void 0;
|
|
304
|
+
}
|
|
305
|
+
function getModelResponseTextParts(content) {
|
|
306
|
+
if (!Array.isArray(content)) {
|
|
307
|
+
return [];
|
|
308
|
+
}
|
|
309
|
+
return content.flatMap((part) => {
|
|
310
|
+
const text = getModelResponseText(part);
|
|
311
|
+
if (text !== void 0) {
|
|
312
|
+
return [text];
|
|
313
|
+
}
|
|
314
|
+
if (typeof part === "object" && part !== null && "text" in part && typeof part.text === "string") {
|
|
315
|
+
return [part.text];
|
|
316
|
+
}
|
|
317
|
+
return [];
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function stringifyModelResponseContent(content) {
|
|
321
|
+
return getModelResponseText(content) ?? JSON.stringify(content);
|
|
322
|
+
}
|
|
323
|
+
function stringifyModelResponseContentSafely(content) {
|
|
324
|
+
try {
|
|
325
|
+
return stringifyModelResponseContent(content) ?? "undefined";
|
|
326
|
+
} catch (error) {
|
|
327
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
328
|
+
return `[Unserializable model content: ${reason}]`;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
301
332
|
// src/react/nodes/shared.ts
|
|
302
333
|
var import_messages = require("@langchain/core/messages");
|
|
303
334
|
|
|
@@ -454,7 +485,7 @@ function createReasoningNode(llm, tools, systemPrompt, maxIterations, verbose =
|
|
|
454
485
|
});
|
|
455
486
|
const messages = buildReasoningMessages(systemPrompt, state.messages, state.scratchpad);
|
|
456
487
|
const response = await llmWithTools.invoke(messages);
|
|
457
|
-
const thought =
|
|
488
|
+
const thought = getModelResponseText(response.content) ?? "";
|
|
458
489
|
const toolCalls = extractToolCalls(response);
|
|
459
490
|
const shouldContinue = toolCalls.length > 0 && currentIteration + 1 < maxIterations;
|
|
460
491
|
reasoningLogger.info("Reasoning complete", {
|
|
@@ -1142,40 +1173,15 @@ var plannerLogger = createPatternLogger("agentforge:patterns:plan-execute:planne
|
|
|
1142
1173
|
var executorLogger = createPatternLogger("agentforge:patterns:plan-execute:executor");
|
|
1143
1174
|
var replannerLogger = createPatternLogger("agentforge:patterns:plan-execute:replanner");
|
|
1144
1175
|
|
|
1145
|
-
// src/plan-execute/
|
|
1146
|
-
function
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1176
|
+
// src/plan-execute/response-parsing.ts
|
|
1177
|
+
function parseJsonModelResponse(content, context) {
|
|
1178
|
+
const text = getModelResponseText(content);
|
|
1179
|
+
const textParts = Array.isArray(content) ? getModelResponseTextParts(content.filter((part) => typeof part !== "string")).filter(
|
|
1180
|
+
(part) => part.length > 0
|
|
1181
|
+
) : [];
|
|
1182
|
+
const representedContent = text ?? (textParts.length > 0 ? textParts.join("\n") : stringifyModelResponseContentSafely(content));
|
|
1150
1183
|
try {
|
|
1151
|
-
|
|
1152
|
-
return serialized === void 0 ? "undefined" : serialized;
|
|
1153
|
-
} catch (error) {
|
|
1154
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1155
|
-
return `[Unserializable model content: ${reason}]`;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
function normalizeModelContent(content) {
|
|
1159
|
-
if (typeof content === "string") {
|
|
1160
|
-
return content;
|
|
1161
|
-
}
|
|
1162
|
-
if (Array.isArray(content)) {
|
|
1163
|
-
const textParts = [];
|
|
1164
|
-
for (const part of content) {
|
|
1165
|
-
if (hasTextContentPart(part) && part.text.length > 0) {
|
|
1166
|
-
textParts.push(part.text);
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
if (textParts.length > 0) {
|
|
1170
|
-
return textParts.join("\n");
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
return stringifyModelContent(content);
|
|
1174
|
-
}
|
|
1175
|
-
function parseModelResponse(content, context) {
|
|
1176
|
-
const normalized = normalizeModelContent(content);
|
|
1177
|
-
try {
|
|
1178
|
-
return JSON.parse(normalized);
|
|
1184
|
+
return JSON.parse(representedContent);
|
|
1179
1185
|
} catch (parseError) {
|
|
1180
1186
|
throw new Error(`Failed to parse ${context} from LLM response: ${parseError}`);
|
|
1181
1187
|
}
|
|
@@ -1207,7 +1213,7 @@ function createPlannerNode(config) {
|
|
|
1207
1213
|
new import_messages2.HumanMessage(userPrompt)
|
|
1208
1214
|
];
|
|
1209
1215
|
const response = await model.invoke(messages);
|
|
1210
|
-
const parsed =
|
|
1216
|
+
const parsed = parseJsonModelResponse(response.content, "plan");
|
|
1211
1217
|
const plan = {
|
|
1212
1218
|
steps: parsed.steps.slice(0, maxSteps),
|
|
1213
1219
|
goal: parsed.goal || state.input || "",
|
|
@@ -1472,7 +1478,10 @@ function createReplannerNode(config) {
|
|
|
1472
1478
|
new import_messages3.HumanMessage(userPrompt)
|
|
1473
1479
|
];
|
|
1474
1480
|
const response = await model.invoke(messages);
|
|
1475
|
-
const decision =
|
|
1481
|
+
const decision = parseJsonModelResponse(
|
|
1482
|
+
response.content,
|
|
1483
|
+
"replan decision"
|
|
1484
|
+
);
|
|
1476
1485
|
if (decision.shouldReplan) {
|
|
1477
1486
|
replannerLogger.info("Replanning triggered", {
|
|
1478
1487
|
reason: decision.reason,
|
|
@@ -1862,9 +1871,6 @@ var import_messages4 = require("@langchain/core/messages");
|
|
|
1862
1871
|
var generatorLogger = createPatternLogger("agentforge:patterns:reflection:generator");
|
|
1863
1872
|
var reflectorLogger = createPatternLogger("agentforge:patterns:reflection:reflector");
|
|
1864
1873
|
var reviserLogger = createPatternLogger("agentforge:patterns:reflection:reviser");
|
|
1865
|
-
function serializeModelContent(content) {
|
|
1866
|
-
return typeof content === "string" ? content : JSON.stringify(content);
|
|
1867
|
-
}
|
|
1868
1874
|
function buildRevisionHistorySection(revisions, heading) {
|
|
1869
1875
|
if (revisions.length === 0) {
|
|
1870
1876
|
return "";
|
|
@@ -1900,7 +1906,7 @@ ${lastReflection.critique}` : "";
|
|
|
1900
1906
|
new import_messages4.SystemMessage(systemPrompt),
|
|
1901
1907
|
new import_messages4.HumanMessage(userPrompt)
|
|
1902
1908
|
]);
|
|
1903
|
-
const content =
|
|
1909
|
+
const content = stringifyModelResponseContent(response.content);
|
|
1904
1910
|
generatorLogger.info("Response generated", {
|
|
1905
1911
|
attempt: state.iteration + 1,
|
|
1906
1912
|
responseLength: content.length,
|
|
@@ -1984,7 +1990,7 @@ function createReflectorNode(config) {
|
|
|
1984
1990
|
new import_messages5.SystemMessage(systemPrompt),
|
|
1985
1991
|
new import_messages5.HumanMessage(userPrompt)
|
|
1986
1992
|
]);
|
|
1987
|
-
const reflection = parseReflection(
|
|
1993
|
+
const reflection = parseReflection(stringifyModelResponseContent(response.content));
|
|
1988
1994
|
reflectorLogger.info("Reflection complete", {
|
|
1989
1995
|
attempt: state.iteration,
|
|
1990
1996
|
...reflection.score !== void 0 ? { score: reflection.score } : {},
|
|
@@ -2041,7 +2047,7 @@ function createReviserNode(config) {
|
|
|
2041
2047
|
new import_messages6.SystemMessage(systemPrompt),
|
|
2042
2048
|
new import_messages6.HumanMessage(userPrompt)
|
|
2043
2049
|
]);
|
|
2044
|
-
const content =
|
|
2050
|
+
const content = stringifyModelResponseContent(response.content);
|
|
2045
2051
|
reviserLogger.info("Revision complete", {
|
|
2046
2052
|
attempt: state.iteration,
|
|
2047
2053
|
revisionLength: content.length,
|
|
@@ -2433,12 +2439,9 @@ function convertWorkerToolsForLangChain(tools) {
|
|
|
2433
2439
|
const safeTools = tools ?? [];
|
|
2434
2440
|
return (0, import_core8.toLangChainTools)(safeTools);
|
|
2435
2441
|
}
|
|
2436
|
-
function
|
|
2437
|
-
if (typeof content === "string") {
|
|
2438
|
-
return content;
|
|
2439
|
-
}
|
|
2442
|
+
function requireSerializedModelContent(content) {
|
|
2440
2443
|
try {
|
|
2441
|
-
const serialized =
|
|
2444
|
+
const serialized = stringifyModelResponseContent(content);
|
|
2442
2445
|
if (typeof serialized !== "string") {
|
|
2443
2446
|
const error = new Error(
|
|
2444
2447
|
"Failed to serialize model content: JSON.stringify returned undefined"
|
|
@@ -2506,30 +2509,12 @@ function isRecord(value) {
|
|
|
2506
2509
|
function isContentCarrier(value) {
|
|
2507
2510
|
return isRecord(value) && "content" in value;
|
|
2508
2511
|
}
|
|
2509
|
-
function serializeRoutingContent(content) {
|
|
2510
|
-
if (typeof content === "string") {
|
|
2511
|
-
return content;
|
|
2512
|
-
}
|
|
2513
|
-
if (Array.isArray(content)) {
|
|
2514
|
-
const textParts = content.flatMap((part) => {
|
|
2515
|
-
if (typeof part === "string") {
|
|
2516
|
-
return [part];
|
|
2517
|
-
}
|
|
2518
|
-
if (isRecord(part) && typeof part.text === "string") {
|
|
2519
|
-
return [part.text];
|
|
2520
|
-
}
|
|
2521
|
-
return [];
|
|
2522
|
-
});
|
|
2523
|
-
if (textParts.length > 0) {
|
|
2524
|
-
return textParts.join("\n");
|
|
2525
|
-
}
|
|
2526
|
-
return JSON.stringify(content);
|
|
2527
|
-
}
|
|
2528
|
-
return JSON.stringify(content);
|
|
2529
|
-
}
|
|
2530
2512
|
function normalizeRoutingDecisionInput(decision) {
|
|
2531
2513
|
if (isContentCarrier(decision)) {
|
|
2532
|
-
|
|
2514
|
+
const text = getModelResponseText(decision.content);
|
|
2515
|
+
const textParts = getModelResponseTextParts(decision.content);
|
|
2516
|
+
const representedContent = text ?? (textParts.length > 0 ? textParts.join("\n") : stringifyModelResponseContent(decision.content));
|
|
2517
|
+
return JSON.parse(representedContent);
|
|
2533
2518
|
}
|
|
2534
2519
|
return decision;
|
|
2535
2520
|
}
|
|
@@ -2815,23 +2800,22 @@ function getReActResultShape(value) {
|
|
|
2815
2800
|
}
|
|
2816
2801
|
|
|
2817
2802
|
// src/multi-agent/utils-react-result.ts
|
|
2818
|
-
function
|
|
2803
|
+
function getWrappedResponseContent(content) {
|
|
2819
2804
|
if (content === null || content === void 0) {
|
|
2820
2805
|
return void 0;
|
|
2821
2806
|
}
|
|
2822
|
-
|
|
2823
|
-
|
|
2807
|
+
const text = getModelResponseText(content);
|
|
2808
|
+
if (text !== void 0) {
|
|
2809
|
+
return text.length > 0 ? text : void 0;
|
|
2824
2810
|
}
|
|
2825
2811
|
if (Array.isArray(content)) {
|
|
2826
2812
|
const parts = content.map((part) => {
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
if (isRecord2(part) && typeof part.text === "string" && part.text.length > 0) {
|
|
2831
|
-
return part.text;
|
|
2813
|
+
const partText = getModelResponseTextParts([part])[0];
|
|
2814
|
+
if (partText !== void 0 && partText.length > 0) {
|
|
2815
|
+
return partText;
|
|
2832
2816
|
}
|
|
2833
2817
|
try {
|
|
2834
|
-
return
|
|
2818
|
+
return stringifyModelResponseContent(part);
|
|
2835
2819
|
} catch {
|
|
2836
2820
|
return String(part);
|
|
2837
2821
|
}
|
|
@@ -2839,7 +2823,7 @@ function safeSerializeContent(content) {
|
|
|
2839
2823
|
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2840
2824
|
}
|
|
2841
2825
|
try {
|
|
2842
|
-
const serialized =
|
|
2826
|
+
const serialized = stringifyModelResponseContent(content);
|
|
2843
2827
|
if (typeof serialized === "string" && serialized.length > 0 && serialized !== "null") {
|
|
2844
2828
|
return serialized;
|
|
2845
2829
|
}
|
|
@@ -2850,7 +2834,7 @@ function safeSerializeContent(content) {
|
|
|
2850
2834
|
}
|
|
2851
2835
|
function extractResponse(resultShape) {
|
|
2852
2836
|
const lastMessage = resultShape.messages?.[resultShape.messages.length - 1];
|
|
2853
|
-
const serialized =
|
|
2837
|
+
const serialized = getWrappedResponseContent(lastMessage?.content);
|
|
2854
2838
|
return serialized ?? "No response";
|
|
2855
2839
|
}
|
|
2856
2840
|
function extractToolsUsed(resultShape) {
|
|
@@ -3048,7 +3032,7 @@ function createAggregatorNode(config = {}) {
|
|
|
3048
3032
|
const messages = createPromptMessages(systemPrompt, createAggregationPrompt(state));
|
|
3049
3033
|
logger.debug("Invoking aggregation LLM");
|
|
3050
3034
|
const response = await model.invoke(messages);
|
|
3051
|
-
const aggregatedResponse =
|
|
3035
|
+
const aggregatedResponse = requireSerializedModelContent(response.content);
|
|
3052
3036
|
logger.info("Aggregation complete", {
|
|
3053
3037
|
responseLength: aggregatedResponse.length
|
|
3054
3038
|
});
|
|
@@ -3243,7 +3227,7 @@ async function invokeWorkerModel(model, config, assignment) {
|
|
|
3243
3227
|
}
|
|
3244
3228
|
logger.debug("Invoking LLM", { workerId: config.id });
|
|
3245
3229
|
const response = await modelToUse.invoke(messages);
|
|
3246
|
-
const result =
|
|
3230
|
+
const result = requireSerializedModelContent(response.content);
|
|
3247
3231
|
logger.info("Worker task completed", {
|
|
3248
3232
|
workerId: config.id,
|
|
3249
3233
|
assignmentId: assignment.id,
|
package/dist/index.js
CHANGED
|
@@ -193,6 +193,37 @@ function formatScratchpad(scratchpad) {
|
|
|
193
193
|
// src/react/nodes/reasoning.ts
|
|
194
194
|
import { toLangChainTools } from "@agentforge/core";
|
|
195
195
|
|
|
196
|
+
// src/shared/model-response-content.ts
|
|
197
|
+
function getModelResponseText(content) {
|
|
198
|
+
return typeof content === "string" ? content : void 0;
|
|
199
|
+
}
|
|
200
|
+
function getModelResponseTextParts(content) {
|
|
201
|
+
if (!Array.isArray(content)) {
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
return content.flatMap((part) => {
|
|
205
|
+
const text = getModelResponseText(part);
|
|
206
|
+
if (text !== void 0) {
|
|
207
|
+
return [text];
|
|
208
|
+
}
|
|
209
|
+
if (typeof part === "object" && part !== null && "text" in part && typeof part.text === "string") {
|
|
210
|
+
return [part.text];
|
|
211
|
+
}
|
|
212
|
+
return [];
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function stringifyModelResponseContent(content) {
|
|
216
|
+
return getModelResponseText(content) ?? JSON.stringify(content);
|
|
217
|
+
}
|
|
218
|
+
function stringifyModelResponseContentSafely(content) {
|
|
219
|
+
try {
|
|
220
|
+
return stringifyModelResponseContent(content) ?? "undefined";
|
|
221
|
+
} catch (error) {
|
|
222
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
223
|
+
return `[Unserializable model content: ${reason}]`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
196
227
|
// src/react/nodes/shared.ts
|
|
197
228
|
import {
|
|
198
229
|
HumanMessage,
|
|
@@ -354,7 +385,7 @@ function createReasoningNode(llm, tools, systemPrompt, maxIterations, verbose =
|
|
|
354
385
|
});
|
|
355
386
|
const messages = buildReasoningMessages(systemPrompt, state.messages, state.scratchpad);
|
|
356
387
|
const response = await llmWithTools.invoke(messages);
|
|
357
|
-
const thought =
|
|
388
|
+
const thought = getModelResponseText(response.content) ?? "";
|
|
358
389
|
const toolCalls = extractToolCalls(response);
|
|
359
390
|
const shouldContinue = toolCalls.length > 0 && currentIteration + 1 < maxIterations;
|
|
360
391
|
reasoningLogger.info("Reasoning complete", {
|
|
@@ -1042,40 +1073,15 @@ var plannerLogger = createPatternLogger("agentforge:patterns:plan-execute:planne
|
|
|
1042
1073
|
var executorLogger = createPatternLogger("agentforge:patterns:plan-execute:executor");
|
|
1043
1074
|
var replannerLogger = createPatternLogger("agentforge:patterns:plan-execute:replanner");
|
|
1044
1075
|
|
|
1045
|
-
// src/plan-execute/
|
|
1046
|
-
function
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1076
|
+
// src/plan-execute/response-parsing.ts
|
|
1077
|
+
function parseJsonModelResponse(content, context) {
|
|
1078
|
+
const text = getModelResponseText(content);
|
|
1079
|
+
const textParts = Array.isArray(content) ? getModelResponseTextParts(content.filter((part) => typeof part !== "string")).filter(
|
|
1080
|
+
(part) => part.length > 0
|
|
1081
|
+
) : [];
|
|
1082
|
+
const representedContent = text ?? (textParts.length > 0 ? textParts.join("\n") : stringifyModelResponseContentSafely(content));
|
|
1050
1083
|
try {
|
|
1051
|
-
|
|
1052
|
-
return serialized === void 0 ? "undefined" : serialized;
|
|
1053
|
-
} catch (error) {
|
|
1054
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1055
|
-
return `[Unserializable model content: ${reason}]`;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
function normalizeModelContent(content) {
|
|
1059
|
-
if (typeof content === "string") {
|
|
1060
|
-
return content;
|
|
1061
|
-
}
|
|
1062
|
-
if (Array.isArray(content)) {
|
|
1063
|
-
const textParts = [];
|
|
1064
|
-
for (const part of content) {
|
|
1065
|
-
if (hasTextContentPart(part) && part.text.length > 0) {
|
|
1066
|
-
textParts.push(part.text);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
if (textParts.length > 0) {
|
|
1070
|
-
return textParts.join("\n");
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
return stringifyModelContent(content);
|
|
1074
|
-
}
|
|
1075
|
-
function parseModelResponse(content, context) {
|
|
1076
|
-
const normalized = normalizeModelContent(content);
|
|
1077
|
-
try {
|
|
1078
|
-
return JSON.parse(normalized);
|
|
1084
|
+
return JSON.parse(representedContent);
|
|
1079
1085
|
} catch (parseError) {
|
|
1080
1086
|
throw new Error(`Failed to parse ${context} from LLM response: ${parseError}`);
|
|
1081
1087
|
}
|
|
@@ -1107,7 +1113,7 @@ function createPlannerNode(config) {
|
|
|
1107
1113
|
new HumanMessage2(userPrompt)
|
|
1108
1114
|
];
|
|
1109
1115
|
const response = await model.invoke(messages);
|
|
1110
|
-
const parsed =
|
|
1116
|
+
const parsed = parseJsonModelResponse(response.content, "plan");
|
|
1111
1117
|
const plan = {
|
|
1112
1118
|
steps: parsed.steps.slice(0, maxSteps),
|
|
1113
1119
|
goal: parsed.goal || state.input || "",
|
|
@@ -1372,7 +1378,10 @@ function createReplannerNode(config) {
|
|
|
1372
1378
|
new HumanMessage3(userPrompt)
|
|
1373
1379
|
];
|
|
1374
1380
|
const response = await model.invoke(messages);
|
|
1375
|
-
const decision =
|
|
1381
|
+
const decision = parseJsonModelResponse(
|
|
1382
|
+
response.content,
|
|
1383
|
+
"replan decision"
|
|
1384
|
+
);
|
|
1376
1385
|
if (decision.shouldReplan) {
|
|
1377
1386
|
replannerLogger.info("Replanning triggered", {
|
|
1378
1387
|
reason: decision.reason,
|
|
@@ -1762,9 +1771,6 @@ import { HumanMessage as HumanMessage4, SystemMessage as SystemMessage4 } from "
|
|
|
1762
1771
|
var generatorLogger = createPatternLogger("agentforge:patterns:reflection:generator");
|
|
1763
1772
|
var reflectorLogger = createPatternLogger("agentforge:patterns:reflection:reflector");
|
|
1764
1773
|
var reviserLogger = createPatternLogger("agentforge:patterns:reflection:reviser");
|
|
1765
|
-
function serializeModelContent(content) {
|
|
1766
|
-
return typeof content === "string" ? content : JSON.stringify(content);
|
|
1767
|
-
}
|
|
1768
1774
|
function buildRevisionHistorySection(revisions, heading) {
|
|
1769
1775
|
if (revisions.length === 0) {
|
|
1770
1776
|
return "";
|
|
@@ -1800,7 +1806,7 @@ ${lastReflection.critique}` : "";
|
|
|
1800
1806
|
new SystemMessage4(systemPrompt),
|
|
1801
1807
|
new HumanMessage4(userPrompt)
|
|
1802
1808
|
]);
|
|
1803
|
-
const content =
|
|
1809
|
+
const content = stringifyModelResponseContent(response.content);
|
|
1804
1810
|
generatorLogger.info("Response generated", {
|
|
1805
1811
|
attempt: state.iteration + 1,
|
|
1806
1812
|
responseLength: content.length,
|
|
@@ -1884,7 +1890,7 @@ function createReflectorNode(config) {
|
|
|
1884
1890
|
new SystemMessage5(systemPrompt),
|
|
1885
1891
|
new HumanMessage5(userPrompt)
|
|
1886
1892
|
]);
|
|
1887
|
-
const reflection = parseReflection(
|
|
1893
|
+
const reflection = parseReflection(stringifyModelResponseContent(response.content));
|
|
1888
1894
|
reflectorLogger.info("Reflection complete", {
|
|
1889
1895
|
attempt: state.iteration,
|
|
1890
1896
|
...reflection.score !== void 0 ? { score: reflection.score } : {},
|
|
@@ -1941,7 +1947,7 @@ function createReviserNode(config) {
|
|
|
1941
1947
|
new SystemMessage6(systemPrompt),
|
|
1942
1948
|
new HumanMessage6(userPrompt)
|
|
1943
1949
|
]);
|
|
1944
|
-
const content =
|
|
1950
|
+
const content = stringifyModelResponseContent(response.content);
|
|
1945
1951
|
reviserLogger.info("Revision complete", {
|
|
1946
1952
|
attempt: state.iteration,
|
|
1947
1953
|
revisionLength: content.length,
|
|
@@ -2333,12 +2339,9 @@ function convertWorkerToolsForLangChain(tools) {
|
|
|
2333
2339
|
const safeTools = tools ?? [];
|
|
2334
2340
|
return toLangChainTools2(safeTools);
|
|
2335
2341
|
}
|
|
2336
|
-
function
|
|
2337
|
-
if (typeof content === "string") {
|
|
2338
|
-
return content;
|
|
2339
|
-
}
|
|
2342
|
+
function requireSerializedModelContent(content) {
|
|
2340
2343
|
try {
|
|
2341
|
-
const serialized =
|
|
2344
|
+
const serialized = stringifyModelResponseContent(content);
|
|
2342
2345
|
if (typeof serialized !== "string") {
|
|
2343
2346
|
const error = new Error(
|
|
2344
2347
|
"Failed to serialize model content: JSON.stringify returned undefined"
|
|
@@ -2406,30 +2409,12 @@ function isRecord(value) {
|
|
|
2406
2409
|
function isContentCarrier(value) {
|
|
2407
2410
|
return isRecord(value) && "content" in value;
|
|
2408
2411
|
}
|
|
2409
|
-
function serializeRoutingContent(content) {
|
|
2410
|
-
if (typeof content === "string") {
|
|
2411
|
-
return content;
|
|
2412
|
-
}
|
|
2413
|
-
if (Array.isArray(content)) {
|
|
2414
|
-
const textParts = content.flatMap((part) => {
|
|
2415
|
-
if (typeof part === "string") {
|
|
2416
|
-
return [part];
|
|
2417
|
-
}
|
|
2418
|
-
if (isRecord(part) && typeof part.text === "string") {
|
|
2419
|
-
return [part.text];
|
|
2420
|
-
}
|
|
2421
|
-
return [];
|
|
2422
|
-
});
|
|
2423
|
-
if (textParts.length > 0) {
|
|
2424
|
-
return textParts.join("\n");
|
|
2425
|
-
}
|
|
2426
|
-
return JSON.stringify(content);
|
|
2427
|
-
}
|
|
2428
|
-
return JSON.stringify(content);
|
|
2429
|
-
}
|
|
2430
2412
|
function normalizeRoutingDecisionInput(decision) {
|
|
2431
2413
|
if (isContentCarrier(decision)) {
|
|
2432
|
-
|
|
2414
|
+
const text = getModelResponseText(decision.content);
|
|
2415
|
+
const textParts = getModelResponseTextParts(decision.content);
|
|
2416
|
+
const representedContent = text ?? (textParts.length > 0 ? textParts.join("\n") : stringifyModelResponseContent(decision.content));
|
|
2417
|
+
return JSON.parse(representedContent);
|
|
2433
2418
|
}
|
|
2434
2419
|
return decision;
|
|
2435
2420
|
}
|
|
@@ -2715,23 +2700,22 @@ function getReActResultShape(value) {
|
|
|
2715
2700
|
}
|
|
2716
2701
|
|
|
2717
2702
|
// src/multi-agent/utils-react-result.ts
|
|
2718
|
-
function
|
|
2703
|
+
function getWrappedResponseContent(content) {
|
|
2719
2704
|
if (content === null || content === void 0) {
|
|
2720
2705
|
return void 0;
|
|
2721
2706
|
}
|
|
2722
|
-
|
|
2723
|
-
|
|
2707
|
+
const text = getModelResponseText(content);
|
|
2708
|
+
if (text !== void 0) {
|
|
2709
|
+
return text.length > 0 ? text : void 0;
|
|
2724
2710
|
}
|
|
2725
2711
|
if (Array.isArray(content)) {
|
|
2726
2712
|
const parts = content.map((part) => {
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
if (isRecord2(part) && typeof part.text === "string" && part.text.length > 0) {
|
|
2731
|
-
return part.text;
|
|
2713
|
+
const partText = getModelResponseTextParts([part])[0];
|
|
2714
|
+
if (partText !== void 0 && partText.length > 0) {
|
|
2715
|
+
return partText;
|
|
2732
2716
|
}
|
|
2733
2717
|
try {
|
|
2734
|
-
return
|
|
2718
|
+
return stringifyModelResponseContent(part);
|
|
2735
2719
|
} catch {
|
|
2736
2720
|
return String(part);
|
|
2737
2721
|
}
|
|
@@ -2739,7 +2723,7 @@ function safeSerializeContent(content) {
|
|
|
2739
2723
|
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2740
2724
|
}
|
|
2741
2725
|
try {
|
|
2742
|
-
const serialized =
|
|
2726
|
+
const serialized = stringifyModelResponseContent(content);
|
|
2743
2727
|
if (typeof serialized === "string" && serialized.length > 0 && serialized !== "null") {
|
|
2744
2728
|
return serialized;
|
|
2745
2729
|
}
|
|
@@ -2750,7 +2734,7 @@ function safeSerializeContent(content) {
|
|
|
2750
2734
|
}
|
|
2751
2735
|
function extractResponse(resultShape) {
|
|
2752
2736
|
const lastMessage = resultShape.messages?.[resultShape.messages.length - 1];
|
|
2753
|
-
const serialized =
|
|
2737
|
+
const serialized = getWrappedResponseContent(lastMessage?.content);
|
|
2754
2738
|
return serialized ?? "No response";
|
|
2755
2739
|
}
|
|
2756
2740
|
function extractToolsUsed(resultShape) {
|
|
@@ -2948,7 +2932,7 @@ function createAggregatorNode(config = {}) {
|
|
|
2948
2932
|
const messages = createPromptMessages(systemPrompt, createAggregationPrompt(state));
|
|
2949
2933
|
logger.debug("Invoking aggregation LLM");
|
|
2950
2934
|
const response = await model.invoke(messages);
|
|
2951
|
-
const aggregatedResponse =
|
|
2935
|
+
const aggregatedResponse = requireSerializedModelContent(response.content);
|
|
2952
2936
|
logger.info("Aggregation complete", {
|
|
2953
2937
|
responseLength: aggregatedResponse.length
|
|
2954
2938
|
});
|
|
@@ -3143,7 +3127,7 @@ async function invokeWorkerModel(model, config, assignment) {
|
|
|
3143
3127
|
}
|
|
3144
3128
|
logger.debug("Invoking LLM", { workerId: config.id });
|
|
3145
3129
|
const response = await modelToUse.invoke(messages);
|
|
3146
|
-
const result =
|
|
3130
|
+
const result = requireSerializedModelContent(response.content);
|
|
3147
3131
|
logger.info("Worker task completed", {
|
|
3148
3132
|
workerId: config.id,
|
|
3149
3133
|
assignmentId: assignment.id,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/patterns",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8",
|
|
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.18.
|
|
44
|
+
"@agentforge/core": "0.18.8",
|
|
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.18.
|
|
50
|
+
"@agentforge/testing": "0.18.8",
|
|
51
51
|
"@eslint/js": "^9.17.0",
|
|
52
52
|
"@types/node": "^22.10.2",
|
|
53
53
|
"eslint": "^9.17.0",
|