@ai-setting/roy-agent-core 1.6.21 → 1.6.23

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 (94) hide show
  1. package/dist/config/index.js +9 -9
  2. package/dist/env/agent/index.js +17 -15
  3. package/dist/env/commands/index.js +9 -9
  4. package/dist/env/context/index.js +5 -5
  5. package/dist/env/debug/index.js +9 -9
  6. package/dist/env/event-source/index.js +14 -13
  7. package/dist/env/hook/index.js +7 -7
  8. package/dist/env/index.js +41 -40
  9. package/dist/env/llm/index.js +11 -11
  10. package/dist/env/log-trace/index.js +9 -9
  11. package/dist/env/mcp/index.js +10 -10
  12. package/dist/env/mcp/tool/index.js +3 -3
  13. package/dist/env/memory/index.js +10 -10
  14. package/dist/env/memory/plugin/index.js +3 -3
  15. package/dist/env/plugin/index.js +9 -9
  16. package/dist/env/prompt/index.js +9 -9
  17. package/dist/env/session/index.js +12 -12
  18. package/dist/env/session/storage/index.js +5 -5
  19. package/dist/env/skill/index.js +9 -9
  20. package/dist/env/task/delegate/index.js +10 -10
  21. package/dist/env/task/index.js +15 -15
  22. package/dist/env/task/plugins/index.js +9 -8
  23. package/dist/env/task/storage/index.js +4 -4
  24. package/dist/env/task/tools/index.js +5 -5
  25. package/dist/env/tool/built-in/index.js +5 -5
  26. package/dist/env/tool/index.js +12 -12
  27. package/dist/env/workflow/engine/index.js +11 -11
  28. package/dist/env/workflow/index.js +22 -22
  29. package/dist/env/workflow/nodes/index.js +4 -4
  30. package/dist/env/workflow/service/index.js +4 -4
  31. package/dist/env/workflow/storage/index.js +5 -5
  32. package/dist/env/workflow/tools/index.js +16 -16
  33. package/dist/env/workflow/utils/index.js +6 -6
  34. package/dist/index.js +52 -51
  35. package/dist/shared/@ai-setting/{roy-agent-core-7kw06e4b.js → roy-agent-core-0qjw25e8.js} +1 -1
  36. package/dist/shared/@ai-setting/{roy-agent-core-bq1gskrf.js → roy-agent-core-0v74marc.js} +1 -1
  37. package/dist/shared/@ai-setting/{roy-agent-core-e0kaxcy1.js → roy-agent-core-12gac5zn.js} +1 -1
  38. package/dist/shared/@ai-setting/{roy-agent-core-f1cjs6c4.js → roy-agent-core-16dqrewm.js} +6 -6
  39. package/dist/shared/@ai-setting/{roy-agent-core-7r72622v.js → roy-agent-core-1k9j90s7.js} +1 -1
  40. package/dist/shared/@ai-setting/{roy-agent-core-m00kamqp.js → roy-agent-core-1khp1m0r.js} +8 -1
  41. package/dist/shared/@ai-setting/{roy-agent-core-zeztnvvb.js → roy-agent-core-3c1b7xh5.js} +221 -79
  42. package/dist/shared/@ai-setting/{roy-agent-core-77wfej1h.js → roy-agent-core-3e0w0ekw.js} +2 -2
  43. package/dist/shared/@ai-setting/{roy-agent-core-zdzkzx5g.js → roy-agent-core-3ep1dxf1.js} +2 -2
  44. package/dist/shared/@ai-setting/{roy-agent-core-gc75v3px.js → roy-agent-core-3x3k7gfs.js} +5 -5
  45. package/dist/shared/@ai-setting/roy-agent-core-4k8tv5q5.js +11 -0
  46. package/dist/shared/@ai-setting/{roy-agent-core-zvwdfm79.js → roy-agent-core-50jdqb7r.js} +95 -32
  47. package/dist/shared/@ai-setting/{roy-agent-core-02aw62bv.js → roy-agent-core-5ts23mx0.js} +1 -1
  48. package/dist/shared/@ai-setting/{roy-agent-core-atpchjdz.js → roy-agent-core-6m2gh57e.js} +1 -1
  49. package/dist/shared/@ai-setting/{roy-agent-core-ehpnd2be.js → roy-agent-core-6re7eg4w.js} +2 -2
  50. package/dist/shared/@ai-setting/{roy-agent-core-ett06sn8.js → roy-agent-core-7cxdkcrz.js} +4 -4
  51. package/dist/shared/@ai-setting/{roy-agent-core-416rpxkp.js → roy-agent-core-7wv7gh6t.js} +5 -5
  52. package/dist/shared/@ai-setting/{roy-agent-core-bb20se79.js → roy-agent-core-8s7qyr5y.js} +8 -8
  53. package/dist/shared/@ai-setting/{roy-agent-core-fxembepv.js → roy-agent-core-90wp1rgb.js} +5 -5
  54. package/dist/shared/@ai-setting/{roy-agent-core-xjj88tpn.js → roy-agent-core-afb03wwp.js} +2 -2
  55. package/dist/shared/@ai-setting/{roy-agent-core-5pzegp1x.js → roy-agent-core-b64s2vk9.js} +2 -2
  56. package/dist/shared/@ai-setting/{roy-agent-core-ataagh3a.js → roy-agent-core-br7dmedr.js} +1 -1
  57. package/dist/shared/@ai-setting/{roy-agent-core-8n0e62y4.js → roy-agent-core-c1stgqnw.js} +2 -2
  58. package/dist/shared/@ai-setting/{roy-agent-core-gmnex23m.js → roy-agent-core-cjraf54z.js} +3 -3
  59. package/dist/shared/@ai-setting/{roy-agent-core-j8t1tyhr.js → roy-agent-core-dbwvfe0m.js} +5 -5
  60. package/dist/shared/@ai-setting/{roy-agent-core-mdp8y7ky.js → roy-agent-core-dxfd6p1c.js} +1 -1
  61. package/dist/shared/@ai-setting/{roy-agent-core-wsqnf2za.js → roy-agent-core-ef486rdm.js} +7 -7
  62. package/dist/shared/@ai-setting/{roy-agent-core-kr58bgz0.js → roy-agent-core-f2nync7q.js} +4 -4
  63. package/dist/shared/@ai-setting/{roy-agent-core-dh9rajdh.js → roy-agent-core-g7nmwg63.js} +1 -1
  64. package/dist/shared/@ai-setting/{roy-agent-core-96mj6gvc.js → roy-agent-core-gb7pm9c0.js} +2 -2
  65. package/dist/shared/@ai-setting/{roy-agent-core-grajzyhd.js → roy-agent-core-gns3wa97.js} +14 -18
  66. package/dist/shared/@ai-setting/{roy-agent-core-ez91vxas.js → roy-agent-core-h1cb2jzh.js} +1 -1
  67. package/dist/shared/@ai-setting/{roy-agent-core-eskgj8nc.js → roy-agent-core-h28gcd77.js} +6 -6
  68. package/dist/shared/@ai-setting/{roy-agent-core-sqt96sam.js → roy-agent-core-h7ak839w.js} +1 -1
  69. package/dist/shared/@ai-setting/{roy-agent-core-c7e3htaq.js → roy-agent-core-hks28tys.js} +2 -2
  70. package/dist/shared/@ai-setting/{roy-agent-core-vc7p80sd.js → roy-agent-core-j29yg06n.js} +2 -2
  71. package/dist/shared/@ai-setting/{roy-agent-core-r15sn7ve.js → roy-agent-core-j9ybhwnq.js} +2 -2
  72. package/dist/shared/@ai-setting/{roy-agent-core-nna4s0qs.js → roy-agent-core-kaq037np.js} +1 -1
  73. package/dist/shared/@ai-setting/{roy-agent-core-e9jf4w3z.js → roy-agent-core-kv7frw13.js} +4 -4
  74. package/dist/shared/@ai-setting/{roy-agent-core-44g3synv.js → roy-agent-core-mvs5sen6.js} +1 -1
  75. package/dist/shared/@ai-setting/{roy-agent-core-akb8mb9v.js → roy-agent-core-pde8hkq4.js} +2 -2
  76. package/dist/shared/@ai-setting/{roy-agent-core-p4z6nxgz.js → roy-agent-core-pdnp5kj0.js} +4 -4
  77. package/dist/shared/@ai-setting/{roy-agent-core-1qjgwjjs.js → roy-agent-core-pz2n121t.js} +4 -4
  78. package/dist/shared/@ai-setting/{roy-agent-core-wr3pk3h3.js → roy-agent-core-qe3m3hec.js} +1 -1
  79. package/dist/shared/@ai-setting/{roy-agent-core-v20nxrs1.js → roy-agent-core-qpt5fa8h.js} +2 -2
  80. package/dist/shared/@ai-setting/{roy-agent-core-keb51jag.js → roy-agent-core-rs5tp44j.js} +4 -4
  81. package/dist/shared/@ai-setting/{roy-agent-core-2b0mw2h3.js → roy-agent-core-s07nere5.js} +3 -3
  82. package/dist/shared/@ai-setting/{roy-agent-core-ajp566yv.js → roy-agent-core-sfwt66pv.js} +2 -2
  83. package/dist/shared/@ai-setting/roy-agent-core-t3yqzgse.js +71 -0
  84. package/dist/shared/@ai-setting/{roy-agent-core-xzc53mnk.js → roy-agent-core-t9h4np6m.js} +4 -2
  85. package/dist/shared/@ai-setting/{roy-agent-core-1mrc9a1r.js → roy-agent-core-w8rv08d3.js} +1 -1
  86. package/dist/shared/@ai-setting/{roy-agent-core-b9q2jfx4.js → roy-agent-core-watkmj7d.js} +6 -6
  87. package/dist/shared/@ai-setting/{roy-agent-core-bwqjwa0d.js → roy-agent-core-wr1pgw0x.js} +8 -8
  88. package/dist/shared/@ai-setting/{roy-agent-core-fntxq0gf.js → roy-agent-core-x0yztmm6.js} +2 -2
  89. package/dist/shared/@ai-setting/{roy-agent-core-dtkbj8fk.js → roy-agent-core-xrr7t0qc.js} +2 -2
  90. package/dist/shared/@ai-setting/{roy-agent-core-q06h6qf8.js → roy-agent-core-xwnpygva.js} +14 -14
  91. package/dist/shared/@ai-setting/{roy-agent-core-pr4jekyy.js → roy-agent-core-z2w7wtqd.js} +5 -5
  92. package/dist/utils/temp-file-manager/index.js +3 -3
  93. package/package.json +1 -1
  94. package/dist/shared/@ai-setting/roy-agent-core-w6kj6nmj.js +0 -11
@@ -1,51 +1,57 @@
1
1
  import {
2
2
  withTimeout
3
- } from "./roy-agent-core-8n0e62y4.js";
3
+ } from "./roy-agent-core-c1stgqnw.js";
4
4
  import {
5
5
  truncateOutputInline
6
- } from "./roy-agent-core-eskgj8nc.js";
6
+ } from "./roy-agent-core-h28gcd77.js";
7
+ import {
8
+ enqueueToAddFakeUserMessage
9
+ } from "./roy-agent-core-t3yqzgse.js";
7
10
  import {
8
11
  AskUserError,
9
12
  init_workflow_hil
10
13
  } from "./roy-agent-core-e25xkv53.js";
11
14
  import {
12
15
  AgentRegistry
13
- } from "./roy-agent-core-fntxq0gf.js";
16
+ } from "./roy-agent-core-x0yztmm6.js";
17
+ import {
18
+ getCurrentBgTaskId
19
+ } from "./roy-agent-core-c1v263jn.js";
14
20
  import {
15
21
  ContextError
16
22
  } from "./roy-agent-core-ctdhjv68.js";
17
23
  import {
18
24
  SessionMessageConverter
19
- } from "./roy-agent-core-7r72622v.js";
25
+ } from "./roy-agent-core-1k9j90s7.js";
20
26
  import {
21
27
  safeParseToolArgs
22
- } from "./roy-agent-core-e0kaxcy1.js";
28
+ } from "./roy-agent-core-12gac5zn.js";
23
29
  import {
24
30
  envKeyToConfigKey
25
31
  } from "./roy-agent-core-7hh0brvs.js";
26
32
  import {
27
33
  BaseComponent
28
- } from "./roy-agent-core-akb8mb9v.js";
34
+ } from "./roy-agent-core-pde8hkq4.js";
29
35
  import {
30
36
  globalHookManager,
31
37
  init_global_hook_manager
32
- } from "./roy-agent-core-vc7p80sd.js";
38
+ } from "./roy-agent-core-j29yg06n.js";
33
39
  import {
34
40
  init_context
35
- } from "./roy-agent-core-sqt96sam.js";
41
+ } from "./roy-agent-core-h7ak839w.js";
36
42
  import {
37
43
  getCurrentTaskId,
38
44
  getEnvContext,
39
45
  runWithEnvContextAsync
40
- } from "./roy-agent-core-dtkbj8fk.js";
46
+ } from "./roy-agent-core-xrr7t0qc.js";
41
47
  import {
42
48
  TracedAs,
43
49
  init_decorator
44
- } from "./roy-agent-core-96mj6gvc.js";
50
+ } from "./roy-agent-core-gb7pm9c0.js";
45
51
  import {
46
52
  createLogger,
47
53
  init_logger
48
- } from "./roy-agent-core-nna4s0qs.js";
54
+ } from "./roy-agent-core-kaq037np.js";
49
55
  import {
50
56
  __legacyDecorateClassTS,
51
57
  __require
@@ -55,6 +61,102 @@ import {
55
61
  init_logger();
56
62
  import { z } from "zod";
57
63
 
64
+ // src/env/task/plugins/max-iteration-reminder-plugin.ts
65
+ init_logger();
66
+ init_decorator();
67
+ var logger = createLogger("MaxIterationReminderPlugin");
68
+ var DEFAULT_REMINDER_MESSAGE = `⚠️ **系统提醒**: 你已经达到最大 ReAct 迭代次数({maxIterations}次)。
69
+
70
+ **请不要再调用任何工具**,利用目前已有的信息直接给用户一个简洁明了的总结,包括:
71
+ 1. 目前的进展
72
+ 2. 已完成的工作
73
+ 3. 遇到的问题(如有)
74
+ 4. 下一步建议(如有)
75
+
76
+ 总结后立即结束,不要继续工具调用。`;
77
+
78
+ class MaxIterationReminderPlugin {
79
+ name = "MaxIterationReminderPlugin";
80
+ version = "3.0.0";
81
+ description = "在 iteration === maxIterations - 1 时通过共享 meta-protocol helper 注入 fake user 消息;AgentComponent 现有 for-loop 后 flush;适用于所有 agent。maxIterations<=1 防御性跳过。";
82
+ priority = 50;
83
+ messageTemplate;
84
+ injectedTraceIds = new Set;
85
+ constructor(config) {
86
+ this.messageTemplate = config?.messageTemplate ?? DEFAULT_REMINDER_MESSAGE;
87
+ }
88
+ async execute(ctx) {
89
+ const { iteration, maxIterations } = ctx;
90
+ const traceId = ctx.context?.traceId ?? ctx.context?.sessionId ?? "unknown";
91
+ const kind = "max-iter";
92
+ const makeResult = (willSet, reason) => {
93
+ const decision = { willSet, iteration, maxIterations, kind, reason, traceId };
94
+ return { continue: true, __maxIterDecision: decision };
95
+ };
96
+ if (typeof iteration !== "number" || typeof maxIterations !== "number") {
97
+ logger.debug(`[MaxIterReminder] skip — non-numeric iter=${iteration} or maxIter=${maxIterations}`);
98
+ return makeResult(false, "non-numeric-iter-or-maxIter");
99
+ }
100
+ if (maxIterations <= 1) {
101
+ logger.debug(`[MaxIterReminder] skip — maxIterations=${maxIterations} <= 1 (one-shot agent)`);
102
+ return makeResult(false, "max-iterations-le-1");
103
+ }
104
+ if (iteration !== maxIterations - 1) {
105
+ return makeResult(false, "iter-not-equal-max-iter-minus-1");
106
+ }
107
+ if (!ctx.toolResult) {
108
+ logger.warn(`[MaxIterReminder] skip — toolResult missing at iter=${iteration}`);
109
+ return makeResult(false, "no-tool-result");
110
+ }
111
+ if (this.injectedTraceIds.has(traceId)) {
112
+ logger.debug(`[MaxIterReminder] skip — traceId=${traceId.slice(0, 20)} already processed`);
113
+ return makeResult(false, "trace-id-already-processed");
114
+ }
115
+ const reminderContent = this.messageTemplate.replace(/\{maxIterations\}/g, String(maxIterations));
116
+ enqueueToAddFakeUserMessage(ctx.toolResult, {
117
+ role: "user",
118
+ content: reminderContent
119
+ }, kind);
120
+ this.injectedTraceIds.add(traceId);
121
+ logger.info(`[MaxIterReminder] max-iter reminder meta-protocol set (session=${(ctx.context?.sessionId ?? "unknown").slice(0, 12)}..., iteration=${iteration}, maxIterations=${maxIterations})`);
122
+ return makeResult(true, "fired");
123
+ }
124
+ }
125
+ __legacyDecorateClassTS([
126
+ TracedAs("plugin.max-iter-reminder.evaluate", {
127
+ recordParams: false,
128
+ recordResult: false,
129
+ log: true,
130
+ resultFilter: (result) => {
131
+ const d = result?.__maxIterDecision;
132
+ if (!d)
133
+ return {};
134
+ return {
135
+ "max-iter.iteration": d.iteration,
136
+ "max-iter.max_iterations": d.maxIterations,
137
+ "max-iter.will_set": d.willSet,
138
+ "max-iter.kind": d.kind,
139
+ "max-iter.reason": d.reason,
140
+ "max-iter.trace_id": d.traceId
141
+ };
142
+ }
143
+ })
144
+ ], MaxIterationReminderPlugin.prototype, "execute", null);
145
+ function createMaxIterationReminderPlugin(config) {
146
+ const inst = new MaxIterationReminderPlugin(config);
147
+ return {
148
+ name: inst.name,
149
+ version: inst.version,
150
+ description: inst.description,
151
+ hooks: [
152
+ { point: "agent:after.tool", priority: inst.priority }
153
+ ],
154
+ execute: async (ctx) => {
155
+ return inst.execute(ctx);
156
+ }
157
+ };
158
+ }
159
+
58
160
  // src/env/agent/agent-config-registration.ts
59
161
  var AGENT_DEFAULTS = {
60
162
  "agent.defaultAgent.maxIterations": 200,
@@ -128,7 +230,7 @@ function composeToolOutputForLLM(toolName, result) {
128
230
  }
129
231
  return `${tag} tool=${toolName} status=${status} (no error message and no runId — tool did not surface a diagnostic)`;
130
232
  }
131
- var logger = createLogger("agent:component");
233
+ var logger2 = createLogger("agent:component");
132
234
  function toLLMMessage(msg) {
133
235
  let content;
134
236
  let toolCallId;
@@ -350,7 +452,7 @@ class AgentComponent extends BaseComponent {
350
452
  allowedTools: parseToolList(constructorDefaultAgent?.allowedTools ?? configComponent.get("agent.defaultAgent.allowedTools")),
351
453
  deniedTools: parseToolList(constructorDefaultAgent?.deniedTools ?? configComponent.get("agent.defaultAgent.deniedTools"))
352
454
  };
353
- logger.info(`[registerConfig] Synced config from ConfigComponent: maxIterations=${this.config.defaultAgent.maxIterations}`);
455
+ logger2.info(`[registerConfig] Synced config from ConfigComponent: maxIterations=${this.config.defaultAgent.maxIterations}`);
354
456
  this.registerConfigWatcher(configComponent);
355
457
  }
356
458
  flattenConfig(obj, prefix = "agent") {
@@ -374,7 +476,7 @@ class AgentComponent extends BaseComponent {
374
476
  });
375
477
  }
376
478
  onConfigChange(event) {
377
- logger.info(`Agent config changed: ${event.key}`, {
479
+ logger2.info(`Agent config changed: ${event.key}`, {
378
480
  oldValue: event.oldValue,
379
481
  newValue: event.newValue
380
482
  });
@@ -386,23 +488,23 @@ class AgentComponent extends BaseComponent {
386
488
  resolvePromptComponent: () => this.env?.getComponent?.("prompt") ?? null
387
489
  });
388
490
  const loadedCount = await this.registry.load();
389
- logger.info(`[AgentComponent] Loaded ${loadedCount} agents from config directory`);
491
+ logger2.info(`[AgentComponent] Loaded ${loadedCount} agents from config directory`);
390
492
  this.registry.registerWorkflowRunner();
391
- logger.info("[AgentComponent] Registered built-in workflow-runner");
493
+ logger2.info("[AgentComponent] Registered built-in workflow-runner");
392
494
  this.registry.registerTaskOrganizer();
393
- logger.info("[AgentComponent] Registered built-in task-organizer");
495
+ logger2.info("[AgentComponent] Registered built-in task-organizer");
394
496
  this.registry.registerJsonExtractAgent();
395
- logger.info("[AgentComponent] Registered built-in json-extract agent");
497
+ logger2.info("[AgentComponent] Registered built-in json-extract agent");
396
498
  this.registry.registerWorkflowCreator();
397
- logger.info("[AgentComponent] Registered built-in workflow-creator");
499
+ logger2.info("[AgentComponent] Registered built-in workflow-creator");
398
500
  this.registry.registerWorkflowExtractAgent();
399
- logger.info("[AgentComponent] Registered built-in workflow-extract agent");
501
+ logger2.info("[AgentComponent] Registered built-in workflow-extract agent");
400
502
  this.registry.registerCompactAgent();
401
- logger.info("[AgentComponent] Registered built-in compact agent");
503
+ logger2.info("[AgentComponent] Registered built-in compact agent");
402
504
  this.registry.registerCompactHintAgent();
403
- logger.info("[AgentComponent] Registered built-in compact-hint agent");
505
+ logger2.info("[AgentComponent] Registered built-in compact-hint agent");
404
506
  this.registry.registerRoyAgent();
405
- logger.info("[AgentComponent] Registered built-in roy agent");
507
+ logger2.info("[AgentComponent] Registered built-in roy agent");
406
508
  for (const agentDef of this.registry.list()) {
407
509
  if (!this.agents.has(agentDef.name)) {
408
510
  const systemPrompt = await this.registry.getSystemPrompt(agentDef.name);
@@ -415,11 +517,11 @@ class AgentComponent extends BaseComponent {
415
517
  model: agentDef.model,
416
518
  maxIterations: agentDef.maxIterations
417
519
  });
418
- logger.debug(`[AgentComponent] Registered agent from config: ${agentDef.name}`);
520
+ logger2.debug(`[AgentComponent] Registered agent from config: ${agentDef.name}`);
419
521
  }
420
522
  }
421
523
  } catch (error) {
422
- logger.warn(`[AgentComponent] Failed to initialize AgentRegistry: ${error}`);
524
+ logger2.warn(`[AgentComponent] Failed to initialize AgentRegistry: ${error}`);
423
525
  }
424
526
  }
425
527
  async syncRegistryAgentsFromConfig() {
@@ -447,7 +549,7 @@ class AgentComponent extends BaseComponent {
447
549
  maxIterations: agentDef.maxIterations
448
550
  });
449
551
  }
450
- logger.debug(`[AgentComponent] Synced registry agent: ${agentDef.name}`);
552
+ logger2.debug(`[AgentComponent] Synced registry agent: ${agentDef.name}`);
451
553
  }
452
554
  }
453
555
  getRegistry() {
@@ -460,11 +562,11 @@ class AgentComponent extends BaseComponent {
460
562
  return this.registry?.list() ?? [];
461
563
  }
462
564
  async onStop() {
463
- logger.info("[AgentComponent] Stopping and cleaning up resources...");
565
+ logger2.info("[AgentComponent] Stopping and cleaning up resources...");
464
566
  for (const [name, agent] of this.agents) {
465
567
  if (agent.status === "running" || agent.status === "idle") {
466
568
  this.abort(name);
467
- logger.debug(`[AgentComponent] Aborted agent: ${name}`);
569
+ logger2.debug(`[AgentComponent] Aborted agent: ${name}`);
468
570
  }
469
571
  }
470
572
  this.abortControllers.clear();
@@ -475,7 +577,7 @@ class AgentComponent extends BaseComponent {
475
577
  }
476
578
  this.agents.clear();
477
579
  this.setStatus("stopped");
478
- logger.info("[AgentComponent] Cleanup completed");
580
+ logger2.info("[AgentComponent] Cleanup completed");
479
581
  }
480
582
  async refreshDependencies() {
481
583
  if (this.env) {
@@ -498,12 +600,12 @@ class AgentComponent extends BaseComponent {
498
600
  });
499
601
  return result.output?.content ?? "";
500
602
  });
501
- logger.debug("[refreshDependencies] understand_image LLM provider injected");
603
+ logger2.debug("[refreshDependencies] understand_image LLM provider injected");
502
604
  } catch (err) {
503
- logger.warn(`[refreshDependencies] failed to inject understand_image provider: ${err.message}`);
605
+ logger2.warn(`[refreshDependencies] failed to inject understand_image provider: ${err.message}`);
504
606
  }
505
607
  }
506
- logger.debug("[refreshDependencies] AgentComponent refreshed", {
608
+ logger2.debug("[refreshDependencies] AgentComponent refreshed", {
507
609
  hasLLM: !!this.llmComponent,
508
610
  hasTool: !!this.toolComponent
509
611
  });
@@ -517,17 +619,17 @@ class AgentComponent extends BaseComponent {
517
619
  return;
518
620
  }
519
621
  if (!this.registry) {
520
- logger.debug(`[resolveSystemPrompt] No registry available for ${agentName}`);
622
+ logger2.debug(`[resolveSystemPrompt] No registry available for ${agentName}`);
521
623
  return;
522
624
  }
523
625
  try {
524
626
  const resolvedPrompt = await this.registry.getSystemPrompt(agentName);
525
627
  if (resolvedPrompt) {
526
628
  agent.config.systemPrompt = resolvedPrompt;
527
- logger.debug(`[AgentComponent] Resolved systemPrompt for agent: ${agentName}`);
629
+ logger2.debug(`[AgentComponent] Resolved systemPrompt for agent: ${agentName}`);
528
630
  }
529
631
  } catch (error) {
530
- logger.warn(`[AgentComponent] Failed to resolve systemPrompt for agent ${agentName}: ${error}`);
632
+ logger2.warn(`[AgentComponent] Failed to resolve systemPrompt for agent ${agentName}: ${error}`);
531
633
  }
532
634
  }
533
635
  getAgent(agentName) {
@@ -575,13 +677,14 @@ class AgentComponent extends BaseComponent {
575
677
  plugins: new Map
576
678
  };
577
679
  this.agents.set(name, instance);
578
- logger.info(`Agent registered: ${name}`, { type: instance.config.type });
680
+ this.registerPlugin(name, createMaxIterationReminderPlugin());
681
+ logger2.info(`Agent registered: ${name}`, { type: instance.config.type });
579
682
  return instance;
580
683
  }
581
684
  unregisterAgent(name) {
582
685
  const deleted = this.agents.delete(name);
583
686
  if (deleted) {
584
- logger.info(`Agent unregistered: ${name}`);
687
+ logger2.info(`Agent unregistered: ${name}`);
585
688
  }
586
689
  return deleted;
587
690
  }
@@ -591,7 +694,7 @@ class AgentComponent extends BaseComponent {
591
694
  throw new Error(`Agent not found: ${agentName}`);
592
695
  }
593
696
  agent.plugins.set(plugin.name, plugin);
594
- logger.info(`Plugin registered: ${plugin.name} to ${agentName}`, {
697
+ logger2.info(`Plugin registered: ${plugin.name} to ${agentName}`, {
595
698
  hooks: plugin.hooks.map((h) => h.point)
596
699
  });
597
700
  }
@@ -602,7 +705,7 @@ class AgentComponent extends BaseComponent {
602
705
  }
603
706
  const deleted = agent.plugins.delete(pluginName);
604
707
  if (deleted) {
605
- logger.info(`Plugin unregistered: ${pluginName} from ${agentName}`);
708
+ logger2.info(`Plugin unregistered: ${pluginName} from ${agentName}`);
606
709
  }
607
710
  return deleted;
608
711
  }
@@ -611,7 +714,7 @@ class AgentComponent extends BaseComponent {
611
714
  }
612
715
  getAvailableTools(agent, context) {
613
716
  let tools = filterToolsByAgent([...this.defaultTools], agent);
614
- logger.debug(`[getAvailableTools] After defaultTools (filtered): ${tools.length} tools`, {
717
+ logger2.debug(`[getAvailableTools] After defaultTools (filtered): ${tools.length} tools`, {
615
718
  toolNames: tools.map((t) => t.name)
616
719
  });
617
720
  if (this.toolComponent?.listTools) {
@@ -620,33 +723,33 @@ class AgentComponent extends BaseComponent {
620
723
  });
621
724
  const filteredComponentTools = filterToolsByAgent(componentTools, agent);
622
725
  tools = [...tools, ...filteredComponentTools];
623
- logger.debug(`[getAvailableTools] After adding componentTools: ${tools.length} tools`, {
726
+ logger2.debug(`[getAvailableTools] After adding componentTools: ${tools.length} tools`, {
624
727
  componentToolNames: filteredComponentTools.map((t) => t.name)
625
728
  });
626
729
  }
627
730
  const allowedTools = context?.allowedTools ?? agent.config.allowedTools;
628
731
  const deniedTools = context?.deniedTools ?? agent.config.deniedTools;
629
- logger.debug(`[getAvailableTools] Filtering: allowed=${allowedTools}, denied=${deniedTools}`);
732
+ logger2.debug(`[getAvailableTools] Filtering: allowed=${allowedTools}, denied=${deniedTools}`);
630
733
  if (allowedTools !== undefined && allowedTools !== null) {
631
734
  tools = tools.filter((t) => allowedTools.includes(t.name));
632
- logger.debug(`[getAvailableTools] After allowedTools filter: ${tools.length} tools`, {
735
+ logger2.debug(`[getAvailableTools] After allowedTools filter: ${tools.length} tools`, {
633
736
  toolNames: tools.map((t) => t.name)
634
737
  });
635
738
  }
636
739
  if (deniedTools?.length) {
637
740
  tools = tools.filter((t) => !deniedTools.includes(t.name));
638
- logger.debug(`[getAvailableTools] After deniedTools filter: ${tools.length} tools`, {
741
+ logger2.debug(`[getAvailableTools] After deniedTools filter: ${tools.length} tools`, {
639
742
  toolNames: tools.map((t) => t.name)
640
743
  });
641
744
  }
642
745
  if (context?.extraTools?.length) {
643
746
  const filteredExtraTools = filterToolsByAgent(context.extraTools, agent);
644
747
  tools = [...tools, ...filteredExtraTools];
645
- logger.debug(`[getAvailableTools] After extraTools (filtered): ${tools.length} tools`, {
748
+ logger2.debug(`[getAvailableTools] After extraTools (filtered): ${tools.length} tools`, {
646
749
  extraToolNames: filteredExtraTools.map((t) => t.name)
647
750
  });
648
751
  }
649
- logger.debug(`[getAvailableTools] Final tools: ${tools.length}`, {
752
+ logger2.debug(`[getAvailableTools] Final tools: ${tools.length}`, {
650
753
  toolNames: tools.map((t) => t.name)
651
754
  });
652
755
  return tools;
@@ -672,7 +775,7 @@ class AgentComponent extends BaseComponent {
672
775
  }
673
776
  flushPendingFakeUserMessage(hookCtx, pendingMsg, iter) {
674
777
  this.pushMessage(hookCtx, pendingMsg);
675
- logger.debug(`[ReAct] Meta-protocol: flushed user message AFTER all tool-results (iter=${iter})`);
778
+ logger2.debug(`[ReAct] Meta-protocol: flushed user message AFTER all tool-results (iter=${iter})`);
676
779
  }
677
780
  async _run(agentName, query, context) {
678
781
  await this.refreshDependencies();
@@ -680,9 +783,18 @@ class AgentComponent extends BaseComponent {
680
783
  if (!agent) {
681
784
  throw new Error(`Agent not found: ${agentName}`);
682
785
  }
683
- const runId = `${agentName}:${++this.runCounter}`;
786
+ if (context?.runId !== undefined && context.runId.trim() === "") {
787
+ throw new Error(`AgentComponent._run: caller-provided runId must not be empty`);
788
+ }
789
+ const internalRunId = `${agentName}:${++this.runCounter}`;
790
+ const runId = context?.runId ?? internalRunId;
791
+ if (context?.runId) {
792
+ if (this.aborted.has(runId) || this.abortControllers.has(runId)) {
793
+ throw new Error(`AgentComponent._run: caller-provided runId '${runId}' is already in use`);
794
+ }
795
+ }
684
796
  const querySummary = typeof query === "string" ? query.substring(0, 100) : query.filter((p) => p.type === "text").map((p) => p.text).join(" ").substring(0, 100) || "[multimodal query]";
685
- logger.info(`Starting agent run: ${agentName} (runId=${runId})`, { query: querySummary });
797
+ logger2.info(`Starting agent run: ${agentName} (runId=${runId})`, { query: querySummary });
686
798
  agent.status = "running";
687
799
  this.aborted.set(runId, false);
688
800
  const abortController = new AbortController;
@@ -708,7 +820,7 @@ class AgentComponent extends BaseComponent {
708
820
  resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{memory}}", "(Memory component not available)");
709
821
  }
710
822
  } catch (err) {
711
- logger.warn(`[AgentComponent._run] Failed to replace {{memory}}: ${err}`);
823
+ logger2.warn(`[AgentComponent._run] Failed to replace {{memory}}: ${err}`);
712
824
  resolvedSystemPrompt = resolvedSystemPrompt.replaceAll("{{memory}}", "(Failed to load memory)");
713
825
  }
714
826
  }
@@ -757,7 +869,7 @@ class AgentComponent extends BaseComponent {
757
869
  historyMessageCount = hookCtx.messages.length;
758
870
  }
759
871
  } catch (err) {
760
- logger.warn(`Failed to load session history: ${err}`);
872
+ logger2.warn(`Failed to load session history: ${err}`);
761
873
  }
762
874
  }
763
875
  const parentEnvContext = getEnvContext();
@@ -813,14 +925,14 @@ class AgentComponent extends BaseComponent {
813
925
  iteration++;
814
926
  hookCtx.iteration = iteration;
815
927
  result.iterations = iteration;
816
- logger.debug(`Iteration ${iteration} started`);
928
+ logger2.debug(`Iteration ${iteration} started`);
817
929
  this.doomLoopCaches.set(runId, new Map);
818
930
  hookCtx.currentToolCall = undefined;
819
931
  hookCtx.maxIterations = agent.config.maxIterations;
820
932
  let iterAllToolCalls = [];
821
933
  let iterProcessedCount = 0;
822
934
  try {
823
- logger.debug(`[ReAct] Iteration ${iteration} buildMessages result: ${hookCtx.messages.length} messages`);
935
+ logger2.debug(`[ReAct] Iteration ${iteration} buildMessages result: ${hookCtx.messages.length} messages`);
824
936
  await this.executePluginHooks(agent, "agent:before.llm", hookCtx);
825
937
  if (hookCtx._stopped)
826
938
  break;
@@ -905,7 +1017,7 @@ class AgentComponent extends BaseComponent {
905
1017
  }
906
1018
  const assistantContent = llmOutput.content?.substring(0, 80) || "(no text)";
907
1019
  const toolCallNames = llmOutput.toolCalls?.map((tc) => tc.function?.name || tc.name).join(", ") || "none";
908
- logger.debug(`[ReAct] Iteration ${iteration} Adding assistant message: text="${assistantContent}" toolCalls=[${toolCallNames}]`);
1020
+ logger2.debug(`[ReAct] Iteration ${iteration} Adding assistant message: text="${assistantContent}" toolCalls=[${toolCallNames}]`);
909
1021
  this.pushMessage(hookCtx, {
910
1022
  role: "assistant",
911
1023
  content: assistantParts
@@ -954,7 +1066,7 @@ class AgentComponent extends BaseComponent {
954
1066
  }
955
1067
  const toolOutput = composeToolOutputForLLM(toolResult.name, toolResult.result);
956
1068
  const toolOutputPreview = typeof toolOutput === "string" ? toolOutput.substring(0, 50) : JSON.stringify(toolOutput).substring(0, 50);
957
- logger.debug(`[ReAct] Iteration ${iteration} Adding tool message: tool=${toolResult.name} output="${toolOutputPreview}..."`);
1069
+ logger2.debug(`[ReAct] Iteration ${iteration} Adding tool message: tool=${toolResult.name} output="${toolOutputPreview}..."`);
958
1070
  this.pushMessage(hookCtx, {
959
1071
  role: "tool",
960
1072
  content: [{
@@ -968,7 +1080,7 @@ class AgentComponent extends BaseComponent {
968
1080
  const captured = this.consumeMetaProtocolUserMessage(hookCtx);
969
1081
  if (captured) {
970
1082
  pendingFakeUserMessage = captured;
971
- logger.debug(`[ReAct] Meta-protocol: captured user message (tool=${toolResult.name}, iter=${iteration}); will flush after loop`);
1083
+ logger2.debug(`[ReAct] Meta-protocol: captured user message (tool=${toolResult.name}, iter=${iteration}); will flush after loop`);
972
1084
  }
973
1085
  }
974
1086
  result.toolCalls.push(hookCtx.currentToolCall);
@@ -980,7 +1092,7 @@ class AgentComponent extends BaseComponent {
980
1092
  await this.executePluginHooks(agent, "agent:on.iteration", hookCtx);
981
1093
  }
982
1094
  } catch (error) {
983
- logger.error(`Iteration ${iteration} error`, { error });
1095
+ logger2.error(`Iteration ${iteration} error`, { error });
984
1096
  hookCtx.error = error instanceof Error ? error : new Error(String(error));
985
1097
  if (error instanceof ContextError && error.llmOutput) {
986
1098
  const llmOutput = error.llmOutput;
@@ -1112,7 +1224,7 @@ class AgentComponent extends BaseComponent {
1112
1224
  if (effectiveContext.persistSession !== false) {
1113
1225
  await this.recordSessionMessages(effectiveContext.sessionId, newMessages);
1114
1226
  } else {
1115
- logger.debug(`Skipping session message recording (persistSession=false, sessionId=${effectiveContext.sessionId})`);
1227
+ logger2.debug(`Skipping session message recording (persistSession=false, sessionId=${effectiveContext.sessionId})`);
1116
1228
  }
1117
1229
  const reactContext = {
1118
1230
  messages: hookCtx.messages,
@@ -1152,7 +1264,7 @@ class AgentComponent extends BaseComponent {
1152
1264
  }
1153
1265
  });
1154
1266
  }
1155
- logger.info(`Agent run completed: ${agentName}`, {
1267
+ logger2.info(`Agent run completed: ${agentName}`, {
1156
1268
  iterations: result.iterations,
1157
1269
  hasError: !!result.error,
1158
1270
  hookCtxMessages: hookCtx.messages.length,
@@ -1171,10 +1283,40 @@ class AgentComponent extends BaseComponent {
1171
1283
  for (const [key, controller] of this.abortControllers) {
1172
1284
  if (key.startsWith(agentName + ":")) {
1173
1285
  controller.abort();
1174
- logger.debug(`[abort] AbortController.abort() called for run: ${key}`);
1286
+ logger2.debug(`[abort] AbortController.abort() called for run: ${key}`);
1175
1287
  }
1176
1288
  }
1177
- logger.info(`Agent aborted: ${agentName}`);
1289
+ logger2.info(`Agent aborted: ${agentName}`);
1290
+ }
1291
+ abortRun(runId, reason) {
1292
+ if (!runId) {
1293
+ return false;
1294
+ }
1295
+ const foundInAborted = this.aborted.has(runId);
1296
+ const foundInControllers = this.abortControllers.has(runId);
1297
+ if (!foundInAborted && !foundInControllers) {
1298
+ logger2.debug(`[abort] abortRun: runId not found (already finalized?)`, {
1299
+ runId,
1300
+ reason
1301
+ });
1302
+ return false;
1303
+ }
1304
+ if (foundInAborted) {
1305
+ this.aborted.set(runId, true);
1306
+ }
1307
+ const controller = this.abortControllers.get(runId);
1308
+ if (controller && !controller.signal.aborted) {
1309
+ try {
1310
+ controller.abort();
1311
+ } catch {}
1312
+ }
1313
+ logger2.info(`[abort] run-scoped abort`, {
1314
+ runId,
1315
+ reason,
1316
+ currentBgTaskId: getCurrentBgTaskId(),
1317
+ currentTaskId: getCurrentTaskId()
1318
+ });
1319
+ return true;
1178
1320
  }
1179
1321
  abortAll() {
1180
1322
  for (const key of this.aborted.keys()) {
@@ -1182,9 +1324,9 @@ class AgentComponent extends BaseComponent {
1182
1324
  }
1183
1325
  for (const [key, controller] of this.abortControllers) {
1184
1326
  controller.abort();
1185
- logger.debug(`[abortAll] AbortController.abort() called for run: ${key}`);
1327
+ logger2.debug(`[abortAll] AbortController.abort() called for run: ${key}`);
1186
1328
  }
1187
- logger.info(`All agents aborted (${this.abortControllers.size} runs)`);
1329
+ logger2.info(`All agents aborted (${this.abortControllers.size} runs)`);
1188
1330
  }
1189
1331
  async _buildAdditionInfo(ctx) {
1190
1332
  let additionInfo = ctx.context?.additionInfo || "";
@@ -1217,11 +1359,11 @@ ${additionInfo}`
1217
1359
  return messages;
1218
1360
  }
1219
1361
  async invokeLLM(ctx) {
1220
- logger.debug("[invokeLLM] Starting LLM invocation");
1362
+ logger2.debug("[invokeLLM] Starting LLM invocation");
1221
1363
  if (this.llmComponent?.invoke) {
1222
1364
  const messages = await this.buildMessages(ctx);
1223
1365
  const convertedMessages = messages.map(toLLMMessage);
1224
- logger.debug(`[invokeLLM] Calling LLMComponent.invoke with ${convertedMessages.length} messages`);
1366
+ logger2.debug(`[invokeLLM] Calling LLMComponent.invoke with ${convertedMessages.length} messages`);
1225
1367
  try {
1226
1368
  const llmPromise = this.llmComponent.invoke({
1227
1369
  messages: convertedMessages,
@@ -1240,7 +1382,7 @@ ${additionInfo}`
1240
1382
  ...ctx.context.toolChoice ? { toolChoice: ctx.context.toolChoice } : {}
1241
1383
  });
1242
1384
  const result = await withTimeout(llmPromise, 300000, "LLM invocation timeout after 300s");
1243
- logger.debug("[invokeLLM] LLMComponent.invoke returned successfully");
1385
+ logger2.debug("[invokeLLM] LLMComponent.invoke returned successfully");
1244
1386
  return {
1245
1387
  content: result.output?.content || "",
1246
1388
  reasoning: result.output?.reasoning,
@@ -1256,11 +1398,11 @@ ${additionInfo}`
1256
1398
  finishReason: result.output?.finishReason
1257
1399
  };
1258
1400
  } catch (error) {
1259
- logger.error("[invokeLLM] LLMComponent.invoke threw an error:", error);
1401
+ logger2.error("[invokeLLM] LLMComponent.invoke threw an error:", error);
1260
1402
  throw error;
1261
1403
  }
1262
1404
  }
1263
- logger.warn("[invokeLLM] No LLMComponent available, using mock");
1405
+ logger2.warn("[invokeLLM] No LLMComponent available, using mock");
1264
1406
  return {
1265
1407
  content: "Mock response: Hello!",
1266
1408
  finishReason: "stop"
@@ -1269,8 +1411,8 @@ ${additionInfo}`
1269
1411
  async executeTool(ctx) {
1270
1412
  const toolCall = ctx.currentToolCall;
1271
1413
  const toolName = toolCall.function?.name || toolCall.name || "unknown";
1272
- logger.debug(`[executeTool] Looking for tool: "${toolName}"`);
1273
- logger.debug(`[executeTool] Available tools: [${ctx.tools.map((t) => t.name).join(", ")}]`);
1414
+ logger2.debug(`[executeTool] Looking for tool: "${toolName}"`);
1415
+ logger2.debug(`[executeTool] Available tools: [${ctx.tools.map((t) => t.name).join(", ")}]`);
1274
1416
  const tool = ctx.tools.find((t) => t.name === toolName);
1275
1417
  if (!tool) {
1276
1418
  this.pushEnvEvent({
@@ -1316,7 +1458,7 @@ ${additionInfo}`
1316
1458
  const isLongRunningTool = toolName === "delegate_task" || toolName === "stop_task" || toolName === "bash" || toolName === "workflow_run" || toolName === "run-workflow";
1317
1459
  const isExtraTool = this.toolComponent?.getTool ? !this.toolComponent.getTool(toolName) : false;
1318
1460
  if (isExtraTool) {
1319
- logger.debug(`[executeTool] Tool "${toolName}" is an extraTool, executing directly`);
1461
+ logger2.debug(`[executeTool] Tool "${toolName}" is an extraTool, executing directly`);
1320
1462
  const toolPromise = tool.execute(toolCall.arguments, toolContext);
1321
1463
  if (isLongRunningTool) {
1322
1464
  result = await toolPromise;
@@ -1332,7 +1474,7 @@ ${additionInfo}`
1332
1474
  result = await withTimeout(toolPromise, 120000, `Tool '${toolName}' execution timeout after 120s`);
1333
1475
  }
1334
1476
  } else {
1335
- logger.debug(`[executeTool] No ToolComponent available, executing tool directly`);
1477
+ logger2.debug(`[executeTool] No ToolComponent available, executing tool directly`);
1336
1478
  const toolPromise = tool.execute(toolCall.arguments, toolContext);
1337
1479
  if (isLongRunningTool) {
1338
1480
  result = await toolPromise;
@@ -1399,14 +1541,14 @@ ${additionInfo}`
1399
1541
  if (!result.continue) {
1400
1542
  ctx._stopped = true;
1401
1543
  ctx._stopReason = `Plugin ${plugin.name} stopped execution`;
1402
- logger.info(`Hook ${point} stopped by plugin ${plugin.name}`);
1544
+ logger2.info(`Hook ${point} stopped by plugin ${plugin.name}`);
1403
1545
  break;
1404
1546
  }
1405
1547
  if (result.action) {
1406
1548
  await this.handleHookAction(result.action, ctx);
1407
1549
  }
1408
1550
  } catch (error) {
1409
- logger.error(`Hook ${point} error in plugin ${plugin.name}`, { error });
1551
+ logger2.error(`Hook ${point} error in plugin ${plugin.name}`, { error });
1410
1552
  ctx._errors = ctx._errors || [];
1411
1553
  ctx._errors.push({
1412
1554
  plugin: plugin.name,
@@ -1438,7 +1580,7 @@ ${additionInfo}`
1438
1580
  }
1439
1581
  }
1440
1582
  notifyMessageAdded(message) {
1441
- logger.debug(`Message added: ${message.role}`);
1583
+ logger2.debug(`Message added: ${message.role}`);
1442
1584
  }
1443
1585
  finalizeResult(result, ctx) {
1444
1586
  return {
@@ -1455,7 +1597,7 @@ ${additionInfo}`
1455
1597
  try {
1456
1598
  const sessionComponent = this.env.getComponent("session");
1457
1599
  if (!sessionComponent) {
1458
- logger.warn("SessionComponent not found, skipping session recording");
1600
+ logger2.warn("SessionComponent not found, skipping session recording");
1459
1601
  return;
1460
1602
  }
1461
1603
  filtered = [];
@@ -1480,9 +1622,9 @@ ${additionInfo}`
1480
1622
  } catch (err) {
1481
1623
  const kind = err && typeof err === "object" && "kind" in err ? err.kind : undefined;
1482
1624
  if (kind === "lock_exhausted") {
1483
- logger.error(`[recordSessionMessages] DROPPED ${filtered?.length ?? "?"} message(s) — SQLITE_BUSY retry exhausted after ${err.attempts ?? "?"} attempts. Session ${sessionId} is now inconsistent with LLM context. Original: ${err}`);
1625
+ logger2.error(`[recordSessionMessages] DROPPED ${filtered?.length ?? "?"} message(s) — SQLITE_BUSY retry exhausted after ${err.attempts ?? "?"} attempts. Session ${sessionId} is now inconsistent with LLM context. Original: ${err}`);
1484
1626
  } else {
1485
- logger.error(`[recordSessionMessages] Failed to record session messages for ${sessionId}: ${err}`);
1627
+ logger2.error(`[recordSessionMessages] Failed to record session messages for ${sessionId}: ${err}`);
1486
1628
  }
1487
1629
  }
1488
1630
  }
@@ -1513,7 +1655,7 @@ ${additionInfo}`
1513
1655
  };
1514
1656
  this.env?.pushEnvEvent(fullEvent);
1515
1657
  } catch (err) {
1516
- logger.warn(`[pushEnvEvent] Failed to push event: ${err}`);
1658
+ logger2.warn(`[pushEnvEvent] Failed to push event: ${err}`);
1517
1659
  }
1518
1660
  }
1519
1661
  }