From 3c859e35dce3df797593a10581983cc86086cb55 Mon Sep 17 00:00:00 2001 From: nosleepcassette Date: Wed, 15 Apr 2026 22:35:59 -0700 Subject: [PATCH] fix: skin spinner faces and verbs not applied at runtime Skins define waiting_faces, thinking_faces, and thinking_verbs in their spinner config, but all 7 call sites in run_agent.py used hardcoded class constants. Add three classmethods on KawaiiSpinner that query the active skin first and fall back to the class constants, matching the existing pattern used for wings/tool_prefix/tool_emojis. Co-authored-by: nosleepcassette --- agent/display.py | 39 +++++++++++++++++++++++++++++++++++++++ run_agent.py | 14 +++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/agent/display.py b/agent/display.py index 063b7bb1c7..a7f3cbaa2d 100644 --- a/agent/display.py +++ b/agent/display.py @@ -600,6 +600,45 @@ class KawaiiSpinner: "analyzing", "computing", "synthesizing", "formulating", "brainstorming", ] + @classmethod + def get_waiting_faces(cls) -> list: + """Return waiting faces from the active skin, falling back to KAWAII_WAITING.""" + try: + skin = _get_skin() + if skin: + faces = skin.spinner.get("waiting_faces", []) + if faces: + return faces + except Exception: + pass + return cls.KAWAII_WAITING + + @classmethod + def get_thinking_faces(cls) -> list: + """Return thinking faces from the active skin, falling back to KAWAII_THINKING.""" + try: + skin = _get_skin() + if skin: + faces = skin.spinner.get("thinking_faces", []) + if faces: + return faces + except Exception: + pass + return cls.KAWAII_THINKING + + @classmethod + def get_thinking_verbs(cls) -> list: + """Return thinking verbs from the active skin, falling back to THINKING_VERBS.""" + try: + skin = _get_skin() + if skin: + verbs = skin.spinner.get("thinking_verbs", []) + if verbs: + return verbs + except Exception: + pass + return cls.THINKING_VERBS + def __init__(self, message: str = "", spinner_type: str = 'dots', print_fn=None): self.message = message self.spinner_frames = self.SPINNERS.get(spinner_type, self.SPINNERS['dots']) diff --git a/run_agent.py b/run_agent.py index ec96ee86eb..2781bf1888 100644 --- a/run_agent.py +++ b/run_agent.py @@ -7490,7 +7490,7 @@ class AIAgent: # Start spinner for CLI mode (skip when TUI handles tool progress) spinner = None if self._should_emit_quiet_tool_messages() and self._should_start_quiet_spinner(): - face = random.choice(KawaiiSpinner.KAWAII_WAITING) + face = random.choice(KawaiiSpinner.get_waiting_faces()) spinner = KawaiiSpinner(f"{face} ⚡ running {num_tools} tools concurrently", spinner_type='dots', print_fn=self._print_fn) spinner.start() @@ -7786,7 +7786,7 @@ class AIAgent: spinner_label = f"🔀 {goal_preview}" if goal_preview else "🔀 delegating" spinner = None if self._should_emit_quiet_tool_messages() and self._should_start_quiet_spinner(): - face = random.choice(KawaiiSpinner.KAWAII_WAITING) + face = random.choice(KawaiiSpinner.get_waiting_faces()) spinner = KawaiiSpinner(f"{face} {spinner_label}", spinner_type='dots', print_fn=self._print_fn) spinner.start() self._delegate_spinner = spinner @@ -7813,7 +7813,7 @@ class AIAgent: # Context engine tools (lcm_grep, lcm_describe, lcm_expand, etc.) spinner = None if self.quiet_mode and not self.tool_progress_callback: - face = random.choice(KawaiiSpinner.KAWAII_WAITING) + face = random.choice(KawaiiSpinner.get_waiting_faces()) emoji = _get_tool_emoji(function_name) preview = _build_tool_preview(function_name, function_args) or function_name spinner = KawaiiSpinner(f"{face} {emoji} {preview}", spinner_type='dots', print_fn=self._print_fn) @@ -7837,7 +7837,7 @@ class AIAgent: # These are not in the tool registry — route through MemoryManager. spinner = None if self._should_emit_quiet_tool_messages() and self._should_start_quiet_spinner(): - face = random.choice(KawaiiSpinner.KAWAII_WAITING) + face = random.choice(KawaiiSpinner.get_waiting_faces()) emoji = _get_tool_emoji(function_name) preview = _build_tool_preview(function_name, function_args) or function_name spinner = KawaiiSpinner(f"{face} {emoji} {preview}", spinner_type='dots', print_fn=self._print_fn) @@ -7859,7 +7859,7 @@ class AIAgent: elif self.quiet_mode: spinner = None if self._should_emit_quiet_tool_messages() and self._should_start_quiet_spinner(): - face = random.choice(KawaiiSpinner.KAWAII_WAITING) + face = random.choice(KawaiiSpinner.get_waiting_faces()) emoji = _get_tool_emoji(function_name) preview = _build_tool_preview(function_name, function_args) or function_name spinner = KawaiiSpinner(f"{face} {emoji} {preview}", spinner_type='dots', print_fn=self._print_fn) @@ -8731,8 +8731,8 @@ class AIAgent: self._vprint(f"{self.log_prefix} 🔧 Available tools: {len(self.tools) if self.tools else 0}") else: # Animated thinking spinner in quiet mode - face = random.choice(KawaiiSpinner.KAWAII_THINKING) - verb = random.choice(KawaiiSpinner.THINKING_VERBS) + face = random.choice(KawaiiSpinner.get_thinking_faces()) + verb = random.choice(KawaiiSpinner.get_thinking_verbs()) if self.thinking_callback: # CLI TUI mode: use prompt_toolkit widget instead of raw spinner # (works in both streaming and non-streaming modes)