@agentforge/patterns 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -283,8 +283,8 @@ function generateToolCallCacheKey(toolName, args) {
283
283
  return `${toolName}:${sortedArgs}`;
284
284
  }
285
285
  function createPatternLogger(name, defaultLevel = "info") {
286
- const logLevel5 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
287
- return (0, import_core2.createLogger)(name, { level: logLevel5 });
286
+ const logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || defaultLevel;
287
+ return (0, import_core2.createLogger)(name, { level: logLevel4 });
288
288
  }
289
289
  function calculateDeduplicationSavings(duplicatesSkipped, toolsExecuted) {
290
290
  if (duplicatesSkipped === 0) {
@@ -2164,66 +2164,6 @@ var MultiAgentState = (0, import_core7.createStateAnnotation)(MultiAgentStateCon
2164
2164
 
2165
2165
  // src/multi-agent/routing.ts
2166
2166
  var import_messages4 = require("@langchain/core/messages");
2167
- var import_core8 = require("@agentforge/core");
2168
- var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
2169
- var logger = (0, import_core8.createLogger)("multi-agent:routing", { level: logLevel });
2170
- async function executeTools(toolCalls, tools) {
2171
- const results = [];
2172
- logger.debug("Executing tools", {
2173
- toolCallCount: toolCalls.length,
2174
- toolNames: toolCalls.map((tc) => tc.name)
2175
- });
2176
- for (const toolCall of toolCalls) {
2177
- const tool = tools.find((t) => t.metadata.name === toolCall.name);
2178
- if (!tool) {
2179
- logger.warn("Tool not found", {
2180
- toolName: toolCall.name,
2181
- availableTools: tools.map((t) => t.metadata.name)
2182
- });
2183
- results.push(new import_messages4.ToolMessage({
2184
- content: `Error: Tool '${toolCall.name}' not found`,
2185
- tool_call_id: toolCall.id
2186
- }));
2187
- continue;
2188
- }
2189
- try {
2190
- logger.debug("Executing tool", {
2191
- toolName: toolCall.name,
2192
- args: toolCall.args
2193
- });
2194
- const result = await tool.execute(toolCall.args);
2195
- const content = typeof result === "string" ? result : JSON.stringify(result);
2196
- logger.debug("Tool execution successful", {
2197
- toolName: toolCall.name,
2198
- resultLength: content.length
2199
- });
2200
- results.push(new import_messages4.ToolMessage({
2201
- content,
2202
- tool_call_id: toolCall.id
2203
- }));
2204
- } catch (error) {
2205
- logger.error("Tool execution failed", {
2206
- toolName: toolCall.name,
2207
- error: error.message
2208
- });
2209
- results.push(new import_messages4.ToolMessage({
2210
- content: `Error executing tool: ${error.message}`,
2211
- tool_call_id: toolCall.id
2212
- }));
2213
- }
2214
- }
2215
- logger.debug("Tool execution complete", {
2216
- successCount: results.filter((r) => {
2217
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2218
- return !content.startsWith("Error");
2219
- }).length,
2220
- errorCount: results.filter((r) => {
2221
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
2222
- return content.startsWith("Error");
2223
- }).length
2224
- });
2225
- return results;
2226
- }
2227
2167
  var DEFAULT_SUPERVISOR_SYSTEM_PROMPT = `You are a supervisor agent responsible for routing tasks to specialized worker agents.
2228
2168
 
2229
2169
  Your job is to:
@@ -2259,151 +2199,48 @@ Choose parallel routing when the task benefits from multiple perspectives or dat
2259
2199
  var llmBasedRouting = {
2260
2200
  name: "llm-based",
2261
2201
  async route(state, config) {
2262
- logger.info("Starting LLM-based routing", {
2263
- iteration: state.iteration,
2264
- availableWorkers: Object.keys(state.workers).length
2265
- });
2266
2202
  if (!config.model) {
2267
2203
  throw new Error("LLM-based routing requires a model to be configured");
2268
2204
  }
2269
2205
  const systemPrompt = config.systemPrompt || DEFAULT_SUPERVISOR_SYSTEM_PROMPT;
2270
- const maxRetries = config.maxToolRetries || 3;
2271
- const tools = config.tools || [];
2272
2206
  const workerInfo = Object.entries(state.workers).map(([id, caps]) => {
2273
2207
  const skills = caps.skills.join(", ");
2274
- const tools2 = caps.tools.join(", ");
2208
+ const tools = caps.tools.join(", ");
2275
2209
  const available = caps.available ? "available" : "busy";
2276
- return `- ${id}: Skills: [${skills}], Tools: [${tools2}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2210
+ return `- ${id}: Skills: [${skills}], Tools: [${tools}], Status: ${available}, Workload: ${caps.currentWorkload}`;
2277
2211
  }).join("\n");
2278
- logger.debug("Worker capabilities", {
2279
- workers: Object.entries(state.workers).map(([id, caps]) => ({
2280
- id,
2281
- skills: caps.skills,
2282
- available: caps.available,
2283
- workload: caps.currentWorkload
2284
- }))
2285
- });
2286
2212
  const lastMessage = state.messages[state.messages.length - 1];
2287
2213
  const taskContext = lastMessage?.content || state.input;
2288
- logger.debug("Task context", {
2289
- taskLength: taskContext.length,
2290
- taskPreview: taskContext.substring(0, 100)
2291
- });
2292
2214
  const userPrompt = `Current task: ${taskContext}
2293
2215
 
2294
2216
  Available workers:
2295
2217
  ${workerInfo}
2296
2218
 
2297
2219
  Select the best worker(s) for this task and explain your reasoning.`;
2298
- const conversationHistory = [];
2299
- let attempt = 0;
2300
- while (attempt < maxRetries) {
2301
- logger.debug("LLM routing attempt", {
2302
- attempt: attempt + 1,
2303
- maxRetries,
2304
- conversationHistoryLength: conversationHistory.length
2305
- });
2306
- const messages = [
2307
- new import_messages4.SystemMessage(systemPrompt),
2308
- new import_messages4.HumanMessage(userPrompt),
2309
- ...conversationHistory
2310
- ];
2311
- const response = await config.model.invoke(messages);
2312
- if (response.tool_calls && response.tool_calls.length > 0) {
2313
- logger.info("LLM requested tool calls", {
2314
- toolCount: response.tool_calls.length,
2315
- toolNames: response.tool_calls.map((tc) => tc.name)
2316
- });
2317
- if (tools.length === 0) {
2318
- throw new Error("LLM requested tool calls but no tools are configured");
2319
- }
2320
- const toolResults = await executeTools(response.tool_calls, tools);
2321
- conversationHistory.push(
2322
- new import_messages4.AIMessage({ content: response.content || "", tool_calls: response.tool_calls }),
2323
- ...toolResults
2324
- );
2325
- attempt++;
2326
- logger.debug("Retrying routing with tool results", { attempt });
2327
- continue;
2328
- }
2329
- logger.debug("Parsing routing decision from LLM response");
2330
- let decision;
2331
- if (response && typeof response === "object" && ("targetAgent" in response || "targetAgents" in response)) {
2332
- logger.debug("Response is structured output", {
2333
- hasTargetAgent: "targetAgent" in response,
2334
- hasTargetAgents: "targetAgents" in response
2335
- });
2336
- decision = response;
2337
- } else if (response.content) {
2338
- if (typeof response.content === "string") {
2339
- try {
2340
- decision = JSON.parse(response.content);
2341
- logger.debug("Parsed JSON from string response");
2342
- } catch (error) {
2343
- logger.error("Failed to parse routing decision", {
2344
- content: response.content,
2345
- error: error instanceof Error ? error.message : String(error)
2346
- });
2347
- throw new Error(`Failed to parse routing decision from LLM. Expected JSON but got: ${response.content}`);
2348
- }
2349
- } else if (typeof response.content === "object") {
2350
- logger.debug("Response content is already an object");
2351
- decision = response.content;
2352
- } else {
2353
- logger.error("Unexpected response content type", {
2354
- type: typeof response.content
2355
- });
2356
- throw new Error(`Unexpected response content type: ${typeof response.content}`);
2357
- }
2358
- } else {
2359
- logger.error("Unexpected response format", {
2360
- response: JSON.stringify(response)
2361
- });
2362
- throw new Error(`Unexpected response format: ${JSON.stringify(response)}`);
2363
- }
2364
- const result = {
2365
- targetAgent: decision.targetAgent,
2366
- targetAgents: decision.targetAgents,
2367
- reasoning: decision.reasoning,
2368
- confidence: decision.confidence,
2369
- strategy: "llm-based",
2370
- timestamp: Date.now()
2371
- };
2372
- logger.info("LLM routing decision made", {
2373
- targetAgent: result.targetAgent,
2374
- targetAgents: result.targetAgents,
2375
- isParallel: result.targetAgents && result.targetAgents.length > 1,
2376
- confidence: result.confidence,
2377
- reasoning: result.reasoning
2378
- });
2379
- return result;
2380
- }
2381
- logger.error("Max tool retries exceeded", { maxRetries });
2382
- throw new Error(`Max tool retries (${maxRetries}) exceeded without routing decision`);
2220
+ const messages = [
2221
+ new import_messages4.SystemMessage(systemPrompt),
2222
+ new import_messages4.HumanMessage(userPrompt)
2223
+ ];
2224
+ const decision = await config.model.invoke(messages);
2225
+ return {
2226
+ targetAgent: decision.targetAgent,
2227
+ targetAgents: decision.targetAgents,
2228
+ reasoning: decision.reasoning,
2229
+ confidence: decision.confidence,
2230
+ strategy: "llm-based",
2231
+ timestamp: Date.now()
2232
+ };
2383
2233
  }
2384
2234
  };
2385
2235
  var roundRobinRouting = {
2386
2236
  name: "round-robin",
2387
2237
  async route(state, config) {
2388
- logger.info("Starting round-robin routing", {
2389
- iteration: state.iteration
2390
- });
2391
2238
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id]) => id);
2392
- logger.debug("Available workers for round-robin", {
2393
- count: availableWorkers.length,
2394
- workers: availableWorkers
2395
- });
2396
2239
  if (availableWorkers.length === 0) {
2397
- logger.error("No available workers for round-robin routing");
2398
2240
  throw new Error("No available workers for round-robin routing");
2399
2241
  }
2400
2242
  const lastRoutingIndex = state.routingHistory.length % availableWorkers.length;
2401
2243
  const targetAgent = availableWorkers[lastRoutingIndex];
2402
- logger.info("Round-robin routing decision", {
2403
- targetAgent,
2404
- index: lastRoutingIndex + 1,
2405
- totalWorkers: availableWorkers.length
2406
- });
2407
2244
  return {
2408
2245
  targetAgent,
2409
2246
  targetAgents: null,
@@ -2417,15 +2254,8 @@ var roundRobinRouting = {
2417
2254
  var skillBasedRouting = {
2418
2255
  name: "skill-based",
2419
2256
  async route(state, config) {
2420
- logger.info("Starting skill-based routing", {
2421
- iteration: state.iteration
2422
- });
2423
2257
  const lastMessage = state.messages[state.messages.length - 1];
2424
2258
  const taskContent = (lastMessage?.content || state.input).toLowerCase();
2425
- logger.debug("Task content for skill matching", {
2426
- taskLength: taskContent.length,
2427
- taskPreview: taskContent.substring(0, 100)
2428
- });
2429
2259
  const workerScores = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => {
2430
2260
  const skillMatches = caps.skills.filter(
2431
2261
  (skill) => taskContent.includes(skill.toLowerCase())
@@ -2436,20 +2266,11 @@ var skillBasedRouting = {
2436
2266
  const score = skillMatches * 2 + toolMatches;
2437
2267
  return { id, score, skills: caps.skills, tools: caps.tools };
2438
2268
  }).filter((w) => w.score > 0).sort((a, b) => b.score - a.score);
2439
- logger.debug("Worker skill scores", {
2440
- scoredWorkers: workerScores.map((w) => ({ id: w.id, score: w.score }))
2441
- });
2442
2269
  if (workerScores.length === 0) {
2443
- logger.warn("No skill matches found, using fallback");
2444
2270
  const firstAvailable = Object.entries(state.workers).find(([_, caps]) => caps.available);
2445
2271
  if (!firstAvailable) {
2446
- logger.error("No available workers for skill-based routing");
2447
2272
  throw new Error("No available workers for skill-based routing");
2448
2273
  }
2449
- logger.info("Skill-based routing fallback decision", {
2450
- targetAgent: firstAvailable[0],
2451
- confidence: 0.5
2452
- });
2453
2274
  return {
2454
2275
  targetAgent: firstAvailable[0],
2455
2276
  targetAgents: null,
@@ -2461,12 +2282,6 @@ var skillBasedRouting = {
2461
2282
  }
2462
2283
  const best = workerScores[0];
2463
2284
  const confidence = Math.min(best.score / 5, 1);
2464
- logger.info("Skill-based routing decision", {
2465
- targetAgent: best.id,
2466
- score: best.score,
2467
- confidence,
2468
- matchedSkills: best.skills
2469
- });
2470
2285
  return {
2471
2286
  targetAgent: best.id,
2472
2287
  targetAgents: null,
@@ -2480,26 +2295,13 @@ var skillBasedRouting = {
2480
2295
  var loadBalancedRouting = {
2481
2296
  name: "load-balanced",
2482
2297
  async route(state, config) {
2483
- logger.info("Starting load-balanced routing", {
2484
- iteration: state.iteration
2485
- });
2486
2298
  const availableWorkers = Object.entries(state.workers).filter(([_, caps]) => caps.available).map(([id, caps]) => ({ id, workload: caps.currentWorkload })).sort((a, b) => a.workload - b.workload);
2487
- logger.debug("Worker workloads", {
2488
- workers: availableWorkers.map((w) => ({ id: w.id, workload: w.workload }))
2489
- });
2490
2299
  if (availableWorkers.length === 0) {
2491
- logger.error("No available workers for load-balanced routing");
2492
2300
  throw new Error("No available workers for load-balanced routing");
2493
2301
  }
2494
2302
  const targetWorker = availableWorkers[0];
2495
2303
  const avgWorkload = availableWorkers.reduce((sum, w) => sum + w.workload, 0) / availableWorkers.length;
2496
2304
  const confidence = targetWorker.workload === 0 ? 1 : Math.max(0.5, 1 - targetWorker.workload / (avgWorkload * 2));
2497
- logger.info("Load-balanced routing decision", {
2498
- targetAgent: targetWorker.id,
2499
- workload: targetWorker.workload,
2500
- avgWorkload: avgWorkload.toFixed(1),
2501
- confidence
2502
- });
2503
2305
  return {
2504
2306
  targetAgent: targetWorker.id,
2505
2307
  targetAgents: null,
@@ -2513,24 +2315,13 @@ var loadBalancedRouting = {
2513
2315
  var ruleBasedRouting = {
2514
2316
  name: "rule-based",
2515
2317
  async route(state, config) {
2516
- logger.info("Starting rule-based routing", {
2517
- iteration: state.iteration
2518
- });
2519
2318
  if (!config.routingFn) {
2520
- logger.error("Rule-based routing requires a custom routing function");
2521
2319
  throw new Error("Rule-based routing requires a custom routing function");
2522
2320
  }
2523
- const decision = await config.routingFn(state);
2524
- logger.info("Rule-based routing decision", {
2525
- targetAgent: decision.targetAgent,
2526
- targetAgents: decision.targetAgents,
2527
- confidence: decision.confidence
2528
- });
2529
- return decision;
2321
+ return await config.routingFn(state);
2530
2322
  }
2531
2323
  };
2532
2324
  function getRoutingStrategy(name) {
2533
- logger.debug("Getting routing strategy", { name });
2534
2325
  switch (name) {
2535
2326
  case "llm-based":
2536
2327
  return llmBasedRouting;
@@ -2543,15 +2334,14 @@ function getRoutingStrategy(name) {
2543
2334
  case "rule-based":
2544
2335
  return ruleBasedRouting;
2545
2336
  default:
2546
- logger.error("Unknown routing strategy", { name });
2547
2337
  throw new Error(`Unknown routing strategy: ${name}`);
2548
2338
  }
2549
2339
  }
2550
2340
 
2551
2341
  // src/multi-agent/utils.ts
2552
- var import_core9 = require("@agentforge/core");
2553
- var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || import_core9.LogLevel.INFO;
2554
- var logger2 = (0, import_core9.createLogger)("multi-agent", { level: logLevel2 });
2342
+ var import_core8 = require("@agentforge/core");
2343
+ var logLevel = process.env.LOG_LEVEL?.toLowerCase() || import_core8.LogLevel.INFO;
2344
+ var logger = (0, import_core8.createLogger)("multi-agent", { level: logLevel });
2555
2345
  function isReActAgent(obj) {
2556
2346
  return obj && typeof obj === "object" && typeof obj.invoke === "function" && typeof obj.stream === "function" && // Additional check to ensure it's not just any object with invoke/stream
2557
2347
  (obj.constructor?.name === "CompiledGraph" || obj.constructor?.name === "CompiledStateGraph");
@@ -2559,9 +2349,9 @@ function isReActAgent(obj) {
2559
2349
  function wrapReActAgent(workerId, agent, verbose = false) {
2560
2350
  return async (state, config) => {
2561
2351
  try {
2562
- logger2.debug("Wrapping ReAct agent execution", { workerId });
2352
+ logger.debug("Wrapping ReAct agent execution", { workerId });
2563
2353
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2564
- logger2.debug("Extracted task", {
2354
+ logger.debug("Extracted task", {
2565
2355
  workerId,
2566
2356
  taskPreview: task.substring(0, 100) + (task.length > 100 ? "..." : "")
2567
2357
  });
@@ -2569,7 +2359,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2569
2359
  (assignment) => assignment.workerId === workerId && !state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2570
2360
  );
2571
2361
  if (!currentAssignment) {
2572
- logger2.debug("No active assignment found", { workerId });
2362
+ logger.debug("No active assignment found", { workerId });
2573
2363
  return {};
2574
2364
  }
2575
2365
  const result = await agent.invoke(
@@ -2580,14 +2370,14 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2580
2370
  // Pass through the config for checkpointing and interrupt support
2581
2371
  );
2582
2372
  const response = result.messages?.[result.messages.length - 1]?.content || "No response";
2583
- logger2.debug("Received response from ReAct agent", {
2373
+ logger.debug("Received response from ReAct agent", {
2584
2374
  workerId,
2585
2375
  responsePreview: response.substring(0, 100) + (response.length > 100 ? "..." : "")
2586
2376
  });
2587
2377
  const toolsUsed = result.actions?.map((action) => action.name).filter(Boolean) || [];
2588
2378
  const uniqueTools = [...new Set(toolsUsed)];
2589
2379
  if (uniqueTools.length > 0) {
2590
- logger2.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2380
+ logger.debug("Tools used by ReAct agent", { workerId, tools: uniqueTools });
2591
2381
  }
2592
2382
  const taskResult = {
2593
2383
  assignmentId: currentAssignment.id,
@@ -2606,7 +2396,7 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2606
2396
  };
2607
2397
  } catch (error) {
2608
2398
  const errorMessage = handleNodeError(error, `react-agent:${workerId}`, false);
2609
- logger2.error("Error in ReAct agent execution", {
2399
+ logger.error("Error in ReAct agent execution", {
2610
2400
  workerId,
2611
2401
  error: errorMessage
2612
2402
  });
@@ -2638,9 +2428,9 @@ function wrapReActAgent(workerId, agent, verbose = false) {
2638
2428
 
2639
2429
  // src/multi-agent/nodes.ts
2640
2430
  var import_messages5 = require("@langchain/core/messages");
2641
- var import_core10 = require("@agentforge/core");
2642
- var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || import_core10.LogLevel.INFO;
2643
- var logger3 = (0, import_core10.createLogger)("multi-agent:nodes", { level: logLevel3 });
2431
+ var import_core9 = require("@agentforge/core");
2432
+ var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || import_core9.LogLevel.INFO;
2433
+ var logger2 = (0, import_core9.createLogger)("multi-agent:nodes", { level: logLevel2 });
2644
2434
  var DEFAULT_AGGREGATOR_SYSTEM_PROMPT = `You are an aggregator agent responsible for combining results from multiple worker agents.
2645
2435
 
2646
2436
  Your job is to:
@@ -2658,19 +2448,19 @@ function createSupervisorNode(config) {
2658
2448
  } = config;
2659
2449
  return async (state) => {
2660
2450
  try {
2661
- logger3.info("Supervisor node executing", {
2451
+ logger2.info("Supervisor node executing", {
2662
2452
  iteration: state.iteration,
2663
2453
  maxIterations,
2664
2454
  activeAssignments: state.activeAssignments.length,
2665
2455
  completedTasks: state.completedTasks.length
2666
2456
  });
2667
- logger3.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2457
+ logger2.debug(`Routing iteration ${state.iteration}/${maxIterations}`);
2668
2458
  if (state.iteration >= maxIterations) {
2669
- logger3.warn("Max iterations reached", {
2459
+ logger2.warn("Max iterations reached", {
2670
2460
  iteration: state.iteration,
2671
2461
  maxIterations
2672
2462
  });
2673
- logger3.debug("Max iterations reached, moving to aggregation");
2463
+ logger2.debug("Max iterations reached, moving to aggregation");
2674
2464
  return {
2675
2465
  status: "aggregating",
2676
2466
  currentAgent: "aggregator"
@@ -2679,26 +2469,26 @@ function createSupervisorNode(config) {
2679
2469
  const allCompleted = state.activeAssignments.every(
2680
2470
  (assignment) => state.completedTasks.some((task2) => task2.assignmentId === assignment.id)
2681
2471
  );
2682
- logger3.debug("Checking task completion", {
2472
+ logger2.debug("Checking task completion", {
2683
2473
  activeAssignments: state.activeAssignments.length,
2684
2474
  completedTasks: state.completedTasks.length,
2685
2475
  allCompleted
2686
2476
  });
2687
2477
  if (allCompleted && state.activeAssignments.length > 0) {
2688
- logger3.info("All tasks completed, moving to aggregation", {
2478
+ logger2.info("All tasks completed, moving to aggregation", {
2689
2479
  completedCount: state.completedTasks.length
2690
2480
  });
2691
- logger3.debug("All tasks completed, moving to aggregation");
2481
+ logger2.debug("All tasks completed, moving to aggregation");
2692
2482
  return {
2693
2483
  status: "aggregating",
2694
2484
  currentAgent: "aggregator"
2695
2485
  };
2696
2486
  }
2697
- logger3.debug("Getting routing strategy", { strategy });
2487
+ logger2.debug("Getting routing strategy", { strategy });
2698
2488
  const routingImpl = getRoutingStrategy(strategy);
2699
2489
  const decision = await routingImpl.route(state, config);
2700
2490
  const targetAgents = decision.targetAgents && decision.targetAgents.length > 0 ? decision.targetAgents : decision.targetAgent ? [decision.targetAgent] : [];
2701
- logger3.debug("Target agents determined", {
2491
+ logger2.debug("Target agents determined", {
2702
2492
  targetAgents,
2703
2493
  isParallel: targetAgents.length > 1,
2704
2494
  decision: {
@@ -2707,17 +2497,17 @@ function createSupervisorNode(config) {
2707
2497
  }
2708
2498
  });
2709
2499
  if (targetAgents.length === 0) {
2710
- logger3.error("No target agents specified in routing decision");
2500
+ logger2.error("No target agents specified in routing decision");
2711
2501
  throw new Error("Routing decision must specify at least one target agent");
2712
2502
  }
2713
2503
  if (targetAgents.length === 1) {
2714
- logger3.info("Routing to single agent", {
2504
+ logger2.info("Routing to single agent", {
2715
2505
  targetAgent: targetAgents[0],
2716
2506
  reasoning: decision.reasoning,
2717
2507
  confidence: decision.confidence
2718
2508
  });
2719
2509
  } else {
2720
- logger3.info("Routing to multiple agents in parallel", {
2510
+ logger2.info("Routing to multiple agents in parallel", {
2721
2511
  targetAgents,
2722
2512
  count: targetAgents.length,
2723
2513
  reasoning: decision.reasoning,
@@ -2725,9 +2515,9 @@ function createSupervisorNode(config) {
2725
2515
  });
2726
2516
  }
2727
2517
  if (targetAgents.length === 1) {
2728
- logger3.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2518
+ logger2.debug(`Routing to ${targetAgents[0]}: ${decision.reasoning}`);
2729
2519
  } else {
2730
- logger3.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2520
+ logger2.debug(`Routing to ${targetAgents.length} agents in parallel [${targetAgents.join(", ")}]: ${decision.reasoning}`);
2731
2521
  }
2732
2522
  const task = state.messages[state.messages.length - 1]?.content || state.input;
2733
2523
  const assignments = targetAgents.map((workerId) => ({
@@ -2737,7 +2527,7 @@ function createSupervisorNode(config) {
2737
2527
  priority: 5,
2738
2528
  assignedAt: Date.now()
2739
2529
  }));
2740
- logger3.debug("Created task assignments", {
2530
+ logger2.debug("Created task assignments", {
2741
2531
  assignmentCount: assignments.length,
2742
2532
  assignments: assignments.map((a) => ({
2743
2533
  id: a.id,
@@ -2757,7 +2547,7 @@ function createSupervisorNode(config) {
2757
2547
  priority: assignment.priority
2758
2548
  }
2759
2549
  }));
2760
- logger3.info("Supervisor routing complete", {
2550
+ logger2.info("Supervisor routing complete", {
2761
2551
  currentAgent: targetAgents.join(","),
2762
2552
  status: "executing",
2763
2553
  assignmentCount: assignments.length,
@@ -2774,7 +2564,7 @@ function createSupervisorNode(config) {
2774
2564
  iteration: state.iteration + 1
2775
2565
  };
2776
2566
  } catch (error) {
2777
- logger3.error("Supervisor node error", {
2567
+ logger2.error("Supervisor node error", {
2778
2568
  error: error instanceof Error ? error.message : String(error),
2779
2569
  stack: error instanceof Error ? error.stack : void 0,
2780
2570
  iteration: state.iteration
@@ -2799,7 +2589,7 @@ function createWorkerNode(config) {
2799
2589
  } = config;
2800
2590
  return async (state, runConfig) => {
2801
2591
  try {
2802
- logger3.info("Worker node executing", {
2592
+ logger2.info("Worker node executing", {
2803
2593
  workerId: id,
2804
2594
  iteration: state.iteration,
2805
2595
  activeAssignments: state.activeAssignments.length
@@ -2808,39 +2598,39 @@ function createWorkerNode(config) {
2808
2598
  (assignment) => assignment.workerId === id && !state.completedTasks.some((task) => task.assignmentId === assignment.id)
2809
2599
  );
2810
2600
  if (!currentAssignment) {
2811
- logger3.debug("No active assignment found for worker", {
2601
+ logger2.debug("No active assignment found for worker", {
2812
2602
  workerId: id,
2813
2603
  totalActiveAssignments: state.activeAssignments.length,
2814
2604
  completedTasks: state.completedTasks.length
2815
2605
  });
2816
2606
  return {};
2817
2607
  }
2818
- logger3.info("Worker processing assignment", {
2608
+ logger2.info("Worker processing assignment", {
2819
2609
  workerId: id,
2820
2610
  assignmentId: currentAssignment.id,
2821
2611
  taskLength: currentAssignment.task.length,
2822
2612
  taskPreview: currentAssignment.task.substring(0, 100)
2823
2613
  });
2824
2614
  if (executeFn) {
2825
- logger3.debug("Using custom execution function", { workerId: id });
2615
+ logger2.debug("Using custom execution function", { workerId: id });
2826
2616
  return await executeFn(state, runConfig);
2827
2617
  }
2828
2618
  if (agent) {
2829
2619
  if (isReActAgent(agent)) {
2830
- logger3.debug("Using ReAct agent", { workerId: id });
2620
+ logger2.debug("Using ReAct agent", { workerId: id });
2831
2621
  const wrappedFn = wrapReActAgent(id, agent, verbose);
2832
2622
  return await wrappedFn(state, runConfig);
2833
2623
  } else {
2834
- logger3.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2624
+ logger2.warn("Agent provided but not a ReAct agent, falling back", { workerId: id });
2835
2625
  }
2836
2626
  }
2837
2627
  if (!model) {
2838
- logger3.error("Worker missing required configuration", { workerId: id });
2628
+ logger2.error("Worker missing required configuration", { workerId: id });
2839
2629
  throw new Error(
2840
2630
  `Worker ${id} requires either a model, an agent, or a custom execution function. Provide one of: config.model, config.agent, or config.executeFn`
2841
2631
  );
2842
2632
  }
2843
- logger3.debug("Using default LLM execution", {
2633
+ logger2.debug("Using default LLM execution", {
2844
2634
  workerId: id,
2845
2635
  hasTools: tools.length > 0,
2846
2636
  toolCount: tools.length
@@ -2856,18 +2646,18 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2856
2646
  ];
2857
2647
  let modelToUse = model;
2858
2648
  if (tools.length > 0 && model.bindTools) {
2859
- logger3.debug("Binding tools to model", {
2649
+ logger2.debug("Binding tools to model", {
2860
2650
  workerId: id,
2861
2651
  toolCount: tools.length,
2862
2652
  toolNames: tools.map((t) => t.metadata.name)
2863
2653
  });
2864
- const langchainTools = (0, import_core10.toLangChainTools)(tools);
2654
+ const langchainTools = (0, import_core9.toLangChainTools)(tools);
2865
2655
  modelToUse = model.bindTools(langchainTools);
2866
2656
  }
2867
- logger3.debug("Invoking LLM", { workerId: id });
2657
+ logger2.debug("Invoking LLM", { workerId: id });
2868
2658
  const response = await modelToUse.invoke(messages);
2869
2659
  const result = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
2870
- logger3.info("Worker task completed", {
2660
+ logger2.info("Worker task completed", {
2871
2661
  workerId: id,
2872
2662
  assignmentId: currentAssignment.id,
2873
2663
  resultLength: result.length,
@@ -2902,7 +2692,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2902
2692
  currentWorkload: Math.max(0, capabilities.currentWorkload - 1)
2903
2693
  }
2904
2694
  };
2905
- logger3.debug("Worker state update", {
2695
+ logger2.debug("Worker state update", {
2906
2696
  workerId: id,
2907
2697
  newWorkload: updatedWorkers[id].currentWorkload
2908
2698
  });
@@ -2913,7 +2703,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2913
2703
  };
2914
2704
  } catch (error) {
2915
2705
  const errorMessage = handleNodeError(error, `worker:${id}`, false);
2916
- logger3.error("Worker node error", {
2706
+ logger2.error("Worker node error", {
2917
2707
  workerId: id,
2918
2708
  error: errorMessage
2919
2709
  });
@@ -2921,7 +2711,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2921
2711
  (assignment) => assignment.workerId === id
2922
2712
  );
2923
2713
  if (currentAssignment) {
2924
- logger3.warn("Creating error result for assignment", {
2714
+ logger2.warn("Creating error result for assignment", {
2925
2715
  workerId: id,
2926
2716
  assignmentId: currentAssignment.id
2927
2717
  });
@@ -2939,7 +2729,7 @@ Execute the assigned task using your skills and tools. Provide a clear, actionab
2939
2729
  status: "routing"
2940
2730
  };
2941
2731
  }
2942
- logger3.error("No assignment found for error handling", { workerId: id });
2732
+ logger2.error("No assignment found for error handling", { workerId: id });
2943
2733
  return {
2944
2734
  status: "failed",
2945
2735
  error: errorMessage
@@ -2956,16 +2746,16 @@ function createAggregatorNode(config = {}) {
2956
2746
  } = config;
2957
2747
  return async (state) => {
2958
2748
  try {
2959
- logger3.info("Aggregator node executing", {
2749
+ logger2.info("Aggregator node executing", {
2960
2750
  completedTasks: state.completedTasks.length,
2961
2751
  successfulTasks: state.completedTasks.filter((t) => t.success).length,
2962
2752
  failedTasks: state.completedTasks.filter((t) => !t.success).length
2963
2753
  });
2964
- logger3.debug("Combining results from workers");
2754
+ logger2.debug("Combining results from workers");
2965
2755
  if (aggregateFn) {
2966
- logger3.debug("Using custom aggregation function");
2756
+ logger2.debug("Using custom aggregation function");
2967
2757
  const response2 = await aggregateFn(state);
2968
- logger3.info("Custom aggregation complete", {
2758
+ logger2.info("Custom aggregation complete", {
2969
2759
  responseLength: response2.length
2970
2760
  });
2971
2761
  return {
@@ -2974,16 +2764,16 @@ function createAggregatorNode(config = {}) {
2974
2764
  };
2975
2765
  }
2976
2766
  if (state.completedTasks.length === 0) {
2977
- logger3.warn("No completed tasks to aggregate");
2767
+ logger2.warn("No completed tasks to aggregate");
2978
2768
  return {
2979
2769
  response: "No tasks were completed.",
2980
2770
  status: "completed"
2981
2771
  };
2982
2772
  }
2983
2773
  if (!model) {
2984
- logger3.debug("No model provided, concatenating results");
2774
+ logger2.debug("No model provided, concatenating results");
2985
2775
  const combinedResults = state.completedTasks.filter((task) => task.success).map((task) => task.result).join("\n\n");
2986
- logger3.info("Simple concatenation complete", {
2776
+ logger2.info("Simple concatenation complete", {
2987
2777
  resultLength: combinedResults.length
2988
2778
  });
2989
2779
  return {
@@ -2991,7 +2781,7 @@ function createAggregatorNode(config = {}) {
2991
2781
  status: "completed"
2992
2782
  };
2993
2783
  }
2994
- logger3.debug("Using LLM for intelligent aggregation", {
2784
+ logger2.debug("Using LLM for intelligent aggregation", {
2995
2785
  taskCount: state.completedTasks.length
2996
2786
  });
2997
2787
  const taskResults = state.completedTasks.map((task, idx) => {
@@ -3010,20 +2800,20 @@ Please synthesize these results into a comprehensive response that addresses the
3010
2800
  new import_messages5.SystemMessage(systemPrompt),
3011
2801
  new import_messages5.HumanMessage(userPrompt)
3012
2802
  ];
3013
- logger3.debug("Invoking aggregation LLM");
2803
+ logger2.debug("Invoking aggregation LLM");
3014
2804
  const response = await model.invoke(messages);
3015
2805
  const aggregatedResponse = typeof response.content === "string" ? response.content : JSON.stringify(response.content);
3016
- logger3.info("Aggregation complete", {
2806
+ logger2.info("Aggregation complete", {
3017
2807
  responseLength: aggregatedResponse.length,
3018
2808
  responsePreview: aggregatedResponse.substring(0, 100)
3019
2809
  });
3020
- logger3.debug("Aggregation complete");
2810
+ logger2.debug("Aggregation complete");
3021
2811
  return {
3022
2812
  response: aggregatedResponse,
3023
2813
  status: "completed"
3024
2814
  };
3025
2815
  } catch (error) {
3026
- logger3.error("Aggregator node error", {
2816
+ logger2.error("Aggregator node error", {
3027
2817
  error: error instanceof Error ? error.message : String(error),
3028
2818
  stack: error instanceof Error ? error.stack : void 0,
3029
2819
  completedTasks: state.completedTasks.length
@@ -3038,9 +2828,9 @@ Please synthesize these results into a comprehensive response that addresses the
3038
2828
 
3039
2829
  // src/multi-agent/agent.ts
3040
2830
  var import_langgraph4 = require("@langchain/langgraph");
3041
- var import_core11 = require("@agentforge/core");
3042
- var logLevel4 = process.env.LOG_LEVEL?.toLowerCase() || import_core11.LogLevel.INFO;
3043
- var logger4 = (0, import_core11.createLogger)("multi-agent:system", { level: logLevel4 });
2831
+ var import_core10 = require("@agentforge/core");
2832
+ var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || import_core10.LogLevel.INFO;
2833
+ var logger3 = (0, import_core10.createLogger)("multi-agent:system", { level: logLevel3 });
3044
2834
  function createMultiAgentSystem(config) {
3045
2835
  const {
3046
2836
  supervisor,
@@ -3057,10 +2847,6 @@ function createMultiAgentSystem(config) {
3057
2847
  if (supervisor.strategy === "llm-based") {
3058
2848
  configuredModel = configuredModel.withStructuredOutput(RoutingDecisionSchema);
3059
2849
  }
3060
- if (supervisor.tools && supervisor.tools.length > 0) {
3061
- const langchainTools = (0, import_core11.toLangChainTools)(supervisor.tools);
3062
- configuredModel = configuredModel.bindTools(langchainTools);
3063
- }
3064
2850
  supervisorConfig.model = configuredModel;
3065
2851
  }
3066
2852
  const supervisorNode = createSupervisorNode(supervisorConfig);
@@ -3082,46 +2868,46 @@ function createMultiAgentSystem(config) {
3082
2868
  });
3083
2869
  workflow.addNode("aggregator", aggregatorNode);
3084
2870
  const supervisorRouter = (state) => {
3085
- logger4.debug("Supervisor router executing", {
2871
+ logger3.debug("Supervisor router executing", {
3086
2872
  status: state.status,
3087
2873
  currentAgent: state.currentAgent,
3088
2874
  iteration: state.iteration
3089
2875
  });
3090
2876
  if (state.status === "completed" || state.status === "failed") {
3091
- logger4.info("Supervisor router: ending workflow", { status: state.status });
2877
+ logger3.info("Supervisor router: ending workflow", { status: state.status });
3092
2878
  return import_langgraph4.END;
3093
2879
  }
3094
2880
  if (state.status === "aggregating") {
3095
- logger4.info("Supervisor router: routing to aggregator");
2881
+ logger3.info("Supervisor router: routing to aggregator");
3096
2882
  return "aggregator";
3097
2883
  }
3098
2884
  if (state.currentAgent && state.currentAgent !== "supervisor") {
3099
2885
  if (state.currentAgent.includes(",")) {
3100
2886
  const agents = state.currentAgent.split(",").map((a) => a.trim());
3101
- logger4.info("Supervisor router: parallel routing", {
2887
+ logger3.info("Supervisor router: parallel routing", {
3102
2888
  agents,
3103
2889
  count: agents.length
3104
2890
  });
3105
2891
  return agents;
3106
2892
  }
3107
- logger4.info("Supervisor router: single agent routing", {
2893
+ logger3.info("Supervisor router: single agent routing", {
3108
2894
  targetAgent: state.currentAgent
3109
2895
  });
3110
2896
  return state.currentAgent;
3111
2897
  }
3112
- logger4.debug("Supervisor router: staying at supervisor");
2898
+ logger3.debug("Supervisor router: staying at supervisor");
3113
2899
  return "supervisor";
3114
2900
  };
3115
2901
  const workerRouter = (state) => {
3116
- logger4.debug("Worker router executing", {
2902
+ logger3.debug("Worker router executing", {
3117
2903
  iteration: state.iteration,
3118
2904
  completedTasks: state.completedTasks.length
3119
2905
  });
3120
- logger4.debug("Worker router: returning to supervisor");
2906
+ logger3.debug("Worker router: returning to supervisor");
3121
2907
  return "supervisor";
3122
2908
  };
3123
2909
  const aggregatorRouter = (state) => {
3124
- logger4.info("Aggregator router: ending workflow", {
2910
+ logger3.info("Aggregator router: ending workflow", {
3125
2911
  completedTasks: state.completedTasks.length,
3126
2912
  status: state.status
3127
2913
  });