open-agents-ai 0.89.0 → 0.90.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 (2) hide show
  1. package/dist/index.js +33 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16487,6 +16487,8 @@ TASK: ${task}` : task }
16487
16487
  let completed = false;
16488
16488
  let summary = "";
16489
16489
  let bruteForceCycle = 0;
16490
+ let consecutiveTextOnly = 0;
16491
+ const MAX_CONSECUTIVE_TEXT_ONLY = 3;
16490
16492
  for (let turn = 0; turn < this.options.maxTurns; turn++) {
16491
16493
  if (this._paused) {
16492
16494
  const shouldContinue = await this.waitIfPaused();
@@ -16600,6 +16602,7 @@ Integrate this guidance into your current approach. Continue working on the task
16600
16602
  break;
16601
16603
  const msg = choice.message;
16602
16604
  if (msg.toolCalls && msg.toolCalls.length > 0) {
16605
+ consecutiveTextOnly = 0;
16603
16606
  messages.push({
16604
16607
  role: "assistant",
16605
16608
  content: msg.content || null,
@@ -16775,6 +16778,7 @@ Do NOT continue walking up parent directories.`);
16775
16778
  } else {
16776
16779
  const content = msg.content || "";
16777
16780
  messages.push({ role: "assistant", content });
16781
+ consecutiveTextOnly++;
16778
16782
  this.emit({
16779
16783
  type: "model_response",
16780
16784
  content: content.slice(0, 200),
@@ -16786,15 +16790,34 @@ Do NOT continue walking up parent directories.`);
16786
16790
  summary = content;
16787
16791
  break;
16788
16792
  }
16793
+ if (consecutiveTextOnly >= MAX_CONSECUTIVE_TEXT_ONLY) {
16794
+ this.emit({
16795
+ type: "status",
16796
+ content: `Model returned ${consecutiveTextOnly} consecutive text-only responses without using tools \u2014 breaking turn loop to avoid runaway`,
16797
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
16798
+ });
16799
+ break;
16800
+ }
16789
16801
  messages.push({
16790
16802
  role: "user",
16791
16803
  content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done."
16792
16804
  });
16793
16805
  }
16794
16806
  }
16807
+ let prevCycleToolCalls = toolCallCount;
16795
16808
  while (!completed && !this.aborted && this.options.bruteForce && bruteForceCycle < this.options.bruteForceMaxCycles) {
16796
16809
  bruteForceCycle++;
16797
16810
  const totalTurns = messages.filter((m) => m.role === "assistant").length;
16811
+ if (bruteForceCycle > 1 && toolCallCount === prevCycleToolCalls) {
16812
+ this.emit({
16813
+ type: "status",
16814
+ content: `Stopping re-engagement \u2014 no tool call progress in cycle ${bruteForceCycle - 1}. Model may not support tool calling for this task.`,
16815
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
16816
+ });
16817
+ break;
16818
+ }
16819
+ prevCycleToolCalls = toolCallCount;
16820
+ consecutiveTextOnly = 0;
16798
16821
  this.emit({
16799
16822
  type: "status",
16800
16823
  content: `Re-engaging \u2014 cycle ${bruteForceCycle} (${totalTurns} turns, ${toolCallCount} tool calls so far)`,
@@ -16918,6 +16941,7 @@ Integrate this guidance into your current approach. Continue working on the task
16918
16941
  break;
16919
16942
  const msg = choice.message;
16920
16943
  if (msg.toolCalls && msg.toolCalls.length > 0) {
16944
+ consecutiveTextOnly = 0;
16921
16945
  messages.push({ role: "assistant", content: msg.content || null, tool_calls: msg.toolCalls.map((tc) => ({ id: tc.id, type: "function", function: { name: tc.name, arguments: JSON.stringify(tc.arguments) } })) });
16922
16946
  for (const tc of msg.toolCalls) {
16923
16947
  if (this.aborted)
@@ -16978,12 +17002,21 @@ Do NOT continue walking up parent directories.`);
16978
17002
  } else {
16979
17003
  const content = msg.content || "";
16980
17004
  messages.push({ role: "assistant", content });
17005
+ consecutiveTextOnly++;
16981
17006
  this.emit({ type: "model_response", content: content.slice(0, 200), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
16982
17007
  if (/task.?complete|all tests pass/i.test(content)) {
16983
17008
  completed = true;
16984
17009
  summary = content;
16985
17010
  break;
16986
17011
  }
17012
+ if (consecutiveTextOnly >= MAX_CONSECUTIVE_TEXT_ONLY) {
17013
+ this.emit({
17014
+ type: "status",
17015
+ content: `Model returned ${consecutiveTextOnly} consecutive text-only responses \u2014 breaking cycle ${bruteForceCycle}`,
17016
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
17017
+ });
17018
+ break;
17019
+ }
16987
17020
  messages.push({ role: "user", content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done." });
16988
17021
  }
16989
17022
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.89.0",
3
+ "version": "0.90.0",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",