@@ -993,7 +993,19 @@ class Agent: |
| 993 | 993 | # No tool calls - check if model outputted raw JSON tool calls as text |
| 994 | 994 | # Some small models do this instead of using the proper API |
| 995 | 995 | if not tool_calls: |
| 996 | + try: |
| 997 | + with open("/tmp/loader_debug.log", "a") as f: |
| 998 | + f.write(f"[loop] no tool_calls, checking for raw JSON/bracket format in content (len={len(content)})\n") |
| 999 | + except Exception: |
| 1000 | + pass |
| 996 | 1001 | raw_tool_calls = self._extract_raw_json_tool_calls(content) |
| 1002 | + try: |
| 1003 | + with open("/tmp/loader_debug.log", "a") as f: |
| 1004 | + f.write(f"[loop] _extract_raw_json_tool_calls returned {len(raw_tool_calls)} calls\n") |
| 1005 | + for tc in raw_tool_calls: |
| 1006 | + f.write(f"[loop] - {tc.name}: {list(tc.arguments.keys())}\n") |
| 1007 | + except Exception: |
| 1008 | + pass |
| 997 | 1009 | if raw_tool_calls: |
| 998 | 1010 | # Successfully extracted tool calls from raw JSON - use them |
| 999 | 1011 | tool_calls = raw_tool_calls |
@@ -1002,9 +1014,19 @@ class Agent: |
| 1002 | 1014 | |
| 1003 | 1015 | # If we now have tool calls (from raw JSON extraction), execute them |
| 1004 | 1016 | if tool_calls: |
| 1017 | + try: |
| 1018 | + with open("/tmp/loader_debug.log", "a") as f: |
| 1019 | + f.write(f"[loop] executing {len(tool_calls)} extracted tool calls\n") |
| 1020 | + except Exception: |
| 1021 | + pass |
| 1005 | 1022 | # This duplicates the tool execution logic above, but that's intentional |
| 1006 | 1023 | # to handle the case where raw JSON tool calls are extracted |
| 1007 | 1024 | for tc in tool_calls: |
| 1025 | + try: |
| 1026 | + with open("/tmp/loader_debug.log", "a") as f: |
| 1027 | + f.write(f"[loop] executing extracted tool: {tc.name} args={tc.arguments}\n") |
| 1028 | + except Exception: |
| 1029 | + pass |
| 1008 | 1030 | actions_taken.append(f"{tc.name}: {str(tc.arguments)[:50]}...") |
| 1009 | 1031 | await emit(AgentEvent( |
| 1010 | 1032 | type="tool_call", |
@@ -1343,6 +1365,16 @@ class Agent: |
| 1343 | 1365 | tool_calls = [] |
| 1344 | 1366 | tool_names = ["write", "read", "edit", "bash", "glob", "grep"] |
| 1345 | 1367 | |
| 1368 | + # Debug log |
| 1369 | + def debug(msg): |
| 1370 | + try: |
| 1371 | + with open("/tmp/loader_debug.log", "a") as f: |
| 1372 | + f.write(f"[extract] {msg}\n") |
| 1373 | + except Exception: |
| 1374 | + pass |
| 1375 | + |
| 1376 | + debug(f"checking content len={len(content)}") |
| 1377 | + |
| 1346 | 1378 | # First, try to extract bracket format: [calls bash tool with: ...] |
| 1347 | 1379 | # or [USE bash tool: ...] or similar variations |
| 1348 | 1380 | bracket_patterns = [ |
@@ -1352,11 +1384,14 @@ class Agent: |
| 1352 | 1384 | ] |
| 1353 | 1385 | |
| 1354 | 1386 | for pattern in bracket_patterns: |
| 1387 | + debug(f"trying pattern: {pattern}") |
| 1355 | 1388 | for match in re.finditer(pattern, content, re.IGNORECASE): |
| 1356 | 1389 | tool_name = match.group(1).lower() |
| 1357 | 1390 | args_str = match.group(2).strip() |
| 1391 | + debug(f" matched: tool={tool_name}, args={args_str[:50]}...") |
| 1358 | 1392 | |
| 1359 | 1393 | if tool_name not in tool_names: |
| 1394 | + debug(f" skipping - tool_name '{tool_name}' not in tool_names") |
| 1360 | 1395 | continue |
| 1361 | 1396 | |
| 1362 | 1397 | try: |