@tangle-network/agent-runtime 0.47.0 → 0.49.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.
Files changed (41) hide show
  1. package/README.md +79 -15
  2. package/dist/agent.js +1 -1
  3. package/dist/chunk-GHX7XOJ2.js +433 -0
  4. package/dist/chunk-GHX7XOJ2.js.map +1 -0
  5. package/dist/{chunk-T4OQQEE3.js → chunk-IQS4HI3F.js} +14 -5
  6. package/dist/chunk-IQS4HI3F.js.map +1 -0
  7. package/dist/{chunk-72JQCHOZ.js → chunk-PXUTIMGJ.js} +2318 -237
  8. package/dist/chunk-PXUTIMGJ.js.map +1 -0
  9. package/dist/{chunk-MGFEUYOH.js → chunk-U2VEWKKK.js} +3 -3
  10. package/dist/{chunk-JNPK46YH.js → chunk-VIEDXELL.js} +408 -6
  11. package/dist/chunk-VIEDXELL.js.map +1 -0
  12. package/dist/{chunk-VR4JIC5H.js → chunk-XTEZ3YJ4.js} +2 -2
  13. package/dist/index.d.ts +29 -4
  14. package/dist/index.js +109 -21
  15. package/dist/index.js.map +1 -1
  16. package/dist/kb-gate-CsXpNRk7.d.ts +1145 -0
  17. package/dist/{loop-runner-bin-DEm4roYF.d.ts → loop-runner-bin-Cgn0A-NW.d.ts} +1 -1
  18. package/dist/loop-runner-bin.d.ts +2 -2
  19. package/dist/loop-runner-bin.js +3 -3
  20. package/dist/loops.d.ts +3 -3
  21. package/dist/loops.js +57 -1
  22. package/dist/mcp/bin.js +187 -24
  23. package/dist/mcp/bin.js.map +1 -1
  24. package/dist/mcp/index.d.ts +28 -125
  25. package/dist/mcp/index.js +28 -6
  26. package/dist/mcp/index.js.map +1 -1
  27. package/dist/platform.js +2 -2
  28. package/dist/platform.js.map +1 -1
  29. package/dist/runtime.d.ts +1100 -62
  30. package/dist/runtime.js +57 -1
  31. package/dist/{types-Cbx3dNK5.d.ts → types-BpDfCPUp.d.ts} +1 -1
  32. package/dist/workflow.js +1 -1
  33. package/package.json +7 -6
  34. package/dist/chunk-5YDS7BLC.js +0 -218
  35. package/dist/chunk-5YDS7BLC.js.map +0 -1
  36. package/dist/chunk-72JQCHOZ.js.map +0 -1
  37. package/dist/chunk-JNPK46YH.js.map +0 -1
  38. package/dist/chunk-T4OQQEE3.js.map +0 -1
  39. package/dist/kb-gate-51BlLlVM.d.ts +0 -529
  40. /package/dist/{chunk-MGFEUYOH.js.map → chunk-U2VEWKKK.js.map} +0 -0
  41. /package/dist/{chunk-VR4JIC5H.js.map → chunk-XTEZ3YJ4.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  mcpToolsForRuntimeMcp,
3
3
  mcpToolsForRuntimeMcpSubset
4
- } from "./chunk-VR4JIC5H.js";
4
+ } from "./chunk-XTEZ3YJ4.js";
5
5
  import {
6
6
  INTELLIGENCE_WIRE_VERSION,
7
7
  buildLoopOtelSpans,
8
8
  createOtelExporter,
9
9
  exportEvalRuns,
10
10
  loopEventToOtelSpan
11
- } from "./chunk-JNPK46YH.js";
11
+ } from "./chunk-VIEDXELL.js";
12
12
  import {
13
13
  DELEGATED_LOOP_MODES,
14
14
  auditLoopRunner,
@@ -21,9 +21,9 @@ import {
21
21
  runDelegatedLoop,
22
22
  runLoopRunnerCli,
23
23
  selfImproveLoopRunner
24
- } from "./chunk-MGFEUYOH.js";
24
+ } from "./chunk-U2VEWKKK.js";
25
25
  import "./chunk-FNMGYYSS.js";
26
- import "./chunk-5YDS7BLC.js";
26
+ import "./chunk-GHX7XOJ2.js";
27
27
  import "./chunk-KADIJAD4.js";
28
28
  import "./chunk-HNUXAZIJ.js";
29
29
  import {
@@ -31,7 +31,7 @@ import {
31
31
  defineRuntimeHooks,
32
32
  notifyRuntimeDecisionPoint,
33
33
  notifyRuntimeHookEvent
34
- } from "./chunk-72JQCHOZ.js";
34
+ } from "./chunk-PXUTIMGJ.js";
35
35
  import {
36
36
  AgentEvalError,
37
37
  BackendTransportError,
@@ -2734,15 +2734,16 @@ function stripNewlines(value) {
2734
2734
  }
2735
2735
 
2736
2736
  // src/tool-loop.ts
2737
- var DEFAULT_MAX_TOOL_TURNS = 8;
2737
+ var RUNAWAY_BACKSTOP_TURNS = 200;
2738
2738
  var DEFAULT_DECISION_CONTEXT_CHARS = 12e3;
2739
2739
  var FAILURE_RECOVERY_ACTIONS = ["retry", "verify", "continue", "stop"];
2740
+ var STUCK_LOOP_THRESHOLD = 3;
2740
2741
  function defaultRender(label, outcome) {
2741
2742
  if (outcome.ok) return `- ${label} \u2192 ok: ${JSON.stringify(outcome.result)}`;
2742
2743
  return `- ${label} \u2192 failed (${outcome.code}): ${outcome.message}`;
2743
2744
  }
2744
2745
  async function runToolLoop(opts) {
2745
- const maxTurns = opts.maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;
2746
+ const backstop = opts.maxToolTurns ?? RUNAWAY_BACKSTOP_TURNS;
2746
2747
  const render = opts.renderResult ?? defaultRender;
2747
2748
  const labelFor = opts.labelFor ?? ((c) => c.toolName);
2748
2749
  const runId = opts.runId ?? `agent-run-${randomSuffix2()}`;
@@ -2755,9 +2756,16 @@ async function runToolLoop(opts) {
2755
2756
  const toolResults = [];
2756
2757
  let finalText = "";
2757
2758
  let turns = 0;
2758
- observer.loopBefore(maxTurns, messages.length);
2759
+ let accumulatedCostUsd = 0;
2760
+ let lastCallHash = null;
2761
+ let consecutiveCount = 0;
2762
+ observer.loopBefore(backstop, messages.length);
2759
2763
  for (let toolTurn = 0; ; toolTurn++) {
2760
2764
  turns++;
2765
+ if (opts.deadlineMs !== void 0 && Date.now() >= opts.deadlineMs) {
2766
+ observer.loopAfter({ turns, toolResults: toolResults.length, stopReason: "deadline" });
2767
+ return { finalText, toolResults, turns, stopReason: "deadline", cappedOut: true };
2768
+ }
2761
2769
  let turnText = "";
2762
2770
  const pending = [];
2763
2771
  const turnEventId = observer.turnBefore(toolTurn, messages.length);
@@ -2776,18 +2784,33 @@ async function runToolLoop(opts) {
2776
2784
  });
2777
2785
  break;
2778
2786
  }
2779
- if (toolTurn >= maxTurns) {
2787
+ if (toolTurn >= backstop) {
2780
2788
  observer.turnAfter(toolTurn, turnEventId, {
2781
2789
  pendingToolCalls: pending.length,
2782
- cappedOut: true
2790
+ stopReason: "backstop"
2783
2791
  });
2784
- observer.loopAfter({ turns, toolResults: toolResults.length, cappedOut: true });
2785
- return { finalText, toolResults, turns, cappedOut: true };
2792
+ observer.loopAfter({ turns, toolResults: toolResults.length, stopReason: "backstop" });
2793
+ return { finalText, toolResults, turns, stopReason: "backstop", cappedOut: true };
2786
2794
  }
2787
2795
  if (turnText.trim()) messages.push({ role: "assistant", content: turnText });
2788
2796
  const lines = [];
2789
2797
  const outcomes = [];
2790
2798
  for (const [callIndex, call] of pending.entries()) {
2799
+ const callHash = canonicalCallHash(call);
2800
+ if (callHash === lastCallHash) {
2801
+ consecutiveCount++;
2802
+ } else {
2803
+ lastCallHash = callHash;
2804
+ consecutiveCount = 1;
2805
+ }
2806
+ if (consecutiveCount >= STUCK_LOOP_THRESHOLD) {
2807
+ observer.turnAfter(toolTurn, turnEventId, {
2808
+ pendingToolCalls: pending.length,
2809
+ stopReason: "stuck-loop"
2810
+ });
2811
+ observer.loopAfter({ turns, toolResults: toolResults.length, stopReason: "stuck-loop" });
2812
+ return { finalText, toolResults, turns, stopReason: "stuck-loop", cappedOut: true };
2813
+ }
2791
2814
  const callEventId = observer.toolCallBefore(toolTurn, turnEventId, callIndex, call);
2792
2815
  let outcome;
2793
2816
  try {
@@ -2799,6 +2822,20 @@ async function runToolLoop(opts) {
2799
2822
  message: err instanceof Error ? err.message : String(err)
2800
2823
  };
2801
2824
  }
2825
+ if (opts.maxCostUsd !== void 0 && opts.costOf !== void 0) {
2826
+ accumulatedCostUsd += opts.costOf(call, outcome);
2827
+ if (accumulatedCostUsd >= opts.maxCostUsd) {
2828
+ const label2 = labelFor(call);
2829
+ toolResults.push({ call, label: label2, outcome });
2830
+ observer.toolCallAfter(toolTurn, callEventId, call, outcome);
2831
+ observer.turnAfter(toolTurn, turnEventId, {
2832
+ pendingToolCalls: pending.length,
2833
+ stopReason: "budget"
2834
+ });
2835
+ observer.loopAfter({ turns, toolResults: toolResults.length, stopReason: "budget" });
2836
+ return { finalText, toolResults, turns, stopReason: "budget", cappedOut: true };
2837
+ }
2838
+ }
2802
2839
  const label = labelFor(call);
2803
2840
  const rendered = render(label, outcome);
2804
2841
  toolResults.push({ call, label, outcome });
@@ -2824,11 +2861,11 @@ async function runToolLoop(opts) {
2824
2861
  messages.push({ role: "user", content: `Tool results:
2825
2862
  ${lines.join("\n")}` });
2826
2863
  }
2827
- observer.loopAfter({ turns, toolResults: toolResults.length, cappedOut: false });
2828
- return { finalText, toolResults, turns, cappedOut: false };
2864
+ observer.loopAfter({ turns, toolResults: toolResults.length, stopReason: "completed" });
2865
+ return { finalText, toolResults, turns, stopReason: "completed", cappedOut: false };
2829
2866
  }
2830
2867
  async function* streamToolLoop(opts) {
2831
- const maxTurns = opts.maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;
2868
+ const backstop = opts.maxToolTurns ?? RUNAWAY_BACKSTOP_TURNS;
2832
2869
  const render = opts.renderResult ?? defaultRender;
2833
2870
  const labelFor = opts.labelFor ?? ((c) => c.toolName);
2834
2871
  const runId = opts.runId ?? `agent-run-${randomSuffix2()}`;
@@ -2838,8 +2875,16 @@ async function* streamToolLoop(opts) {
2838
2875
  { role: "user", content: opts.userMessage }
2839
2876
  ];
2840
2877
  const observer = createToolLoopObserver(opts.hooks, runId, opts.scenarioId);
2841
- observer.loopBefore(maxTurns, messages.length);
2878
+ let accumulatedCostUsd = 0;
2879
+ let lastCallHash = null;
2880
+ let consecutiveCount = 0;
2881
+ observer.loopBefore(backstop, messages.length);
2842
2882
  for (let toolTurn = 0; ; toolTurn++) {
2883
+ if (opts.deadlineMs !== void 0 && Date.now() >= opts.deadlineMs) {
2884
+ observer.loopAfter({ turns: toolTurn + 1, stopReason: "deadline" });
2885
+ yield { kind: "capped", pending: 0, stopReason: "deadline" };
2886
+ return;
2887
+ }
2843
2888
  let turnText = "";
2844
2889
  const pending = [];
2845
2890
  const turnEventId = observer.turnBefore(toolTurn, messages.length);
@@ -2851,22 +2896,38 @@ async function* streamToolLoop(opts) {
2851
2896
  }
2852
2897
  if (pending.length === 0) {
2853
2898
  observer.turnAfter(toolTurn, turnEventId, { pendingToolCalls: 0 });
2854
- observer.loopAfter({ turns: toolTurn + 1, cappedOut: false });
2899
+ observer.loopAfter({ turns: toolTurn + 1, stopReason: "completed" });
2855
2900
  return;
2856
2901
  }
2857
- if (toolTurn >= maxTurns) {
2902
+ if (toolTurn >= backstop) {
2858
2903
  observer.turnAfter(toolTurn, turnEventId, {
2859
2904
  pendingToolCalls: pending.length,
2860
- cappedOut: true
2905
+ stopReason: "backstop"
2861
2906
  });
2862
- observer.loopAfter({ turns: toolTurn + 1, cappedOut: true });
2863
- yield { kind: "capped", pending: pending.length };
2907
+ observer.loopAfter({ turns: toolTurn + 1, stopReason: "backstop" });
2908
+ yield { kind: "capped", pending: pending.length, stopReason: "backstop" };
2864
2909
  return;
2865
2910
  }
2866
2911
  if (turnText.trim()) messages.push({ role: "assistant", content: turnText });
2867
2912
  const lines = [];
2868
2913
  const outcomes = [];
2869
2914
  for (const [callIndex, call] of pending.entries()) {
2915
+ const callHash = canonicalCallHash(call);
2916
+ if (callHash === lastCallHash) {
2917
+ consecutiveCount++;
2918
+ } else {
2919
+ lastCallHash = callHash;
2920
+ consecutiveCount = 1;
2921
+ }
2922
+ if (consecutiveCount >= STUCK_LOOP_THRESHOLD) {
2923
+ observer.turnAfter(toolTurn, turnEventId, {
2924
+ pendingToolCalls: pending.length,
2925
+ stopReason: "stuck-loop"
2926
+ });
2927
+ observer.loopAfter({ turns: toolTurn + 1, stopReason: "stuck-loop" });
2928
+ yield { kind: "capped", pending: pending.length, stopReason: "stuck-loop" };
2929
+ return;
2930
+ }
2870
2931
  const callEventId = observer.toolCallBefore(toolTurn, turnEventId, callIndex, call);
2871
2932
  let outcome;
2872
2933
  try {
@@ -2878,6 +2939,27 @@ async function* streamToolLoop(opts) {
2878
2939
  message: err instanceof Error ? err.message : String(err)
2879
2940
  };
2880
2941
  }
2942
+ if (opts.maxCostUsd !== void 0 && opts.costOf !== void 0) {
2943
+ accumulatedCostUsd += opts.costOf(call, outcome);
2944
+ if (accumulatedCostUsd >= opts.maxCostUsd) {
2945
+ const label2 = labelFor(call);
2946
+ yield {
2947
+ kind: "tool_result",
2948
+ toolName: call.toolName,
2949
+ toolCallId: call.toolCallId,
2950
+ label: label2,
2951
+ outcome
2952
+ };
2953
+ observer.toolCallAfter(toolTurn, callEventId, call, outcome);
2954
+ observer.turnAfter(toolTurn, turnEventId, {
2955
+ pendingToolCalls: pending.length,
2956
+ stopReason: "budget"
2957
+ });
2958
+ observer.loopAfter({ turns: toolTurn + 1, stopReason: "budget" });
2959
+ yield { kind: "capped", pending: pending.length, stopReason: "budget" };
2960
+ return;
2961
+ }
2962
+ }
2881
2963
  const label = labelFor(call);
2882
2964
  yield {
2883
2965
  kind: "tool_result",
@@ -3095,6 +3177,12 @@ ${outcomes.map((item) => item.rendered).join("\n")}`];
3095
3177
  DEFAULT_DECISION_CONTEXT_CHARS
3096
3178
  );
3097
3179
  }
3180
+ function canonicalCallHash(call) {
3181
+ const sortedArgs = Object.fromEntries(
3182
+ Object.entries(call.args).sort(([a], [b]) => a.localeCompare(b))
3183
+ );
3184
+ return `${call.toolName}:${JSON.stringify(sortedArgs)}`;
3185
+ }
3098
3186
  function stringifySafe(value, max) {
3099
3187
  let text;
3100
3188
  try {