From e549708ad59ade5e38c20678fb3433f74faea997 Mon Sep 17 00:00:00 2001 From: JeremyDev87 Date: Sun, 5 Apr 2026 00:39:09 +0900 Subject: [PATCH] fix(plugin): make status bar actor badge fall back to hud_state.activeAgent (#1333) --- .../hooks/codingbuddy-hud.py | 15 +++-- packages/claude-code-plugin/tests/test_hud.py | 55 +++++++++++++++++-- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/packages/claude-code-plugin/hooks/codingbuddy-hud.py b/packages/claude-code-plugin/hooks/codingbuddy-hud.py index f546e61f..979a56de 100644 --- a/packages/claude-code-plugin/hooks/codingbuddy-hud.py +++ b/packages/claude-code-plugin/hooks/codingbuddy-hud.py @@ -7,7 +7,7 @@ Telemetry fallback order per field: cost → stdin cost.total_cost_usd > estimate_cost() duration → stdin cost.total_duration_ms > hud-state sessionStartTimestamp - agent → stdin agent.name > CODINGBUDDY_ACTIVE_AGENT env + agent → stdin agent.name > hud_state.activeAgent > CODINGBUDDY_ACTIVE_AGENT env model → stdin model.display_name > model.id """ import json @@ -220,10 +220,13 @@ def resolve_duration(stdin_data: dict, hud_state: dict) -> str: return "0m" -def resolve_agent(stdin_data: dict, env_agent: str = "") -> str: - """Resolve agent: stdin > env var.""" +def resolve_agent(stdin_data: dict, hud_state=None, env_agent: str = "") -> str: + """Resolve agent: stdin > hud_state.activeAgent > env var.""" stdin_agent = (stdin_data.get("agent") or {}).get("name", "") - return stdin_agent or env_agent + if stdin_agent: + return stdin_agent + hud_agent = (hud_state or {}).get("activeAgent", "") + return hud_agent or env_agent def resolve_model_label(stdin_data: dict) -> tuple: @@ -336,7 +339,7 @@ def format_status_line( Fallback order per field: cost → stdin cost.total_cost_usd > estimate_cost() duration → stdin cost.total_duration_ms > hud-state sessionStartTimestamp - agent → stdin agent.name > active_agent param + agent → stdin agent.name > hud_state.activeAgent > active_agent param model → stdin model.display_name > model.id """ version = hud_state.get("version", "") @@ -351,7 +354,7 @@ def format_status_line( cost, is_exact = resolve_cost(stdin_data, model_id, ctx_window) duration = resolve_duration(stdin_data, hud_state) cache = compute_cache_hit_rate(ctx_window) - agent = resolve_agent(stdin_data, active_agent) + agent = resolve_agent(stdin_data, hud_state, active_agent) cost_prefix = "$" if is_exact else "~$" diff --git a/packages/claude-code-plugin/tests/test_hud.py b/packages/claude-code-plugin/tests/test_hud.py index df54e604..8f43cf6c 100644 --- a/packages/claude-code-plugin/tests/test_hud.py +++ b/packages/claude-code-plugin/tests/test_hud.py @@ -229,13 +229,34 @@ def test_no_data_returns_zero(self): class TestResolveAgent: def test_stdin_agent_preferred(self): stdin = {"agent": {"name": "security-reviewer"}} - assert hud.resolve_agent(stdin, "old-env-agent") == "security-reviewer" + assert hud.resolve_agent(stdin, env_agent="old-env-agent") == "security-reviewer" + + def test_stdin_overrides_hud_state(self): + stdin = {"agent": {"name": "security-reviewer"}} + state = {"activeAgent": "plan-mode"} + assert hud.resolve_agent(stdin, state, "env-agent") == "security-reviewer" + + def test_hud_state_fallback(self): + assert hud.resolve_agent({}, {"activeAgent": "security-specialist"}) == "security-specialist" + + def test_hud_state_overrides_env(self): + state = {"activeAgent": "security-specialist"} + assert hud.resolve_agent({}, state, "env-agent") == "security-specialist" def test_fallback_to_env(self): - assert hud.resolve_agent({}, "env-agent") == "env-agent" + assert hud.resolve_agent({}, env_agent="env-agent") == "env-agent" + + def test_env_when_hud_state_empty(self): + assert hud.resolve_agent({}, {"activeAgent": ""}, "env-agent") == "env-agent" + + def test_env_when_hud_state_none(self): + assert hud.resolve_agent({}, None, "env-agent") == "env-agent" - def test_both_empty(self): - assert hud.resolve_agent({}, "") == "" + def test_all_empty(self): + assert hud.resolve_agent({}, {}, "") == "" + + def test_both_empty_no_hud(self): + assert hud.resolve_agent({}, None, "") == "" class TestResolveModelLabel: @@ -359,6 +380,32 @@ def test_stdin_agent_overrides_env_badge(self): assert "[\u2605 fron]" in result # [★ fron] assert "\u25d0" not in result # ◐ (backend glyph) absent + def test_hud_state_agent_fallback_badge(self): + result = hud.format_status_line( + {}, + {"activeAgent": "security-specialist", "focus": "auth", "blockerCount": 1}, + ) + lines = result.strip().split("\n") + assert len(lines) == 2 + assert "[\u25ee secu]" in lines[1] # [◮ secu] + assert "[auth]" in lines[1] + assert "[\u26a01]" in lines[1] # [⚠1] + + def test_stdin_agent_overrides_hud_state(self): + stdin = {"agent": {"name": "frontend-developer"}} + state = {"activeAgent": "security-specialist"} + result = hud.format_status_line(stdin, state) + assert "[\u2605 fron]" in result # [★ fron] + assert "\u25ee" not in result # ◮ (security glyph) absent + + def test_hud_state_agent_overrides_env(self): + state = {"activeAgent": "security-specialist"} + result = hud.format_status_line({}, state, active_agent="backend-developer") + lines = result.strip().split("\n") + assert len(lines) == 2 + assert "[\u25ee secu]" in lines[1] # [◮ secu] from hud_state + assert "\u25d0" not in result # ◐ (backend glyph) absent + def test_no_agent_single_line(self): result = hud.format_status_line({}, {"version": "5.1.1"}) assert "\n" not in result