Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions packages/claude-code-plugin/hooks/codingbuddy-hud.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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", "")
Expand All @@ -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 "~$"

Expand Down
55 changes: 51 additions & 4 deletions packages/claude-code-plugin/tests/test_hud.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
Loading