"""Renderers for the spawn_agent tool (sub-agent delegation cards)."""
from __future__ import annotations
from rich.box import ROUNDED
from rich.console import RenderableType
from rich.panel import Panel
from rich.text import Text
from clients.terminal.tui.themes import get_active_theme
from .base import ContentRenderer
_SPAWN_TOOL = "spawn_agent"
def _truncate(text: str, limit: int) -> str:
text = (text or "").strip()
if len(text) <= limit:
return text
return text[:limit].rstrip() + " …"
class SpawnAgentStartedRenderer(ContentRenderer):
"""Render the start of a spawn_agent call as a distinct sub-agent card."""
def accepts(self, msg: dict) -> bool:
return msg.get("type") == "tool_started" and msg.get("tool") == _SPAWN_TOOL
def render(self, msg: dict) -> RenderableType:
theme = get_active_theme()
args = msg.get("args") or {}
profile_id = args.get("profile_id") or "default"
task = args.get("task") or ""
briefing = args.get("briefing") or ""
title = f"↘ subagent · {profile_id}"
body = Text(_truncate(task, 240), style=theme.text.hex)
if briefing:
body.append("\n", style=theme.text_dim.hex)
body.append(f"briefing: {_truncate(briefing, 160)}", style=theme.text_dim.hex)
return Panel(
body,
title=title,
title_align="left",
border_style=theme.secondary.hex,
box=ROUNDED,
)
class SpawnAgentResultRenderer(ContentRenderer):
"""Render the result of a spawn_agent call as a distinct sub-agent card."""
def accepts(self, msg: dict) -> bool:
return msg.get("type") == "tool_call" and msg.get("tool") == _SPAWN_TOOL
def render(self, msg: dict) -> RenderableType:
theme = get_active_theme()
args = msg.get("args") or {}
profile_id = args.get("profile_id") or "default"
success = msg.get("success", True)
result = msg.get("result")
color = theme.tool_success if success else theme.tool_error
title = f"↙ subagent · {profile_id} {'✓' if success else '✗'}"
body = Text(_truncate(str(result) if result is not None else "", 600), style=theme.text_dim.hex)
return Panel(
body,
title=title,
title_align="left",
border_style=color.hex,
box=ROUNDED,
)