"""Renderers for planning events (planning_status, plan_ready)."""
from __future__ import annotations
from rich.box import ROUNDED
from rich.console import RenderableType
from rich.markdown import Markdown
from rich.panel import Panel
from rich.text import Text
from clients.terminal.tui.themes import get_active_theme
from .base import ContentRenderer
from .markdown_content import ThemedMarkdownRenderable, _theme_aware_code_theme
class PlanningStatusRenderer(ContentRenderer):
"""Render a planning-phase progress line.
Non-subagent planning is a transient indicator that rolls through phases
(Analysis → Execution plan → Plan review) in one line; subagent planning is
shown dimmed so it does not bleed into the parent turn's indicator.
"""
def accepts(self, msg: dict) -> bool:
return msg.get("type") == "planning_status"
def render(self, msg: dict) -> RenderableType:
theme = get_active_theme()
label = msg.get("label", "") or "planning…"
is_subagent = bool(msg.get("is_subagent", False))
prefix = "(subagent) " if is_subagent else ""
color = theme.text_dim if is_subagent else theme.info
return Text(f"{prefix}⚙ Planning · {label}", style=color.hex)
class PlanReadyRenderer(ContentRenderer):
"""Render the finalized plan as a card.
The plan text is markdown (## Plan, **Task:**, **Steps:** …) and is rendered
with the themed Markdown renderer inside a panel. Subagent plans use a dim
border so they read as nested context, not the main turn's plan.
"""
def accepts(self, msg: dict) -> bool:
return msg.get("type") == "plan_ready"
def render(self, msg: dict) -> RenderableType:
theme = get_active_theme()
plan = msg.get("plan", "") or ""
is_subagent = bool(msg.get("is_subagent", False))
code_theme = _theme_aware_code_theme(theme.name)
body = ThemedMarkdownRenderable(
Markdown(plan, code_theme=code_theme, inline_code_theme=code_theme),
theme.name,
)
title = "subagent plan" if is_subagent else "Plan"
border = theme.text_dim if is_subagent else theme.accent
return Panel(
body,
title=title,
title_align="left",
border_style=border.hex,
box=ROUNDED,
)