@ai-setting/roy-agent-core 1.5.36 → 1.5.40

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.
Files changed (74) hide show
  1. package/dist/config/index.js +4 -3
  2. package/dist/env/agent/index.js +10 -9
  3. package/dist/env/commands/index.js +7 -6
  4. package/dist/env/context/index.js +21 -0
  5. package/dist/env/debug/index.js +4 -3
  6. package/dist/env/event-source/index.js +12 -6
  7. package/dist/env/hook/index.js +2 -1
  8. package/dist/env/index.js +41 -18
  9. package/dist/env/llm/index.js +8 -7
  10. package/dist/env/log-trace/index.js +10 -9
  11. package/dist/env/mcp/index.js +8 -7
  12. package/dist/env/mcp/tool/index.js +4 -4
  13. package/dist/env/memory/index.js +12 -11
  14. package/dist/env/memory/plugin/index.js +4 -4
  15. package/dist/env/plugin/index.js +18 -0
  16. package/dist/env/prompt/index.js +7 -6
  17. package/dist/env/session/index.js +11 -10
  18. package/dist/env/session/storage/index.js +2 -6
  19. package/dist/env/skill/index.js +7 -6
  20. package/dist/env/task/delegate/index.js +6 -5
  21. package/dist/env/task/index.js +10 -8
  22. package/dist/env/task/plugins/index.js +13 -6
  23. package/dist/env/task/storage/index.js +4 -4
  24. package/dist/env/tool/built-in/index.js +3 -3
  25. package/dist/env/tool/index.js +8 -7
  26. package/dist/env/workflow/engine/index.js +5 -5
  27. package/dist/env/workflow/index.js +9 -8
  28. package/dist/env/workflow/storage/index.js +5 -5
  29. package/dist/env/workflow/tools/index.js +3 -3
  30. package/dist/env/workflow/utils/index.js +4 -4
  31. package/dist/index.js +67 -60
  32. package/dist/shared/@ai-setting/{roy-agent-core-44hnfb02.js → roy-agent-core-10n2jh7p.js} +1 -1
  33. package/dist/shared/@ai-setting/{roy-agent-core-xt3fx7m1.js → roy-agent-core-15x8fe5h.js} +38 -56
  34. package/dist/shared/@ai-setting/{roy-agent-core-1akcqxj9.js → roy-agent-core-1bfmxx89.js} +1 -1
  35. package/dist/shared/@ai-setting/{roy-agent-core-ty94k28r.js → roy-agent-core-2jnzv9at.js} +2 -2
  36. package/dist/shared/@ai-setting/{roy-agent-core-3jywqmdd.js → roy-agent-core-2x07feb7.js} +317 -65
  37. package/dist/shared/@ai-setting/{roy-agent-core-cefh9hjv.js → roy-agent-core-4jqq077c.js} +1 -1
  38. package/dist/shared/@ai-setting/{roy-agent-core-xs5rsgat.js → roy-agent-core-58k274fg.js} +108 -23
  39. package/dist/shared/@ai-setting/{roy-agent-core-np1w5dpe.js → roy-agent-core-728h32vx.js} +268 -35
  40. package/dist/shared/@ai-setting/{roy-agent-core-jfh9q2qh.js → roy-agent-core-7b35emr7.js} +0 -15
  41. package/dist/shared/@ai-setting/{roy-agent-core-3rr5k71j.js → roy-agent-core-8n4bz6y3.js} +1 -1
  42. package/dist/shared/@ai-setting/{roy-agent-core-zpn0bqa8.js → roy-agent-core-9ffsvvcf.js} +1 -1
  43. package/dist/shared/@ai-setting/roy-agent-core-az13yzmc.js +11 -0
  44. package/dist/shared/@ai-setting/{roy-agent-core-0wdjp769.js → roy-agent-core-b4wd9tn6.js} +2 -2
  45. package/dist/shared/@ai-setting/{roy-agent-core-6kvtahqv.js → roy-agent-core-c3ct1346.js} +1 -1
  46. package/dist/shared/@ai-setting/{roy-agent-core-psv4v63c.js → roy-agent-core-c6592r3c.js} +19 -2
  47. package/dist/shared/@ai-setting/{roy-agent-core-c2wjwx16.js → roy-agent-core-c8f2hync.js} +305 -287
  48. package/dist/shared/@ai-setting/roy-agent-core-cevpwnq7.js +147 -0
  49. package/dist/shared/@ai-setting/{roy-agent-core-hkb529dw.js → roy-agent-core-dxbsc1zy.js} +7 -7
  50. package/dist/shared/@ai-setting/{roy-agent-core-vqspcspb.js → roy-agent-core-e130w7mv.js} +3 -3
  51. package/dist/shared/@ai-setting/{roy-agent-core-j0ke54vy.js → roy-agent-core-ee6nnnqw.js} +5 -5
  52. package/dist/shared/@ai-setting/{roy-agent-core-qdmt6nz7.js → roy-agent-core-eg6nv09z.js} +2 -2
  53. package/dist/shared/@ai-setting/{roy-agent-core-hd1z20yq.js → roy-agent-core-frx4p6d1.js} +1 -1
  54. package/dist/shared/@ai-setting/{roy-agent-core-bvr1761x.js → roy-agent-core-hsxn8m1j.js} +1 -1
  55. package/dist/shared/@ai-setting/{roy-agent-core-86gphny5.js → roy-agent-core-jqy2mdyq.js} +15 -1
  56. package/dist/shared/@ai-setting/{roy-agent-core-c0d3dtjd.js → roy-agent-core-kajktp3d.js} +7 -7
  57. package/dist/shared/@ai-setting/{roy-agent-core-eajcvp4e.js → roy-agent-core-kwhv9dcd.js} +2 -2
  58. package/dist/shared/@ai-setting/{roy-agent-core-r9ezzemr.js → roy-agent-core-m0wp34r4.js} +1 -1
  59. package/dist/shared/@ai-setting/{roy-agent-core-fg1kxf70.js → roy-agent-core-nqgrjja0.js} +5 -5
  60. package/dist/shared/@ai-setting/{roy-agent-core-d7cyjkf7.js → roy-agent-core-pwkk12p4.js} +1 -1
  61. package/dist/shared/@ai-setting/{roy-agent-core-97ma0pr5.js → roy-agent-core-pxcrzyv9.js} +2 -2
  62. package/dist/shared/@ai-setting/{roy-agent-core-zgypchmt.js → roy-agent-core-q5qj0fes.js} +19 -11
  63. package/dist/shared/@ai-setting/{roy-agent-core-sx7wsvnn.js → roy-agent-core-qakqwbbh.js} +2 -2
  64. package/dist/shared/@ai-setting/{roy-agent-core-qfdp3pvq.js → roy-agent-core-rsybkb38.js} +1 -1
  65. package/dist/shared/@ai-setting/roy-agent-core-ty33mnr7.js +14 -0
  66. package/dist/shared/@ai-setting/{roy-agent-core-3prpabp8.js → roy-agent-core-v53rfk99.js} +2 -2
  67. package/dist/shared/@ai-setting/{roy-agent-core-wjd5kars.js → roy-agent-core-wb43x8hd.js} +3 -3
  68. package/dist/shared/@ai-setting/{roy-agent-core-e2vk2qh7.js → roy-agent-core-yc543gnq.js} +6 -6
  69. package/dist/shared/@ai-setting/{roy-agent-core-gf2c2pxr.js → roy-agent-core-ycg9rk6z.js} +3 -3
  70. package/dist/shared/@ai-setting/roy-agent-core-z33en0cz.js +44 -0
  71. package/dist/shared/@ai-setting/{roy-agent-core-by55z88t.js → roy-agent-core-zrja5v78.js} +11 -11
  72. package/dist/shared/@ai-setting/{roy-agent-core-wft9ra24.js → roy-agent-core-zwp3jp02.js} +4 -4
  73. package/package.json +1 -1
  74. package/dist/shared/@ai-setting/roy-agent-core-bcbqy27c.js +0 -14
@@ -5,26 +5,29 @@ import {
5
5
  import {
6
6
  ContextError
7
7
  } from "./roy-agent-core-ctdhjv68.js";
8
+ import {
9
+ TracedAs,
10
+ init_decorator
11
+ } from "./roy-agent-core-q5qj0fes.js";
8
12
  import {
9
13
  envKeyToConfigKey
10
14
  } from "./roy-agent-core-qxhq8ven.js";
11
15
  import {
12
16
  BaseComponent
13
- } from "./roy-agent-core-cefh9hjv.js";
17
+ } from "./roy-agent-core-4jqq077c.js";
14
18
  import {
15
19
  globalHookManager
16
- } from "./roy-agent-core-86gphny5.js";
17
- import {
18
- SessionMessageConverter
19
- } from "./roy-agent-core-jfh9q2qh.js";
20
+ } from "./roy-agent-core-jqy2mdyq.js";
20
21
  import {
21
- TracedAs,
22
- init_decorator
23
- } from "./roy-agent-core-zgypchmt.js";
22
+ runWithEnvContextAsync
23
+ } from "./roy-agent-core-z33en0cz.js";
24
24
  import {
25
25
  createLogger,
26
26
  init_logger
27
- } from "./roy-agent-core-44hnfb02.js";
27
+ } from "./roy-agent-core-10n2jh7p.js";
28
+ import {
29
+ SessionMessageConverter
30
+ } from "./roy-agent-core-7b35emr7.js";
28
31
  import {
29
32
  __legacyDecorateClassTS
30
33
  } from "./roy-agent-core-fs0mn2jk.js";
@@ -463,195 +466,85 @@ class AgentComponent extends BaseComponent {
463
466
  logger.warn(`Failed to load session history: ${err}`);
464
467
  }
465
468
  }
466
- this.pushEnvEvent({
467
- type: "agent.start",
468
- payload: {
469
- sessionId: effectiveContext.sessionId,
470
- model: effectiveContext.model
471
- }
472
- });
473
- this.pushMessage(hookCtx, {
474
- role: "user",
475
- content: query
476
- });
477
- await this.executePluginHooks(agent, "agent:before.start", hookCtx);
478
- if (hookCtx._stopped) {
479
- return this.finalizeResult(result, hookCtx);
480
- }
481
- let iteration = 0;
482
- let finalText;
483
- while (iteration < agent.config.maxIterations) {
469
+ const envContext = {
470
+ traceId: effectiveContext.metadata?.traceId,
471
+ sessionId: effectiveContext.sessionId,
472
+ userId: effectiveContext.metadata?.userId,
473
+ messageId: effectiveContext.metadata?.messageId,
474
+ pluginEnabled: effectiveContext.pluginEnabled,
475
+ plugins: effectiveContext.plugins,
476
+ envEvent: effectiveContext.envEvent,
477
+ replyChannel: effectiveContext.envEvent?.metadata?.replyChannel,
478
+ sourceId: effectiveContext.envEvent?.metadata?.sourceId,
479
+ sourceType: effectiveContext.envEvent?.metadata?.sourceType,
480
+ metadata: { ...effectiveContext.metadata }
481
+ };
482
+ return await runWithEnvContextAsync(envContext, async () => {
483
+ this.pushEnvEvent({
484
+ type: "agent.start",
485
+ payload: {
486
+ sessionId: effectiveContext.sessionId,
487
+ model: effectiveContext.model
488
+ }
489
+ });
490
+ this.pushMessage(hookCtx, {
491
+ role: "user",
492
+ content: query
493
+ });
494
+ await this.executePluginHooks(agent, "agent:before.start", hookCtx);
484
495
  if (hookCtx._stopped) {
485
- break;
486
- }
487
- if (this.aborted.get(runId)) {
488
- hookCtx._stopped = true;
489
- hookCtx._stopReason = "aborted";
490
- break;
491
- }
492
- if (effectiveContext.abort?.aborted) {
493
- hookCtx._stopped = true;
494
- hookCtx._stopReason = "abort_signal";
495
- break;
496
+ return this.finalizeResult(result, hookCtx);
496
497
  }
497
- iteration++;
498
- hookCtx.iteration = iteration;
499
- result.iterations = iteration;
500
- logger.debug(`Iteration ${iteration} started`);
501
- this.doomLoopCaches.set(runId, new Map);
502
- hookCtx.maxIterations = agent.config.maxIterations;
503
- try {
504
- logger.debug(`[ReAct] Iteration ${iteration} buildMessages result: ${hookCtx.messages.length} messages`);
505
- await this.executePluginHooks(agent, "agent:before.llm", hookCtx);
506
- if (hookCtx._stopped)
498
+ let iteration = 0;
499
+ let finalText;
500
+ while (iteration < agent.config.maxIterations) {
501
+ if (hookCtx._stopped) {
507
502
  break;
508
- const llmOutput = await this.invokeLLM(hookCtx);
509
- hookCtx.llmOutput = llmOutput;
510
- if (this.aborted.get(runId) || effectiveContext.abort?.aborted) {
503
+ }
504
+ if (this.aborted.get(runId)) {
511
505
  hookCtx._stopped = true;
512
506
  hookCtx._stopReason = "aborted";
513
507
  break;
514
508
  }
515
- await this.executePluginHooks(agent, "agent:after.llm", hookCtx);
516
- if (hookCtx._stopped)
509
+ if (effectiveContext.abort?.aborted) {
510
+ hookCtx._stopped = true;
511
+ hookCtx._stopReason = "abort_signal";
517
512
  break;
518
- if (llmOutput.content && !llmOutput.toolCalls?.length) {
513
+ }
514
+ iteration++;
515
+ hookCtx.iteration = iteration;
516
+ result.iterations = iteration;
517
+ logger.debug(`Iteration ${iteration} started`);
518
+ this.doomLoopCaches.set(runId, new Map);
519
+ hookCtx.maxIterations = agent.config.maxIterations;
520
+ try {
521
+ logger.debug(`[ReAct] Iteration ${iteration} buildMessages result: ${hookCtx.messages.length} messages`);
522
+ await this.executePluginHooks(agent, "agent:before.llm", hookCtx);
523
+ if (hookCtx._stopped)
524
+ break;
525
+ const llmOutput = await this.invokeLLM(hookCtx);
526
+ hookCtx.llmOutput = llmOutput;
519
527
  if (this.aborted.get(runId) || effectiveContext.abort?.aborted) {
520
528
  hookCtx._stopped = true;
521
529
  hookCtx._stopReason = "aborted";
522
530
  break;
523
531
  }
524
- finalText = llmOutput.content;
525
- this.pushMessage(hookCtx, {
526
- role: "assistant",
527
- content: llmOutput.content
528
- });
529
- break;
530
- }
531
- if (llmOutput.toolCalls?.length) {
532
- const assistantParts = [];
533
- if (llmOutput.content) {
534
- assistantParts.push({
535
- type: "text",
536
- text: llmOutput.content
537
- });
538
- }
539
- if (llmOutput.reasoning) {
540
- assistantParts.push({
541
- type: "reasoning",
542
- text: llmOutput.reasoning,
543
- reasoningType: "core"
544
- });
545
- }
546
- for (const tc of llmOutput.toolCalls) {
547
- let argsStr = "";
548
- let argsObj = {};
549
- if (tc.function?.arguments) {
550
- if (typeof tc.function.arguments === "string") {
551
- argsStr = tc.function.arguments;
552
- try {
553
- argsObj = JSON.parse(argsStr);
554
- } catch {
555
- argsObj = { _raw: argsStr };
556
- }
557
- } else {
558
- argsObj = tc.function.arguments;
559
- argsStr = JSON.stringify(argsObj);
560
- }
561
- } else if (tc.arguments) {
562
- if (typeof tc.arguments === "string") {
563
- argsStr = tc.arguments;
564
- try {
565
- argsObj = JSON.parse(argsStr);
566
- } catch {
567
- argsObj = { _raw: argsStr };
568
- }
569
- } else {
570
- argsObj = tc.arguments;
571
- argsStr = JSON.stringify(argsObj);
572
- }
573
- }
574
- assistantParts.push({
575
- type: "tool-call",
576
- toolCallId: tc.id,
577
- toolName: tc.function?.name || tc.name || "unknown",
578
- input: argsObj,
579
- toolCall: {
580
- name: tc.function?.name || tc.name || "unknown",
581
- arguments: argsStr
582
- }
583
- });
584
- }
585
- const assistantContent = llmOutput.content?.substring(0, 80) || "(no text)";
586
- const toolCallNames = llmOutput.toolCalls?.map((tc) => tc.function?.name || tc.name).join(", ") || "none";
587
- logger.debug(`[ReAct] Iteration ${iteration} Adding assistant message: text="${assistantContent}" toolCalls=[${toolCallNames}]`);
588
- this.pushMessage(hookCtx, {
589
- role: "assistant",
590
- content: assistantParts
591
- });
592
- const allToolCalls = llmOutput.toolCalls;
593
- let processedCount = 0;
594
- for (const toolCall of allToolCalls) {
532
+ await this.executePluginHooks(agent, "agent:after.llm", hookCtx);
533
+ if (hookCtx._stopped)
534
+ break;
535
+ if (llmOutput.content && !llmOutput.toolCalls?.length) {
595
536
  if (this.aborted.get(runId) || effectiveContext.abort?.aborted) {
596
537
  hookCtx._stopped = true;
597
538
  hookCtx._stopReason = "aborted";
598
- this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted");
599
- break;
600
- }
601
- const func = toolCall.function;
602
- const tcName = func?.name || toolCall.name || "unknown";
603
- const tcArgs = func?.arguments ? typeof func.arguments === "string" ? JSON.parse(func.arguments) : func.arguments : toolCall.arguments;
604
- hookCtx.currentToolCall = {
605
- id: toolCall.id,
606
- name: tcName,
607
- arguments: tcArgs
608
- };
609
- const doomKey = `${tcName}:${JSON.stringify(tcArgs)}`;
610
- const agentCache = this.doomLoopCaches.get(runId) || new Map;
611
- const doomCount = agentCache.get(doomKey) || 0;
612
- if (doomCount >= agent.config.doomLoopThreshold) {
613
- hookCtx.error = new Error(`Doom loop detected: ${tcName}`);
614
- await this.executePluginHooks(agent, "on.error", hookCtx);
615
- result.error = hookCtx.error.message;
616
- this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted: Doom loop detected");
617
539
  break;
618
540
  }
619
- agentCache.set(doomKey, doomCount + 1);
620
- this.doomLoopCaches.set(runId, agentCache);
621
- await this.executePluginHooks(agent, "agent:before.tool", hookCtx);
622
- if (hookCtx._stopped) {
623
- this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted by plugin hook");
624
- break;
625
- }
626
- const toolResult = await this.executeTool(hookCtx);
627
- hookCtx.toolResult = toolResult;
628
- await this.executePluginHooks(agent, "agent:after.tool", hookCtx);
629
- if (hookCtx._stopped) {
630
- this.addRemainingToolResults(hookCtx, allToolCalls, processedCount + 1, "Execution aborted by plugin hook");
631
- break;
632
- }
633
- const toolOutput = toolResult.success ? toolResult.result.output || "" : toolResult.result.error || "Unknown error";
634
- const toolOutputPreview = typeof toolOutput === "string" ? toolOutput.substring(0, 50) : JSON.stringify(toolOutput).substring(0, 50);
635
- logger.debug(`[ReAct] Iteration ${iteration} Adding tool message: tool=${toolResult.name} output="${toolOutputPreview}..."`);
541
+ finalText = llmOutput.content;
636
542
  this.pushMessage(hookCtx, {
637
- role: "tool",
638
- content: [{
639
- type: "tool-result",
640
- toolCallId: hookCtx.currentToolCall.id,
641
- toolName: toolResult.name,
642
- output: toolOutput
643
- }]
543
+ role: "assistant",
544
+ content: llmOutput.content
644
545
  });
645
- result.toolCalls.push(hookCtx.currentToolCall);
646
- processedCount++;
546
+ break;
647
547
  }
648
- await this.executePluginHooks(agent, "agent:on.iteration", hookCtx);
649
- }
650
- } catch (error) {
651
- logger.error(`Iteration ${iteration} error`, { error });
652
- hookCtx.error = error instanceof Error ? error : new Error(String(error));
653
- if (error instanceof Error && error instanceof ContextError && error.llmOutput) {
654
- const llmOutput = error.llmOutput;
655
548
  if (llmOutput.toolCalls?.length) {
656
549
  const assistantParts = [];
657
550
  if (llmOutput.content) {
@@ -668,152 +561,277 @@ class AgentComponent extends BaseComponent {
668
561
  });
669
562
  }
670
563
  for (const tc of llmOutput.toolCalls) {
564
+ let argsStr = "";
565
+ let argsObj = {};
566
+ if (tc.function?.arguments) {
567
+ if (typeof tc.function.arguments === "string") {
568
+ argsStr = tc.function.arguments;
569
+ try {
570
+ argsObj = JSON.parse(argsStr);
571
+ } catch {
572
+ argsObj = { _raw: argsStr };
573
+ }
574
+ } else {
575
+ argsObj = tc.function.arguments;
576
+ argsStr = JSON.stringify(argsObj);
577
+ }
578
+ } else if (tc.arguments) {
579
+ if (typeof tc.arguments === "string") {
580
+ argsStr = tc.arguments;
581
+ try {
582
+ argsObj = JSON.parse(argsStr);
583
+ } catch {
584
+ argsObj = { _raw: argsStr };
585
+ }
586
+ } else {
587
+ argsObj = tc.arguments;
588
+ argsStr = JSON.stringify(argsObj);
589
+ }
590
+ }
671
591
  assistantParts.push({
672
592
  type: "tool-call",
673
593
  toolCallId: tc.id,
674
594
  toolName: tc.function?.name || tc.name || "unknown",
675
- input: typeof tc.function?.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.arguments || {}
595
+ input: argsObj,
596
+ toolCall: {
597
+ name: tc.function?.name || tc.name || "unknown",
598
+ arguments: argsStr
599
+ }
676
600
  });
677
601
  }
602
+ const assistantContent = llmOutput.content?.substring(0, 80) || "(no text)";
603
+ const toolCallNames = llmOutput.toolCalls?.map((tc) => tc.function?.name || tc.name).join(", ") || "none";
604
+ logger.debug(`[ReAct] Iteration ${iteration} Adding assistant message: text="${assistantContent}" toolCalls=[${toolCallNames}]`);
678
605
  this.pushMessage(hookCtx, {
679
606
  role: "assistant",
680
607
  content: assistantParts
681
608
  });
682
- } else if (llmOutput.content) {
683
- const assistantParts = [];
684
- if (llmOutput.content) {
685
- assistantParts.push({
686
- type: "text",
687
- text: llmOutput.content
688
- });
689
- }
690
- if (llmOutput.reasoning) {
691
- assistantParts.push({
692
- type: "reasoning",
693
- text: llmOutput.reasoning,
694
- reasoningType: "core"
695
- });
696
- }
697
- this.pushMessage(hookCtx, {
698
- role: "assistant",
699
- content: assistantParts.length > 0 ? assistantParts : llmOutput.content
700
- });
701
- }
702
- }
703
- await this.executePluginHooks(agent, "agent:on.error", hookCtx);
704
- if (!hookCtx._stopped) {
705
- hookCtx._stopped = true;
706
- if (error instanceof AskUserError) {
707
- hookCtx._stopReason = "ask-user";
708
- if (hookCtx.currentToolCall) {
609
+ const allToolCalls = llmOutput.toolCalls;
610
+ let processedCount = 0;
611
+ for (const toolCall of allToolCalls) {
612
+ if (this.aborted.get(runId) || effectiveContext.abort?.aborted) {
613
+ hookCtx._stopped = true;
614
+ hookCtx._stopReason = "aborted";
615
+ this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted");
616
+ break;
617
+ }
618
+ const func = toolCall.function;
619
+ const tcName = func?.name || toolCall.name || "unknown";
620
+ const tcArgs = func?.arguments ? typeof func.arguments === "string" ? JSON.parse(func.arguments) : func.arguments : toolCall.arguments;
621
+ hookCtx.currentToolCall = {
622
+ id: toolCall.id,
623
+ name: tcName,
624
+ arguments: tcArgs
625
+ };
626
+ const doomKey = `${tcName}:${JSON.stringify(tcArgs)}`;
627
+ const agentCache = this.doomLoopCaches.get(runId) || new Map;
628
+ const doomCount = agentCache.get(doomKey) || 0;
629
+ if (doomCount >= agent.config.doomLoopThreshold) {
630
+ hookCtx.error = new Error(`Doom loop detected: ${tcName}`);
631
+ await this.executePluginHooks(agent, "on.error", hookCtx);
632
+ result.error = hookCtx.error.message;
633
+ this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted: Doom loop detected");
634
+ break;
635
+ }
636
+ agentCache.set(doomKey, doomCount + 1);
637
+ this.doomLoopCaches.set(runId, agentCache);
638
+ await this.executePluginHooks(agent, "agent:before.tool", hookCtx);
639
+ if (hookCtx._stopped) {
640
+ this.addRemainingToolResults(hookCtx, allToolCalls, processedCount, "Execution aborted by plugin hook");
641
+ break;
642
+ }
643
+ const toolResult = await this.executeTool(hookCtx);
644
+ hookCtx.toolResult = toolResult;
645
+ await this.executePluginHooks(agent, "agent:after.tool", hookCtx);
646
+ if (hookCtx._stopped) {
647
+ this.addRemainingToolResults(hookCtx, allToolCalls, processedCount + 1, "Execution aborted by plugin hook");
648
+ break;
649
+ }
650
+ const toolOutput = toolResult.success ? toolResult.result.output || "" : toolResult.result.error || "Unknown error";
651
+ const toolOutputPreview = typeof toolOutput === "string" ? toolOutput.substring(0, 50) : JSON.stringify(toolOutput).substring(0, 50);
652
+ logger.debug(`[ReAct] Iteration ${iteration} Adding tool message: tool=${toolResult.name} output="${toolOutputPreview}..."`);
709
653
  this.pushMessage(hookCtx, {
710
654
  role: "tool",
711
655
  content: [{
712
656
  type: "tool-result",
713
657
  toolCallId: hookCtx.currentToolCall.id,
714
- toolName: "ask_user",
715
- output: JSON.stringify({
716
- error: "AskUserError",
717
- query: error.query,
718
- message: error.message
719
- })
658
+ toolName: toolResult.name,
659
+ output: toolOutput
720
660
  }]
721
661
  });
662
+ result.toolCalls.push(hookCtx.currentToolCall);
663
+ processedCount++;
722
664
  }
723
- const errorInfo = {
724
- query: error.query,
725
- sessionId: error.sessionId,
726
- nodeId: error.nodeId,
727
- nodeType: error.nodeType
728
- };
729
- result.error = `__ASK_USER_ERROR__:${JSON.stringify(errorInfo)}`;
730
- } else {
731
- result.error = hookCtx.error.message;
732
- if (error?.name === "AbortError") {
733
- hookCtx._stopReason = hookCtx._stopReason || "aborted";
665
+ await this.executePluginHooks(agent, "agent:on.iteration", hookCtx);
666
+ }
667
+ } catch (error) {
668
+ logger.error(`Iteration ${iteration} error`, { error });
669
+ hookCtx.error = error instanceof Error ? error : new Error(String(error));
670
+ if (error instanceof Error && error instanceof ContextError && error.llmOutput) {
671
+ const llmOutput = error.llmOutput;
672
+ if (llmOutput.toolCalls?.length) {
673
+ const assistantParts = [];
674
+ if (llmOutput.content) {
675
+ assistantParts.push({
676
+ type: "text",
677
+ text: llmOutput.content
678
+ });
679
+ }
680
+ if (llmOutput.reasoning) {
681
+ assistantParts.push({
682
+ type: "reasoning",
683
+ text: llmOutput.reasoning,
684
+ reasoningType: "core"
685
+ });
686
+ }
687
+ for (const tc of llmOutput.toolCalls) {
688
+ assistantParts.push({
689
+ type: "tool-call",
690
+ toolCallId: tc.id,
691
+ toolName: tc.function?.name || tc.name || "unknown",
692
+ input: typeof tc.function?.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.arguments || {}
693
+ });
694
+ }
695
+ this.pushMessage(hookCtx, {
696
+ role: "assistant",
697
+ content: assistantParts
698
+ });
699
+ } else if (llmOutput.content) {
700
+ const assistantParts = [];
701
+ if (llmOutput.content) {
702
+ assistantParts.push({
703
+ type: "text",
704
+ text: llmOutput.content
705
+ });
706
+ }
707
+ if (llmOutput.reasoning) {
708
+ assistantParts.push({
709
+ type: "reasoning",
710
+ text: llmOutput.reasoning,
711
+ reasoningType: "core"
712
+ });
713
+ }
714
+ this.pushMessage(hookCtx, {
715
+ role: "assistant",
716
+ content: assistantParts.length > 0 ? assistantParts : llmOutput.content
717
+ });
718
+ }
719
+ }
720
+ await this.executePluginHooks(agent, "agent:on.error", hookCtx);
721
+ if (!hookCtx._stopped) {
722
+ hookCtx._stopped = true;
723
+ if (error instanceof AskUserError) {
724
+ hookCtx._stopReason = "ask-user";
725
+ if (hookCtx.currentToolCall) {
726
+ this.pushMessage(hookCtx, {
727
+ role: "tool",
728
+ content: [{
729
+ type: "tool-result",
730
+ toolCallId: hookCtx.currentToolCall.id,
731
+ toolName: "ask_user",
732
+ output: JSON.stringify({
733
+ error: "AskUserError",
734
+ query: error.query,
735
+ message: error.message
736
+ })
737
+ }]
738
+ });
739
+ }
740
+ const errorInfo = {
741
+ query: error.query,
742
+ sessionId: error.sessionId,
743
+ nodeId: error.nodeId,
744
+ nodeType: error.nodeType
745
+ };
746
+ result.error = `__ASK_USER_ERROR__:${JSON.stringify(errorInfo)}`;
734
747
  } else {
735
- hookCtx._stopReason = "error";
748
+ result.error = hookCtx.error.message;
749
+ if (error?.name === "AbortError") {
750
+ hookCtx._stopReason = hookCtx._stopReason || "aborted";
751
+ } else {
752
+ hookCtx._stopReason = "error";
753
+ }
754
+ if (hookCtx.currentToolCall) {
755
+ this.pushMessage(hookCtx, {
756
+ role: "tool",
757
+ content: [{
758
+ type: "tool-result",
759
+ toolCallId: hookCtx.currentToolCall.id,
760
+ toolName: hookCtx.currentToolCall.name,
761
+ output: JSON.stringify({ error: hookCtx.error.message })
762
+ }]
763
+ });
764
+ }
736
765
  }
766
+ } else {
767
+ result.error = hookCtx.error.message;
737
768
  if (hookCtx.currentToolCall) {
769
+ const errorMsg = hookCtx.error?.message || "Execution interrupted";
738
770
  this.pushMessage(hookCtx, {
739
771
  role: "tool",
740
772
  content: [{
741
773
  type: "tool-result",
742
774
  toolCallId: hookCtx.currentToolCall.id,
743
775
  toolName: hookCtx.currentToolCall.name,
744
- output: JSON.stringify({ error: hookCtx.error.message })
776
+ output: JSON.stringify({ error: errorMsg })
745
777
  }]
746
778
  });
747
779
  }
748
780
  }
749
- } else {
750
- result.error = hookCtx.error.message;
751
- if (hookCtx.currentToolCall) {
752
- const errorMsg = hookCtx.error?.message || "Execution interrupted";
753
- this.pushMessage(hookCtx, {
754
- role: "tool",
755
- content: [{
756
- type: "tool-result",
757
- toolCallId: hookCtx.currentToolCall.id,
758
- toolName: hookCtx.currentToolCall.name,
759
- output: JSON.stringify({ error: errorMsg })
760
- }]
761
- });
762
- }
781
+ break;
763
782
  }
764
- break;
765
783
  }
766
- }
767
- result.finalText = finalText;
768
- if (iteration >= agent.config.maxIterations && !result.finalText) {
769
- result.finalText = "Maximum iterations reached.";
770
- }
771
- const reactContext = {
772
- messages: hookCtx.messages,
773
- sessionId: effectiveContext.sessionId,
774
- summary: result.finalText
775
- };
776
- await this.executePluginHooks(agent, "agent:after.react", {
777
- ...hookCtx,
778
- ...reactContext
779
- });
780
- await this.executePluginHooks(agent, "agent:after.complete", hookCtx);
781
- if (this.aborted.get(runId) === true || hookCtx._stopped) {
782
- agent.status = "stopped";
783
- } else {
784
- agent.status = "idle";
785
- }
786
- this.aborted.delete(runId);
787
- this.abortControllers.delete(runId);
788
- if (result.error) {
789
- this.pushEnvEvent({
790
- type: "agent.error",
791
- payload: {
792
- error: result.error,
793
- iterations: result.iterations,
794
- stopReason: result.stopReason
795
- }
784
+ result.finalText = finalText;
785
+ if (iteration >= agent.config.maxIterations && !result.finalText) {
786
+ result.finalText = "Maximum iterations reached.";
787
+ }
788
+ const reactContext = {
789
+ messages: hookCtx.messages,
790
+ sessionId: effectiveContext.sessionId,
791
+ summary: result.finalText
792
+ };
793
+ await this.executePluginHooks(agent, "agent:after.react", {
794
+ ...hookCtx,
795
+ ...reactContext
796
796
  });
797
- } else {
798
- this.pushEnvEvent({
799
- type: "agent.completed",
800
- payload: {
801
- finalText: result.finalText,
802
- iterations: result.iterations,
803
- stopReason: result.stopReason
804
- }
797
+ await this.executePluginHooks(agent, "agent:after.complete", hookCtx);
798
+ if (this.aborted.get(runId) === true || hookCtx._stopped) {
799
+ agent.status = "stopped";
800
+ } else {
801
+ agent.status = "idle";
802
+ }
803
+ this.aborted.delete(runId);
804
+ this.abortControllers.delete(runId);
805
+ if (result.error) {
806
+ this.pushEnvEvent({
807
+ type: "agent.error",
808
+ payload: {
809
+ error: result.error,
810
+ iterations: result.iterations,
811
+ stopReason: result.stopReason
812
+ }
813
+ });
814
+ } else {
815
+ this.pushEnvEvent({
816
+ type: "agent.completed",
817
+ payload: {
818
+ finalText: result.finalText,
819
+ iterations: result.iterations,
820
+ stopReason: result.stopReason
821
+ }
822
+ });
823
+ }
824
+ let newMessages = hookCtx.messages.slice(historyMessageCount);
825
+ logger.info(`Agent run completed: ${agentName}`, {
826
+ iterations: result.iterations,
827
+ hasError: !!result.error,
828
+ hookCtxMessages: hookCtx.messages.length,
829
+ historyMessageCount,
830
+ sessionId: effectiveContext.sessionId
805
831
  });
806
- }
807
- let newMessages = hookCtx.messages.slice(historyMessageCount);
808
- logger.info(`Agent run completed: ${agentName}`, {
809
- iterations: result.iterations,
810
- hasError: !!result.error,
811
- hookCtxMessages: hookCtx.messages.length,
812
- historyMessageCount,
813
- sessionId: effectiveContext.sessionId
832
+ await this.recordSessionMessages(effectiveContext.sessionId, newMessages);
833
+ return this.finalizeResult(result, hookCtx);
814
834
  });
815
- await this.recordSessionMessages(effectiveContext.sessionId, newMessages);
816
- return this.finalizeResult(result, hookCtx);
817
835
  }
818
836
  abort(agentName) {
819
837
  for (const key of this.aborted.keys()) {