Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/claude_monitor/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ def normalize_model_name(model: str) -> str:
if "3.5" in model_lower or "3-5" in model_lower:
return "claude-3-5-haiku"
return "claude-3-haiku"
if "fable" in model_lower:
return model_lower

return model

Expand Down
3 changes: 3 additions & 0 deletions src/claude_monitor/ui/progress_bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ class ModelUsageBar(BaseProgressBar):
_FAMILY_STYLES: Final[dict[str, str]] = {
"Sonnet": "info",
"Opus": "warning",
"Fable": "highlight",
"Haiku": "success",
"Other": "dim",
}
Expand All @@ -279,6 +280,8 @@ def _family_for(model_name: str) -> str:
return "Sonnet"
if "opus" in name:
return "Opus"
if "fable" in name:
return "Fable"
if "haiku" in name:
return "Haiku"
return "Other"
Expand Down
4 changes: 4 additions & 0 deletions src/tests/test_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ def test_normalize_model_name(self) -> None:
assert normalize_model_name("Claude 3.5 Sonnet") == "claude-3-5-sonnet"
assert normalize_model_name("claude-3-5-haiku") == "claude-3-5-haiku"

# Test Claude 5 models
assert normalize_model_name("claude-fable-5") == "claude-fable-5"
assert normalize_model_name("Claude-Fable-5") == "claude-fable-5"

# Test empty/None inputs
assert normalize_model_name("") == ""
assert normalize_model_name(None) == ""
Expand Down
14 changes: 14 additions & 0 deletions src/tests/test_progress_bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ def test_render_lists_every_present_family() -> None:
assert family in out


def test_render_fable_family_recognized_not_other() -> None:
"""Fable 5 usage shows under its own family name, not as 'Other'."""
bar = ModelUsageBar(width=50)
out = bar.render(
{
"claude-fable-5": _tokens(70),
"claude-sonnet-4-5": _tokens(30),
}
)
assert "Fable" in out and "70.0%" in out
assert "Sonnet" in out and "30.0%" in out
assert "Other" not in out


def test_render_unknown_family_shown_as_other_not_dropped() -> None:
"""An unmapped family still appears (as 'Other'); its share is not silently lost."""
bar = ModelUsageBar(width=50)
Expand Down