@agentforge/patterns 0.6.0 → 0.6.2
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 +48 -26
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +44 -22
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -327,6 +327,9 @@ function createActionNode(tools, verbose = false) {
|
|
|
327
327
|
console.log(`[action] Tool '${action.name}' executed successfully`);
|
|
328
328
|
}
|
|
329
329
|
} catch (error) {
|
|
330
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
330
333
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
331
334
|
observations.push({
|
|
332
335
|
toolCallId: action.id,
|
|
@@ -870,6 +873,9 @@ function createExecutorNode(config) {
|
|
|
870
873
|
result = { message: "Step completed without tool execution" };
|
|
871
874
|
}
|
|
872
875
|
} catch (execError) {
|
|
876
|
+
if (execError && typeof execError === "object" && "constructor" in execError && execError.constructor.name === "GraphInterrupt") {
|
|
877
|
+
throw execError;
|
|
878
|
+
}
|
|
873
879
|
success = false;
|
|
874
880
|
error = execError instanceof Error ? execError.message : "Unknown execution error";
|
|
875
881
|
result = null;
|
|
@@ -2097,43 +2103,48 @@ function getRoutingStrategy(name) {
|
|
|
2097
2103
|
}
|
|
2098
2104
|
|
|
2099
2105
|
// src/multi-agent/utils.ts
|
|
2106
|
+
var import_core7 = require("@agentforge/core");
|
|
2107
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core7.LogLevel.INFO;
|
|
2108
|
+
var logger = (0, import_core7.createLogger)("multi-agent", { level: logLevel });
|
|
2100
2109
|
function isReActAgent(obj) {
|
|
2101
2110
|
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
|
|
2102
2111
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
2103
2112
|
}
|
|
2104
2113
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2105
|
-
return async (state) => {
|
|
2114
|
+
return async (state, config) => {
|
|
2106
2115
|
try {
|
|
2107
|
-
|
|
2108
|
-
console.log(`[ReActWrapper:${workerId}] Wrapping ReAct agent execution`);
|
|
2109
|
-
}
|
|
2116
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2110
2117
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2118
|
+
logger.debug("Extracted task", {
|
|
2119
|
+
workerId,
|
|
2120
|
+
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2121
|
+
});
|
|
2114
2122
|
const currentAssignment = state.activeAssignments.find(
|
|
2115
2123
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2116
2124
|
);
|
|
2117
2125
|
if (!currentAssignment) {
|
|
2118
|
-
|
|
2119
|
-
console.log(`[ReActWrapper:${workerId}] No active assignment found`);
|
|
2120
|
-
}
|
|
2126
|
+
logger.debug("No active assignment found", { workerId });
|
|
2121
2127
|
return {
|
|
2122
2128
|
currentAgent: "supervisor",
|
|
2123
2129
|
status: "routing"
|
|
2124
2130
|
};
|
|
2125
2131
|
}
|
|
2126
|
-
const result = await agent.invoke(
|
|
2127
|
-
|
|
2128
|
-
|
|
2132
|
+
const result = await agent.invoke(
|
|
2133
|
+
{
|
|
2134
|
+
messages: [{ role: "user", content: task }]
|
|
2135
|
+
},
|
|
2136
|
+
config
|
|
2137
|
+
// Pass through the config for checkpointing and interrupt support
|
|
2138
|
+
);
|
|
2129
2139
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2140
|
+
logger.debug("Received response from ReAct agent", {
|
|
2141
|
+
workerId,
|
|
2142
|
+
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2143
|
+
});
|
|
2133
2144
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2134
2145
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2135
|
-
if (
|
|
2136
|
-
|
|
2146
|
+
if (uniqueTools.length > 0) {
|
|
2147
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2137
2148
|
}
|
|
2138
2149
|
const taskResult = {
|
|
2139
2150
|
assignmentId: currentAssignment.id,
|
|
@@ -2153,7 +2164,15 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2153
2164
|
status: "routing"
|
|
2154
2165
|
};
|
|
2155
2166
|
} catch (error) {
|
|
2156
|
-
|
|
2167
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2168
|
+
logger.debug("GraphInterrupt detected - re-throwing", { workerId });
|
|
2169
|
+
throw error;
|
|
2170
|
+
}
|
|
2171
|
+
logger.error("Error in ReAct agent execution", {
|
|
2172
|
+
workerId,
|
|
2173
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2174
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
2175
|
+
});
|
|
2157
2176
|
const currentAssignment = state.activeAssignments.find(
|
|
2158
2177
|
(assignment) => assignment.workerId === workerId
|
|
2159
2178
|
);
|
|
@@ -2182,7 +2201,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2182
2201
|
|
|
2183
2202
|
// src/multi-agent/nodes.ts
|
|
2184
2203
|
var import_messages5 = require("@langchain/core/messages");
|
|
2185
|
-
var
|
|
2204
|
+
var import_core8 = require("@agentforge/core");
|
|
2186
2205
|
var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
|
|
2187
2206
|
|
|
2188
2207
|
Your job is to:
|
|
@@ -2276,7 +2295,7 @@ function createWorkerNode(config) {
|
|
|
2276
2295
|
executeFn,
|
|
2277
2296
|
agent
|
|
2278
2297
|
} = config;
|
|
2279
|
-
return async (state) => {
|
|
2298
|
+
return async (state, runConfig) => {
|
|
2280
2299
|
try {
|
|
2281
2300
|
if (verbose) {
|
|
2282
2301
|
console.log(`[Worker:${id}] Executing task`);
|
|
@@ -2297,7 +2316,7 @@ function createWorkerNode(config) {
|
|
|
2297
2316
|
if (verbose) {
|
|
2298
2317
|
console.log(`[Worker:${id}] Using custom executeFn`);
|
|
2299
2318
|
}
|
|
2300
|
-
return await executeFn(state);
|
|
2319
|
+
return await executeFn(state, runConfig);
|
|
2301
2320
|
}
|
|
2302
2321
|
if (agent) {
|
|
2303
2322
|
if (isReActAgent(agent)) {
|
|
@@ -2305,7 +2324,7 @@ function createWorkerNode(config) {
|
|
|
2305
2324
|
console.log(`[Worker:${id}] Using ReAct agent (auto-wrapped)`);
|
|
2306
2325
|
}
|
|
2307
2326
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2308
|
-
return await wrappedFn(state);
|
|
2327
|
+
return await wrappedFn(state, runConfig);
|
|
2309
2328
|
} else {
|
|
2310
2329
|
console.warn(`[Worker:${id}] Agent provided but does not appear to be a ReAct agent. Falling back to default execution.`);
|
|
2311
2330
|
}
|
|
@@ -2326,7 +2345,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2326
2345
|
];
|
|
2327
2346
|
let modelToUse = model;
|
|
2328
2347
|
if (tools.length > 0 && model.bindTools) {
|
|
2329
|
-
const langchainTools = (0,
|
|
2348
|
+
const langchainTools = (0, import_core8.toLangChainTools)(tools);
|
|
2330
2349
|
modelToUse = model.bindTools(langchainTools);
|
|
2331
2350
|
}
|
|
2332
2351
|
const response = await modelToUse.invoke(messages);
|
|
@@ -2371,6 +2390,9 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2371
2390
|
status: "routing"
|
|
2372
2391
|
};
|
|
2373
2392
|
} catch (error) {
|
|
2393
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2394
|
+
throw error;
|
|
2395
|
+
}
|
|
2374
2396
|
console.error(`[Worker:${id}] Error:`, error);
|
|
2375
2397
|
const currentAssignment = state.activeAssignments.find(
|
|
2376
2398
|
(assignment) => assignment.workerId === id
|
|
@@ -2466,7 +2488,7 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2466
2488
|
|
|
2467
2489
|
// src/multi-agent/agent.ts
|
|
2468
2490
|
var import_langgraph4 = require("@langchain/langgraph");
|
|
2469
|
-
var
|
|
2491
|
+
var import_core9 = require("@agentforge/core");
|
|
2470
2492
|
function createMultiAgentSystem(config) {
|
|
2471
2493
|
const {
|
|
2472
2494
|
supervisor,
|
|
@@ -2479,7 +2501,7 @@ function createMultiAgentSystem(config) {
|
|
|
2479
2501
|
const workflow = new import_langgraph4.StateGraph(MultiAgentState);
|
|
2480
2502
|
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2481
2503
|
if (supervisor.model && supervisor.tools && supervisor.tools.length > 0) {
|
|
2482
|
-
const langchainTools = (0,
|
|
2504
|
+
const langchainTools = (0, import_core9.toLangChainTools)(supervisor.tools);
|
|
2483
2505
|
const modelWithTools = supervisor.model.bindTools(langchainTools);
|
|
2484
2506
|
supervisorConfig.model = modelWithTools;
|
|
2485
2507
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -2476,8 +2476,11 @@ interface WorkerConfig {
|
|
|
2476
2476
|
*
|
|
2477
2477
|
* If provided, this function will be used to execute tasks for this worker.
|
|
2478
2478
|
* Takes precedence over the `agent` property.
|
|
2479
|
+
*
|
|
2480
|
+
* The config parameter contains LangGraph runtime configuration including
|
|
2481
|
+
* thread_id for checkpointing, which is required for interrupt functionality.
|
|
2479
2482
|
*/
|
|
2480
|
-
executeFn?: (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
|
|
2483
|
+
executeFn?: (state: MultiAgentStateType, config?: any) => Promise<Partial<MultiAgentStateType>>;
|
|
2481
2484
|
/**
|
|
2482
2485
|
* ReAct agent instance
|
|
2483
2486
|
*
|
|
@@ -2655,7 +2658,7 @@ declare function createSupervisorNode(config: SupervisorConfig): (state: MultiAg
|
|
|
2655
2658
|
/**
|
|
2656
2659
|
* Create a worker agent node
|
|
2657
2660
|
*/
|
|
2658
|
-
declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
|
|
2661
|
+
declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType, runConfig?: any) => Promise<Partial<MultiAgentStateType>>;
|
|
2659
2662
|
/**
|
|
2660
2663
|
* Create an aggregator node that combines worker results
|
|
2661
2664
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -2476,8 +2476,11 @@ interface WorkerConfig {
|
|
|
2476
2476
|
*
|
|
2477
2477
|
* If provided, this function will be used to execute tasks for this worker.
|
|
2478
2478
|
* Takes precedence over the `agent` property.
|
|
2479
|
+
*
|
|
2480
|
+
* The config parameter contains LangGraph runtime configuration including
|
|
2481
|
+
* thread_id for checkpointing, which is required for interrupt functionality.
|
|
2479
2482
|
*/
|
|
2480
|
-
executeFn?: (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
|
|
2483
|
+
executeFn?: (state: MultiAgentStateType, config?: any) => Promise<Partial<MultiAgentStateType>>;
|
|
2481
2484
|
/**
|
|
2482
2485
|
* ReAct agent instance
|
|
2483
2486
|
*
|
|
@@ -2655,7 +2658,7 @@ declare function createSupervisorNode(config: SupervisorConfig): (state: MultiAg
|
|
|
2655
2658
|
/**
|
|
2656
2659
|
* Create a worker agent node
|
|
2657
2660
|
*/
|
|
2658
|
-
declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType) => Promise<Partial<MultiAgentStateType>>;
|
|
2661
|
+
declare function createWorkerNode(config: WorkerConfig): (state: MultiAgentStateType, runConfig?: any) => Promise<Partial<MultiAgentStateType>>;
|
|
2659
2662
|
/**
|
|
2660
2663
|
* Create an aggregator node that combines worker results
|
|
2661
2664
|
*/
|
package/dist/index.js
CHANGED
|
@@ -228,6 +228,9 @@ function createActionNode(tools, verbose = false) {
|
|
|
228
228
|
console.log(`[action] Tool '${action.name}' executed successfully`);
|
|
229
229
|
}
|
|
230
230
|
} catch (error) {
|
|
231
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
231
234
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
232
235
|
observations.push({
|
|
233
236
|
toolCallId: action.id,
|
|
@@ -771,6 +774,9 @@ function createExecutorNode(config) {
|
|
|
771
774
|
result = { message: "Step completed without tool execution" };
|
|
772
775
|
}
|
|
773
776
|
} catch (execError) {
|
|
777
|
+
if (execError && typeof execError === "object" && "constructor" in execError && execError.constructor.name === "GraphInterrupt") {
|
|
778
|
+
throw execError;
|
|
779
|
+
}
|
|
774
780
|
success = false;
|
|
775
781
|
error = execError instanceof Error ? execError.message : "Unknown execution error";
|
|
776
782
|
result = null;
|
|
@@ -1998,43 +2004,48 @@ function getRoutingStrategy(name) {
|
|
|
1998
2004
|
}
|
|
1999
2005
|
|
|
2000
2006
|
// src/multi-agent/utils.ts
|
|
2007
|
+
import { createLogger, LogLevel } from "@agentforge/core";
|
|
2008
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
2009
|
+
var logger = createLogger("multi-agent", { level: logLevel });
|
|
2001
2010
|
function isReActAgent(obj) {
|
|
2002
2011
|
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
|
|
2003
2012
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
2004
2013
|
}
|
|
2005
2014
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2006
|
-
return async (state) => {
|
|
2015
|
+
return async (state, config) => {
|
|
2007
2016
|
try {
|
|
2008
|
-
|
|
2009
|
-
console.log(`[ReActWrapper:${workerId}] Wrapping ReAct agent execution`);
|
|
2010
|
-
}
|
|
2017
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2011
2018
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2019
|
+
logger.debug("Extracted task", {
|
|
2020
|
+
workerId,
|
|
2021
|
+
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2022
|
+
});
|
|
2015
2023
|
const currentAssignment = state.activeAssignments.find(
|
|
2016
2024
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2017
2025
|
);
|
|
2018
2026
|
if (!currentAssignment) {
|
|
2019
|
-
|
|
2020
|
-
console.log(`[ReActWrapper:${workerId}] No active assignment found`);
|
|
2021
|
-
}
|
|
2027
|
+
logger.debug("No active assignment found", { workerId });
|
|
2022
2028
|
return {
|
|
2023
2029
|
currentAgent: "supervisor",
|
|
2024
2030
|
status: "routing"
|
|
2025
2031
|
};
|
|
2026
2032
|
}
|
|
2027
|
-
const result = await agent.invoke(
|
|
2028
|
-
|
|
2029
|
-
|
|
2033
|
+
const result = await agent.invoke(
|
|
2034
|
+
{
|
|
2035
|
+
messages: [{ role: "user", content: task }]
|
|
2036
|
+
},
|
|
2037
|
+
config
|
|
2038
|
+
// Pass through the config for checkpointing and interrupt support
|
|
2039
|
+
);
|
|
2030
2040
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2041
|
+
logger.debug("Received response from ReAct agent", {
|
|
2042
|
+
workerId,
|
|
2043
|
+
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2044
|
+
});
|
|
2034
2045
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2035
2046
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2036
|
-
if (
|
|
2037
|
-
|
|
2047
|
+
if (uniqueTools.length > 0) {
|
|
2048
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2038
2049
|
}
|
|
2039
2050
|
const taskResult = {
|
|
2040
2051
|
assignmentId: currentAssignment.id,
|
|
@@ -2054,7 +2065,15 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2054
2065
|
status: "routing"
|
|
2055
2066
|
};
|
|
2056
2067
|
} catch (error) {
|
|
2057
|
-
|
|
2068
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2069
|
+
logger.debug("GraphInterrupt detected - re-throwing", { workerId });
|
|
2070
|
+
throw error;
|
|
2071
|
+
}
|
|
2072
|
+
logger.error("Error in ReAct agent execution", {
|
|
2073
|
+
workerId,
|
|
2074
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2075
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
2076
|
+
});
|
|
2058
2077
|
const currentAssignment = state.activeAssignments.find(
|
|
2059
2078
|
(assignment) => assignment.workerId === workerId
|
|
2060
2079
|
);
|
|
@@ -2177,7 +2196,7 @@ function createWorkerNode(config) {
|
|
|
2177
2196
|
executeFn,
|
|
2178
2197
|
agent
|
|
2179
2198
|
} = config;
|
|
2180
|
-
return async (state) => {
|
|
2199
|
+
return async (state, runConfig) => {
|
|
2181
2200
|
try {
|
|
2182
2201
|
if (verbose) {
|
|
2183
2202
|
console.log(`[Worker:${id}] Executing task`);
|
|
@@ -2198,7 +2217,7 @@ function createWorkerNode(config) {
|
|
|
2198
2217
|
if (verbose) {
|
|
2199
2218
|
console.log(`[Worker:${id}] Using custom executeFn`);
|
|
2200
2219
|
}
|
|
2201
|
-
return await executeFn(state);
|
|
2220
|
+
return await executeFn(state, runConfig);
|
|
2202
2221
|
}
|
|
2203
2222
|
if (agent) {
|
|
2204
2223
|
if (isReActAgent(agent)) {
|
|
@@ -2206,7 +2225,7 @@ function createWorkerNode(config) {
|
|
|
2206
2225
|
console.log(`[Worker:${id}] Using ReAct agent (auto-wrapped)`);
|
|
2207
2226
|
}
|
|
2208
2227
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2209
|
-
return await wrappedFn(state);
|
|
2228
|
+
return await wrappedFn(state, runConfig);
|
|
2210
2229
|
} else {
|
|
2211
2230
|
console.warn(`[Worker:${id}] Agent provided but does not appear to be a ReAct agent. Falling back to default execution.`);
|
|
2212
2231
|
}
|
|
@@ -2272,6 +2291,9 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2272
2291
|
status: "routing"
|
|
2273
2292
|
};
|
|
2274
2293
|
} catch (error) {
|
|
2294
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2295
|
+
throw error;
|
|
2296
|
+
}
|
|
2275
2297
|
console.error(`[Worker:${id}] Error:`, error);
|
|
2276
2298
|
const currentAssignment = state.activeAssignments.find(
|
|
2277
2299
|
(assignment) => assignment.workerId === id
|