@@ -1441,10 +1441,13 @@ class Agent: |
| 1441 | 1441 | |
| 1442 | 1442 | # First, try to extract bracket format: [calls bash tool with: ...] |
| 1443 | 1443 | # or [USE bash tool: ...] or similar variations |
| 1444 | + # Note: Using (.+?) with re.DOTALL to capture content that may span patterns |
| 1445 | + # The ] at end acts as anchor, but we need to handle ] inside content |
| 1444 | 1446 | bracket_patterns = [ |
| 1447 | + r'\[calls?\s+(\w+)\s+tool\s+with:\s*(.+?)\](?=\s*(?:\n|$|[A-Z]|Done|Created|Error))', |
| 1448 | + r'\[USE\s+(\w+)\s+tool:\s*(.+?)\](?=\s*(?:\n|$|[A-Z]|Done|Created|Error))', |
| 1445 | 1449 | r'\[calls?\s+(\w+)\s+tool\s+with:\s*([^\]]+)\]', |
| 1446 | 1450 | r'\[USE\s+(\w+)\s+tool:\s*([^\]]+)\]', |
| 1447 | | - r'\[(\w+)\s+tool:\s*([^\]]+)\]', |
| 1448 | 1451 | ] |
| 1449 | 1452 | |
| 1450 | 1453 | for pattern in bracket_patterns: |
@@ -1469,15 +1472,38 @@ class Agent: |
| 1469 | 1472 | )) |
| 1470 | 1473 | elif tool_name == "write": |
| 1471 | 1474 | # write tool: file_path=..., content="..." |
| 1472 | | - file_path_match = re.search(r'file_path[=:]\s*([^,\s]+)', args_str) |
| 1473 | | - content_match = re.search(r'content[=:]\s*["\'](.+)["\']', args_str, re.DOTALL) |
| 1474 | | - if not content_match: |
| 1475 | | - # Try without quotes |
| 1476 | | - content_match = re.search(r'content[=:]\s*(.+)', args_str, re.DOTALL) |
| 1475 | + # Handle quoted file paths |
| 1476 | + file_path_match = re.search(r'file_path[=:]\s*["\']?([^"\'`,]+)["\']?', args_str) |
| 1477 | + |
| 1478 | + # For content, find the content= part and extract everything after it |
| 1479 | + # Handle both quoted and unquoted content |
| 1480 | + content_start = re.search(r'content[=:]\s*', args_str) |
| 1481 | + file_content = "" |
| 1482 | + if content_start: |
| 1483 | + rest = args_str[content_start.end():] |
| 1484 | + # Check if content starts with a quote |
| 1485 | + if rest.startswith('"'): |
| 1486 | + # Find matching end quote (handle escaped quotes) |
| 1487 | + end_idx = len(rest) - 1 |
| 1488 | + # Walk backward to find the last quote |
| 1489 | + while end_idx > 0 and rest[end_idx] != '"': |
| 1490 | + end_idx -= 1 |
| 1491 | + if end_idx > 0: |
| 1492 | + file_content = rest[1:end_idx] |
| 1493 | + elif rest.startswith("'"): |
| 1494 | + end_idx = len(rest) - 1 |
| 1495 | + while end_idx > 0 and rest[end_idx] != "'": |
| 1496 | + end_idx -= 1 |
| 1497 | + if end_idx > 0: |
| 1498 | + file_content = rest[1:end_idx] |
| 1499 | + else: |
| 1500 | + # No quotes - take everything |
| 1501 | + file_content = rest.strip() |
| 1502 | + |
| 1503 | + debug(f" write: file_path={file_path_match.group(1) if file_path_match else None}, content_len={len(file_content)}") |
| 1477 | 1504 | |
| 1478 | 1505 | if file_path_match: |
| 1479 | 1506 | file_path = file_path_match.group(1).strip('"\'') |
| 1480 | | - file_content = content_match.group(1) if content_match else "" |
| 1481 | 1507 | tool_calls.append(ToolCall( |
| 1482 | 1508 | id=f"bracket_{tool_name}_{len(tool_calls)}", |
| 1483 | 1509 | name=tool_name, |