|
15 | 15 | import sys |
16 | 16 | from datetime import datetime, timezone |
17 | 17 |
|
18 | | -BUDDY_FACE = "\u25d5\u203f\u25d5" # ◕‿◕ |
| 18 | +# --- lib import bootstrap --- |
| 19 | +# statusLine entry script: sys.path insertion here is intentional so |
| 20 | +# lib/* imports work when Claude Code invokes `python codingbuddy-hud.py`. |
| 21 | +_LIB_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lib") |
| 22 | +if _LIB_DIR not in sys.path: |
| 23 | + sys.path.insert(0, _LIB_DIR) |
| 24 | + |
| 25 | +# === test_hud.py compatibility re-exports — DO NOT REMOVE without coordinated test update === |
| 26 | +# Defensive fallback: statusLine is a hot path invoked by Claude Code on |
| 27 | +# every render. If any lib module is temporarily broken (e.g. mid-wave |
| 28 | +# refactor), fall back to minimal inline implementations so the status |
| 29 | +# bar still renders instead of crashing the Claude Code subprocess. |
| 30 | +try: |
| 31 | + from hud_buddy import BUDDY_FACE # canonical SSoT via tiny_actor_presets |
| 32 | +except Exception: # pragma: no cover - defensive |
| 33 | + BUDDY_FACE = "\u25d5\u203f\u25d5" # ◕‿◕ |
| 34 | + |
| 35 | +try: |
| 36 | + from hud_rate_limits import format_rate_limits |
| 37 | +except Exception: # pragma: no cover - defensive |
| 38 | + def format_rate_limits(stdin_data: dict) -> str: # type: ignore[misc] |
| 39 | + return "" |
| 40 | + |
| 41 | +try: |
| 42 | + from hud_version import get_fresh_version as _get_fresh_version # backcompat alias |
| 43 | +except Exception: # pragma: no cover - defensive |
| 44 | + def _get_fresh_version( # type: ignore[misc] |
| 45 | + hud_state: dict, *, plugins_file: str = "" |
| 46 | + ) -> str: |
| 47 | + return hud_state.get("version", "") |
19 | 48 |
|
20 | 49 | # Agent eye glyphs from .ai-rules agent definitions. |
21 | 50 | AGENT_GLYPHS = { |
@@ -303,25 +332,6 @@ def resolve_model_label(stdin_data: dict) -> tuple: |
303 | 332 | return (model_id, display_name) |
304 | 333 |
|
305 | 334 |
|
306 | | -def format_rate_limits(stdin_data: dict) -> str: |
307 | | - """Format rate-limit info if present. Returns '' when absent.""" |
308 | | - rl = stdin_data.get("rate_limits") |
309 | | - if not rl: |
310 | | - return "" |
311 | | - parts = [] |
312 | | - five = rl.get("five_hour") |
313 | | - if five: |
314 | | - pct = five.get("used_percentage", 0) |
315 | | - parts.append(f"5h:{pct:.0f}%") |
316 | | - seven = rl.get("seven_day") |
317 | | - if seven: |
318 | | - pct = seven.get("used_percentage", 0) |
319 | | - parts.append(f"7d:{pct:.0f}%") |
320 | | - if not parts: |
321 | | - return "" |
322 | | - return "RL:" + ",".join(parts) |
323 | | - |
324 | | - |
325 | 335 | def format_worktree(stdin_data: dict) -> str: |
326 | 336 | """Format worktree name if present. Returns '' when absent.""" |
327 | 337 | wt = stdin_data.get("worktree") |
@@ -395,28 +405,6 @@ def format_badge_line(agent: str, focus: str, blocker_count) -> str: |
395 | 405 | return " ".join(badges) |
396 | 406 |
|
397 | 407 |
|
398 | | -def _get_fresh_version(hud_state: dict, *, plugins_file: str = "") -> str: |
399 | | - """Return the most current plugin version. |
400 | | -
|
401 | | - Prefers installed_plugins.json (authoritative after updates) |
402 | | - over the hud-state snapshot written at session start. |
403 | | - Pass *plugins_file* explicitly for testing. |
404 | | - """ |
405 | | - try: |
406 | | - lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lib") |
407 | | - if lib_dir not in sys.path: |
408 | | - sys.path.insert(0, lib_dir) |
409 | | - from hud_helpers import read_installed_version |
410 | | - |
411 | | - kwargs = {"plugins_file": plugins_file} if plugins_file else {} |
412 | | - fresh = read_installed_version(**kwargs) |
413 | | - if fresh: |
414 | | - return fresh |
415 | | - except Exception: |
416 | | - pass |
417 | | - return hud_state.get("version", "") |
418 | | - |
419 | | - |
420 | 408 | def format_status_line( |
421 | 409 | stdin_data: dict, |
422 | 410 | hud_state: dict, |
|
0 commit comments