From d13402e4525e31f12fbe6bc452cb4a8c8003aade Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 01:54:27 +0000 Subject: [PATCH 1/2] Initial plan From 7429a108522e34caf5a30e04aa610d8f0abf5005 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 01:57:05 +0000 Subject: [PATCH 2/2] feat: add separator banners to TOOL USE, AGENT START, and ERROR events - Add `self._magenta` (bright magenta \033[95m]) ANSI color in __init__ - Add TOOL USE separator banner (magenta) to _handle_tool_start - Add AGENT START separator banner (magenta) to _handle_agent_start - Add ERROR separator banner (red) to _handle_error - Reset _active_agent in _handle_tool_start for proper mode transitions - Add tests verifying separator text appears in rendered output Agent-Logs-Url: https://github.com/strands-compose/sdk-python/sessions/fa2d145b-5b66-4434-b1d2-eadf0473f279 Co-authored-by: galuszkm <53984802+galuszkm@users.noreply.github.com> --- src/strands_compose/renderers/ansi.py | 7 ++++++- tests/unit/renderers/test_ansi.py | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/strands_compose/renderers/ansi.py b/src/strands_compose/renderers/ansi.py index fecfd86..bffdd97 100644 --- a/src/strands_compose/renderers/ansi.py +++ b/src/strands_compose/renderers/ansi.py @@ -67,6 +67,7 @@ def __init__( self._green = "\033[32m" if is_tty else "" self._red = "\033[31m" if is_tty else "" self._yellow = "\033[33m" if is_tty else "" + self._magenta = "\033[95m" if is_tty else "" self._reset = "\033[0m" if is_tty else "" if separator_width is not None: @@ -120,16 +121,19 @@ def _handle_agent_start(self, event: StreamEvent) -> None: self._break() self._mode = None self._active_agent = None - self._out.write(f"\n{self._cyan}{self._bold}[{event.agent_name}]{self._reset} starting…\n") + self._out.write(self._separator(event.agent_name, "AGENT START", color=self._magenta)) + self._out.write(f"{self._cyan}{self._bold}[{event.agent_name}]{self._reset} starting…\n") self._out.flush() def _handle_tool_start(self, event: StreamEvent) -> None: self._break() self._mode = None + self._active_agent = None data = event.data label = data.get("tool_label") or data.get("tool_name", "unknown") tool_input = data.get("tool_input", {}) preview = str(tool_input)[:80] + ("…" if len(str(tool_input)) > 80 else "") + self._out.write(self._separator(event.agent_name, "TOOL USE", color=self._magenta)) self._out.write( f" {self._yellow}⚙{self._reset} [{event.agent_name}] -> {label!r}" f" {self._dim}{preview}{self._reset}\n" @@ -164,6 +168,7 @@ def _handle_complete(self, event: StreamEvent) -> None: def _handle_error(self, event: StreamEvent) -> None: self._break() self._mode = None + self._out.write(self._separator(event.agent_name, "ERROR", color=self._red)) msg = event.data.get("message", "unknown error") exc_type = event.data.get("exception_type") if exc_type and msg.startswith(f"{exc_type}: "): diff --git a/tests/unit/renderers/test_ansi.py b/tests/unit/renderers/test_ansi.py index f0962e9..9d8c731 100644 --- a/tests/unit/renderers/test_ansi.py +++ b/tests/unit/renderers/test_ansi.py @@ -66,8 +66,10 @@ def test_agent_start_breaks_token_stream(self) -> None: def test_agent_start(self) -> None: r, buf = self._renderer() r.render(_event(EventType.AGENT_START)) - assert AGENT in buf.getvalue() - assert "starting" in buf.getvalue() + output = buf.getvalue() + assert AGENT in output + assert "starting" in output + assert "AGENT START" in output def test_tool_start(self) -> None: r, buf = self._renderer() @@ -75,6 +77,7 @@ def test_tool_start(self) -> None: output = buf.getvalue() assert "search" in output assert "⚙" in output + assert "TOOL USE" in output def test_tool_end_success(self) -> None: r, buf = self._renderer() @@ -103,6 +106,14 @@ def test_error(self) -> None: assert "ERROR" in output assert "something broke" in output + def test_error_separator_appears_before_detail(self) -> None: + r, buf = self._renderer() + r.render(_event(EventType.ERROR, message="something broke")) + output = buf.getvalue() + separator_idx = output.index("ERROR") + detail_idx = output.index("something broke") + assert separator_idx < detail_idx + def test_node_start(self) -> None: r, buf = self._renderer() r.render(_event(EventType.NODE_START, node_id="n1"))