mirror of
https://github.com/codeflash-ai/codeflash.git
synced 2026-05-04 18:25:17 +00:00
fix: output structured XML errors in subagent mode
When codeflash runs with --subagent (e.g., via the Claude Code plugin), exit_with_message() now outputs <codeflash-error> XML to stdout instead of Rich panel text. This lets the calling agent parse errors programmatically rather than receiving unstructured text. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1e92f3d2ed
commit
bc7a5bf4bb
2 changed files with 37 additions and 1 deletions
|
|
@ -17,7 +17,7 @@ import tomlkit
|
|||
|
||||
from codeflash.cli_cmds.console import logger, paneled_text
|
||||
from codeflash.code_utils.config_parser import find_pyproject_toml, get_all_closest_config_files
|
||||
from codeflash.lsp.helpers import is_LSP_enabled
|
||||
from codeflash.lsp.helpers import is_LSP_enabled, is_subagent_mode
|
||||
|
||||
_INVALID_CHARS_NT = {"<", ">", ":", '"', "|", "?", "*"}
|
||||
|
||||
|
|
@ -458,6 +458,11 @@ def exit_with_message(message: str, *, error_on_exit: bool = False) -> None:
|
|||
if is_LSP_enabled():
|
||||
logger.error(message)
|
||||
return
|
||||
if is_subagent_mode():
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
sys.stdout.write(f"<codeflash-error>{escape(message)}</codeflash-error>\n")
|
||||
sys.exit(1 if error_on_exit else 0)
|
||||
paneled_text(message, panel_args={"style": "red"})
|
||||
|
||||
sys.exit(1 if error_on_exit else 0)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import pytest
|
|||
|
||||
from codeflash.code_utils.code_utils import (
|
||||
cleanup_paths,
|
||||
exit_with_message,
|
||||
file_name_from_test_module_name,
|
||||
file_path_from_module_name,
|
||||
get_all_function_names,
|
||||
|
|
@ -751,3 +752,33 @@ class MyClass:
|
|||
"""
|
||||
result = validate_python_code(code)
|
||||
assert result == code
|
||||
|
||||
|
||||
class TestExitWithMessageSubagent:
|
||||
@patch("codeflash.code_utils.code_utils.is_subagent_mode", return_value=True)
|
||||
def test_outputs_structured_xml_in_subagent_mode(self, _mock_subagent: MagicMock, capsys: pytest.CaptureFixture[str]) -> None:
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
exit_with_message("Something went wrong", error_on_exit=True)
|
||||
assert exc_info.value.code == 1
|
||||
captured = capsys.readouterr()
|
||||
assert "<codeflash-error>" in captured.out
|
||||
assert "Something went wrong" in captured.out
|
||||
assert "</codeflash-error>" in captured.out
|
||||
|
||||
@patch("codeflash.code_utils.code_utils.is_subagent_mode", return_value=True)
|
||||
def test_escapes_xml_special_chars(self, _mock_subagent: MagicMock, capsys: pytest.CaptureFixture[str]) -> None:
|
||||
with pytest.raises(SystemExit):
|
||||
exit_with_message('File <foo> & "bar" not found', error_on_exit=True)
|
||||
captured = capsys.readouterr()
|
||||
assert "<foo>" in captured.out
|
||||
assert "&" in captured.out
|
||||
|
||||
@patch("codeflash.code_utils.code_utils.is_subagent_mode", return_value=False)
|
||||
@patch("codeflash.code_utils.code_utils.is_LSP_enabled", return_value=False)
|
||||
def test_no_xml_when_not_subagent(
|
||||
self, _mock_lsp: MagicMock, _mock_subagent: MagicMock, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
with pytest.raises(SystemExit):
|
||||
exit_with_message("Normal error", error_on_exit=True)
|
||||
captured = capsys.readouterr()
|
||||
assert "<codeflash-error>" not in captured.out
|
||||
|
|
|
|||
Loading…
Reference in a new issue