@agentforge/patterns 0.6.0 → 0.6.1
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 +45 -26
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +41 -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,
|
|
@@ -2097,43 +2100,48 @@ function getRoutingStrategy(name) {
|
|
|
2097
2100
|
}
|
|
2098
2101
|
|
|
2099
2102
|
// src/multi-agent/utils.ts
|
|
2103
|
+
var import_core7 = require("@agentforge/core");
|
|
2104
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core7.LogLevel.INFO;
|
|
2105
|
+
var logger = (0, import_core7.createLogger)("multi-agent", { level: logLevel });
|
|
2100
2106
|
function isReActAgent(obj) {
|
|
2101
2107
|
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
2108
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
2103
2109
|
}
|
|
2104
2110
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2105
|
-
return async (state) => {
|
|
2111
|
+
return async (state, config) => {
|
|
2106
2112
|
try {
|
|
2107
|
-
|
|
2108
|
-
console.log(`[ReActWrapper:${workerId}] Wrapping ReAct agent execution`);
|
|
2109
|
-
}
|
|
2113
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2110
2114
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2115
|
+
logger.debug("Extracted task", {
|
|
2116
|
+
workerId,
|
|
2117
|
+
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2118
|
+
});
|
|
2114
2119
|
const currentAssignment = state.activeAssignments.find(
|
|
2115
2120
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2116
2121
|
);
|
|
2117
2122
|
if (!currentAssignment) {
|
|
2118
|
-
|
|
2119
|
-
console.log(`[ReActWrapper:${workerId}] No active assignment found`);
|
|
2120
|
-
}
|
|
2123
|
+
logger.debug("No active assignment found", { workerId });
|
|
2121
2124
|
return {
|
|
2122
2125
|
currentAgent: "supervisor",
|
|
2123
2126
|
status: "routing"
|
|
2124
2127
|
};
|
|
2125
2128
|
}
|
|
2126
|
-
const result = await agent.invoke(
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
+
const result = await agent.invoke(
|
|
2130
|
+
{
|
|
2131
|
+
messages: [{ role: "user", content: task }]
|
|
2132
|
+
},
|
|
2133
|
+
config
|
|
2134
|
+
// Pass through the config for checkpointing and interrupt support
|
|
2135
|
+
);
|
|
2129
2136
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2137
|
+
logger.debug("Received response from ReAct agent", {
|
|
2138
|
+
workerId,
|
|
2139
|
+
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2140
|
+
});
|
|
2133
2141
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2134
2142
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2135
|
-
if (
|
|
2136
|
-
|
|
2143
|
+
if (uniqueTools.length > 0) {
|
|
2144
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2137
2145
|
}
|
|
2138
2146
|
const taskResult = {
|
|
2139
2147
|
assignmentId: currentAssignment.id,
|
|
@@ -2153,7 +2161,15 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2153
2161
|
status: "routing"
|
|
2154
2162
|
};
|
|
2155
2163
|
} catch (error) {
|
|
2156
|
-
|
|
2164
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2165
|
+
logger.debug("GraphInterrupt detected - re-throwing", { workerId });
|
|
2166
|
+
throw error;
|
|
2167
|
+
}
|
|
2168
|
+
logger.error("Error in ReAct agent execution", {
|
|
2169
|
+
workerId,
|
|
2170
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2171
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
2172
|
+
});
|
|
2157
2173
|
const currentAssignment = state.activeAssignments.find(
|
|
2158
2174
|
(assignment) => assignment.workerId === workerId
|
|
2159
2175
|
);
|
|
@@ -2182,7 +2198,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2182
2198
|
|
|
2183
2199
|
// src/multi-agent/nodes.ts
|
|
2184
2200
|
var import_messages5 = require("@langchain/core/messages");
|
|
2185
|
-
var
|
|
2201
|
+
var import_core8 = require("@agentforge/core");
|
|
2186
2202
|
var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
|
|
2187
2203
|
|
|
2188
2204
|
Your job is to:
|
|
@@ -2276,7 +2292,7 @@ function createWorkerNode(config) {
|
|
|
2276
2292
|
executeFn,
|
|
2277
2293
|
agent
|
|
2278
2294
|
} = config;
|
|
2279
|
-
return async (state) => {
|
|
2295
|
+
return async (state, runConfig) => {
|
|
2280
2296
|
try {
|
|
2281
2297
|
if (verbose) {
|
|
2282
2298
|
console.log(`[Worker:${id}] Executing task`);
|
|
@@ -2297,7 +2313,7 @@ function createWorkerNode(config) {
|
|
|
2297
2313
|
if (verbose) {
|
|
2298
2314
|
console.log(`[Worker:${id}] Using custom executeFn`);
|
|
2299
2315
|
}
|
|
2300
|
-
return await executeFn(state);
|
|
2316
|
+
return await executeFn(state, runConfig);
|
|
2301
2317
|
}
|
|
2302
2318
|
if (agent) {
|
|
2303
2319
|
if (isReActAgent(agent)) {
|
|
@@ -2305,7 +2321,7 @@ function createWorkerNode(config) {
|
|
|
2305
2321
|
console.log(`[Worker:${id}] Using ReAct agent (auto-wrapped)`);
|
|
2306
2322
|
}
|
|
2307
2323
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2308
|
-
return await wrappedFn(state);
|
|
2324
|
+
return await wrappedFn(state, runConfig);
|
|
2309
2325
|
} else {
|
|
2310
2326
|
console.warn(`[Worker:${id}] Agent provided but does not appear to be a ReAct agent. Falling back to default execution.`);
|
|
2311
2327
|
}
|
|
@@ -2326,7 +2342,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2326
2342
|
];
|
|
2327
2343
|
let modelToUse = model;
|
|
2328
2344
|
if (tools.length > 0 && model.bindTools) {
|
|
2329
|
-
const langchainTools = (0,
|
|
2345
|
+
const langchainTools = (0, import_core8.toLangChainTools)(tools);
|
|
2330
2346
|
modelToUse = model.bindTools(langchainTools);
|
|
2331
2347
|
}
|
|
2332
2348
|
const response = await modelToUse.invoke(messages);
|
|
@@ -2371,6 +2387,9 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2371
2387
|
status: "routing"
|
|
2372
2388
|
};
|
|
2373
2389
|
} catch (error) {
|
|
2390
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2391
|
+
throw error;
|
|
2392
|
+
}
|
|
2374
2393
|
console.error(`[Worker:${id}] Error:`, error);
|
|
2375
2394
|
const currentAssignment = state.activeAssignments.find(
|
|
2376
2395
|
(assignment) => assignment.workerId === id
|
|
@@ -2466,7 +2485,7 @@ Please synthesize these results into a comprehensive response that addresses the
|
|
|
2466
2485
|
|
|
2467
2486
|
// src/multi-agent/agent.ts
|
|
2468
2487
|
var import_langgraph4 = require("@langchain/langgraph");
|
|
2469
|
-
var
|
|
2488
|
+
var import_core9 = require("@agentforge/core");
|
|
2470
2489
|
function createMultiAgentSystem(config) {
|
|
2471
2490
|
const {
|
|
2472
2491
|
supervisor,
|
|
@@ -2479,7 +2498,7 @@ function createMultiAgentSystem(config) {
|
|
|
2479
2498
|
const workflow = new import_langgraph4.StateGraph(MultiAgentState);
|
|
2480
2499
|
let supervisorConfig = { ...supervisor, maxIterations, verbose };
|
|
2481
2500
|
if (supervisor.model && supervisor.tools && supervisor.tools.length > 0) {
|
|
2482
|
-
const langchainTools = (0,
|
|
2501
|
+
const langchainTools = (0, import_core9.toLangChainTools)(supervisor.tools);
|
|
2483
2502
|
const modelWithTools = supervisor.model.bindTools(langchainTools);
|
|
2484
2503
|
supervisorConfig.model = modelWithTools;
|
|
2485
2504
|
}
|
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,
|
|
@@ -1998,43 +2001,48 @@ function getRoutingStrategy(name) {
|
|
|
1998
2001
|
}
|
|
1999
2002
|
|
|
2000
2003
|
// src/multi-agent/utils.ts
|
|
2004
|
+
import { createLogger, LogLevel } from "@agentforge/core";
|
|
2005
|
+
var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
2006
|
+
var logger = createLogger("multi-agent", { level: logLevel });
|
|
2001
2007
|
function isReActAgent(obj) {
|
|
2002
2008
|
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
2009
|
(obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
|
|
2004
2010
|
}
|
|
2005
2011
|
function wrapReActAgent(workerId, agent, verbose = false) {
|
|
2006
|
-
return async (state) => {
|
|
2012
|
+
return async (state, config) => {
|
|
2007
2013
|
try {
|
|
2008
|
-
|
|
2009
|
-
console.log(`[ReActWrapper:${workerId}] Wrapping ReAct agent execution`);
|
|
2010
|
-
}
|
|
2014
|
+
logger.debug("Wrapping ReAct agent execution", { workerId });
|
|
2011
2015
|
const task = state.messages[state.messages.length - 1]?.content || state.input;
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2016
|
+
logger.debug("Extracted task", {
|
|
2017
|
+
workerId,
|
|
2018
|
+
taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
|
|
2019
|
+
});
|
|
2015
2020
|
const currentAssignment = state.activeAssignments.find(
|
|
2016
2021
|
(assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
|
|
2017
2022
|
);
|
|
2018
2023
|
if (!currentAssignment) {
|
|
2019
|
-
|
|
2020
|
-
console.log(`[ReActWrapper:${workerId}] No active assignment found`);
|
|
2021
|
-
}
|
|
2024
|
+
logger.debug("No active assignment found", { workerId });
|
|
2022
2025
|
return {
|
|
2023
2026
|
currentAgent: "supervisor",
|
|
2024
2027
|
status: "routing"
|
|
2025
2028
|
};
|
|
2026
2029
|
}
|
|
2027
|
-
const result = await agent.invoke(
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
+
const result = await agent.invoke(
|
|
2031
|
+
{
|
|
2032
|
+
messages: [{ role: "user", content: task }]
|
|
2033
|
+
},
|
|
2034
|
+
config
|
|
2035
|
+
// Pass through the config for checkpointing and interrupt support
|
|
2036
|
+
);
|
|
2030
2037
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2038
|
+
logger.debug("Received response from ReAct agent", {
|
|
2039
|
+
workerId,
|
|
2040
|
+
responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
|
|
2041
|
+
});
|
|
2034
2042
|
const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
|
|
2035
2043
|
const uniqueTools = [...new Set(toolsUsed)];
|
|
2036
|
-
if (
|
|
2037
|
-
|
|
2044
|
+
if (uniqueTools.length > 0) {
|
|
2045
|
+
logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
|
|
2038
2046
|
}
|
|
2039
2047
|
const taskResult = {
|
|
2040
2048
|
assignmentId: currentAssignment.id,
|
|
@@ -2054,7 +2062,15 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2054
2062
|
status: "routing"
|
|
2055
2063
|
};
|
|
2056
2064
|
} catch (error) {
|
|
2057
|
-
|
|
2065
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2066
|
+
logger.debug("GraphInterrupt detected - re-throwing", { workerId });
|
|
2067
|
+
throw error;
|
|
2068
|
+
}
|
|
2069
|
+
logger.error("Error in ReAct agent execution", {
|
|
2070
|
+
workerId,
|
|
2071
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2072
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
2073
|
+
});
|
|
2058
2074
|
const currentAssignment = state.activeAssignments.find(
|
|
2059
2075
|
(assignment) => assignment.workerId === workerId
|
|
2060
2076
|
);
|
|
@@ -2177,7 +2193,7 @@ function createWorkerNode(config) {
|
|
|
2177
2193
|
executeFn,
|
|
2178
2194
|
agent
|
|
2179
2195
|
} = config;
|
|
2180
|
-
return async (state) => {
|
|
2196
|
+
return async (state, runConfig) => {
|
|
2181
2197
|
try {
|
|
2182
2198
|
if (verbose) {
|
|
2183
2199
|
console.log(`[Worker:${id}] Executing task`);
|
|
@@ -2198,7 +2214,7 @@ function createWorkerNode(config) {
|
|
|
2198
2214
|
if (verbose) {
|
|
2199
2215
|
console.log(`[Worker:${id}] Using custom executeFn`);
|
|
2200
2216
|
}
|
|
2201
|
-
return await executeFn(state);
|
|
2217
|
+
return await executeFn(state, runConfig);
|
|
2202
2218
|
}
|
|
2203
2219
|
if (agent) {
|
|
2204
2220
|
if (isReActAgent(agent)) {
|
|
@@ -2206,7 +2222,7 @@ function createWorkerNode(config) {
|
|
|
2206
2222
|
console.log(`[Worker:${id}] Using ReAct agent (auto-wrapped)`);
|
|
2207
2223
|
}
|
|
2208
2224
|
const wrappedFn = wrapReActAgent(id, agent, verbose);
|
|
2209
|
-
return await wrappedFn(state);
|
|
2225
|
+
return await wrappedFn(state, runConfig);
|
|
2210
2226
|
} else {
|
|
2211
2227
|
console.warn(`[Worker:${id}] Agent provided but does not appear to be a ReAct agent. Falling back to default execution.`);
|
|
2212
2228
|
}
|
|
@@ -2272,6 +2288,9 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
|
|
|
2272
2288
|
status: "routing"
|
|
2273
2289
|
};
|
|
2274
2290
|
} catch (error) {
|
|
2291
|
+
if (error && typeof error === "object" && "constructor" in error && error.constructor.name === "GraphInterrupt") {
|
|
2292
|
+
throw error;
|
|
2293
|
+
}
|
|
2275
2294
|
console.error(`[Worker:${id}] Error:`, error);
|
|
2276
2295
|
const currentAssignment = state.activeAssignments.find(
|
|
2277
2296
|
(assignment) => assignment.workerId === id
|