(result, tool_name)
| 354 | return "[ERROR] " + error_msg |
| 355 | |
| 356 | def is_error(result, tool_name): |
| 357 | if not isinstance(result, str): |
| 358 | return False |
| 359 | result_lower = result.lower() |
| 360 | if "[cancelled]" in result_lower: |
| 361 | return False |
| 362 | # All tools: treat [ERROR] prefix as an error |
| 363 | if result.startswith("[ERROR]"): |
| 364 | return True |
| 365 | # Shell-specific: detect Python tracebacks and command failures |
| 366 | if tool_name == "shell": |
| 367 | error_signals = [ |
| 368 | "traceback", "syntaxerror", "nameerror", "typeerror", |
| 369 | "importerror", "modulenotfounderror", "indentationerror", |
| 370 | "attributeerror", "valueerror", "filenotfounderror", |
| 371 | "permissionerror", "error:", "exception:", "failed", |
| 372 | "command not found", "no such file", |
| 373 | ] |
| 374 | return any(s in result_lower for s in error_signals) |
| 375 | return False |
| 376 | |
| 377 | def is_hallucination(response, user_message, tools_used): |
| 378 | """ |
no outgoing calls
no test coverage detected