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