fix: add None-entry guard to tool_calls loops in run_agent, batch_runner, and mini_swe_runner (#2316)

Co-authored-by: Dilee <uzmpsk.dilekakbas@gmail.com>
This commit is contained in:
Teknium
2026-03-21 07:20:41 -07:00
committed by GitHub
parent 453f4c5175
commit 9305164bf3
3 changed files with 6 additions and 0 deletions

View File

@@ -128,6 +128,7 @@ def _extract_tool_stats(messages: List[Dict[str, Any]]) -> Dict[str, Dict[str, i
# Track tool calls from assistant messages # Track tool calls from assistant messages
if msg["role"] == "assistant" and "tool_calls" in msg and msg["tool_calls"]: if msg["role"] == "assistant" and "tool_calls" in msg and msg["tool_calls"]:
for tool_call in msg["tool_calls"]: for tool_call in msg["tool_calls"]:
if not tool_call or not isinstance(tool_call, dict): continue
tool_name = tool_call["function"]["name"] tool_name = tool_call["function"]["name"]
tool_call_id = tool_call["id"] tool_call_id = tool_call["id"]

View File

@@ -339,6 +339,7 @@ class MiniSWERunner:
# Add tool calls in XML format # Add tool calls in XML format
for tool_call in msg["tool_calls"]: for tool_call in msg["tool_calls"]:
if not tool_call or not isinstance(tool_call, dict): continue
try: try:
arguments = json.loads(tool_call["function"]["arguments"]) \ arguments = json.loads(tool_call["function"]["arguments"]) \
if isinstance(tool_call["function"]["arguments"], str) \ if isinstance(tool_call["function"]["arguments"], str) \

View File

@@ -1618,6 +1618,7 @@ class AIAgent:
# Add tool calls wrapped in XML tags # Add tool calls wrapped in XML tags
for tool_call in msg["tool_calls"]: for tool_call in msg["tool_calls"]:
if not tool_call or not isinstance(tool_call, dict): continue
# Parse arguments - should always succeed since we validate during conversation # Parse arguments - should always succeed since we validate during conversation
# but keep try-except as safety net # but keep try-except as safety net
try: try:
@@ -6783,6 +6784,7 @@ class AIAgent:
if msg.get("role") == "assistant" and msg.get("tool_calls"): if msg.get("role") == "assistant" and msg.get("tool_calls"):
tool_names = [] tool_names = []
for tc in msg["tool_calls"]: for tc in msg["tool_calls"]:
if not tc or not isinstance(tc, dict): continue
fn = tc.get("function", {}) fn = tc.get("function", {})
tool_names.append(fn.get("name", "unknown")) tool_names.append(fn.get("name", "unknown"))
msg["content"] = f"Calling the {', '.join(tool_names)} tool{'s' if len(tool_names) > 1 else ''}..." msg["content"] = f"Calling the {', '.join(tool_names)} tool{'s' if len(tool_names) > 1 else ''}..."
@@ -6825,6 +6827,7 @@ class AIAgent:
if msg.get("role") == "assistant" and msg.get("tool_calls"): if msg.get("role") == "assistant" and msg.get("tool_calls"):
tool_names = [] tool_names = []
for tc in msg["tool_calls"]: for tc in msg["tool_calls"]:
if not tc or not isinstance(tc, dict): continue
fn = tc.get("function", {}) fn = tc.get("function", {})
tool_names.append(fn.get("name", "unknown")) tool_names.append(fn.get("name", "unknown"))
msg["content"] = f"Calling the {', '.join(tool_names)} tool{'s' if len(tool_names) > 1 else ''}..." msg["content"] = f"Calling the {', '.join(tool_names)} tool{'s' if len(tool_names) > 1 else ''}..."
@@ -6944,6 +6947,7 @@ class AIAgent:
if isinstance(m, dict) and m.get("role") == "tool" if isinstance(m, dict) and m.get("role") == "tool"
} }
for tc in msg["tool_calls"]: for tc in msg["tool_calls"]:
if not tc or not isinstance(tc, dict): continue
if tc["id"] not in answered_ids: if tc["id"] not in answered_ids:
err_msg = { err_msg = {
"role": "tool", "role": "tool",