diff --git a/elixir/lib/symphony_elixir/status_dashboard.ex b/elixir/lib/symphony_elixir/status_dashboard.ex index 33f0e558..9e5c4350 100644 --- a/elixir/lib/symphony_elixir/status_dashboard.ex +++ b/elixir/lib/symphony_elixir/status_dashboard.ex @@ -1174,6 +1174,7 @@ defmodule SymphonyElixir.StatusDashboard do payload |> inspect(pretty: true, limit: 30) |> String.replace("\n", " ") + |> sanitize_ansi_and_control_bytes() |> String.trim() end end @@ -1182,6 +1183,7 @@ defmodule SymphonyElixir.StatusDashboard do defp humanize_codex_payload(payload) when is_binary(payload) do payload |> String.replace("\n", " ") + |> sanitize_ansi_and_control_bytes() |> String.trim() end @@ -1189,9 +1191,17 @@ defmodule SymphonyElixir.StatusDashboard do payload |> inspect(pretty: true, limit: 20) |> String.replace("\n", " ") + |> sanitize_ansi_and_control_bytes() |> String.trim() end + defp sanitize_ansi_and_control_bytes(value) when is_binary(value) do + value + |> String.replace(~r/\x1B\[[0-9;]*[A-Za-z]/, "") + |> String.replace(~r/\x1B./, "") + |> String.replace(~r/[\x00-\x1F\x7F]/, "") + end + defp humanize_codex_method("thread/started", payload) do thread_id = map_path(payload, ["params", "thread", "id"]) || map_path(payload, [:params, :thread, :id]) diff --git a/elixir/test/symphony_elixir/orchestrator_status_test.exs b/elixir/test/symphony_elixir/orchestrator_status_test.exs index 886a4cc9..14c3e1bb 100644 --- a/elixir/test/symphony_elixir/orchestrator_status_test.exs +++ b/elixir/test/symphony_elixir/orchestrator_status_test.exs @@ -1296,6 +1296,35 @@ defmodule SymphonyElixir.OrchestratorStatusTest do refute plain =~ " notification " end + test "status dashboard strips ANSI and control bytes from last codex message" do + payload = + "cmd: " <> + <<27>> <> + "[31mRED" <> + <<27>> <> + "[0m" <> + <<0>> <> + " after\nline" + + row = + StatusDashboard.format_running_summary_for_test(%{ + identifier: "MT-898", + state: "running", + session_id: "thread-1234567890", + codex_app_server_pid: "4242", + codex_total_tokens: 12, + runtime_seconds: 15, + last_codex_event: :notification, + last_codex_message: payload + }) + + plain = Regex.replace(~r/\e\[[0-9;]*m/, row, "") + + assert plain =~ "cmd: RED after line" + refute plain =~ <<27>> + refute plain =~ <<0>> + end + test "status dashboard expands running row to requested terminal width" do terminal_columns = 140