from __future__ import annotations from typing import Any from agent_framework.presentation import register_tool_response_renderer def _money_brl(value: Any) -> str: try: return f"{float(value):.2f}".replace(".", ",") except (TypeError, ValueError): return str(value) def render_contas_plan( *, tool_name: str, result: dict[str, Any], state: dict[str, Any], agent_label: str ) -> str | None: plans = result.get("plans") if not isinstance(plans, list) or not plans: return None lines: list[str] = [] for plan in plans: if not isinstance(plan, dict): continue name = plan.get("name") if not name: continue value = plan.get("value") line = f"- {name}" if value is not None: line += f": R$ {_money_brl(value)}" lines.append(line) if not lines: return None if len(lines) == 1: return f"[{agent_label}] Seu plano é:\n{lines[0]}" return f"[{agent_label}] Existem {len(lines)} planos associados à sua conta:\n" + "\n".join(lines) def _service_value(service: dict[str, Any]) -> Any: details = service.get("details") if isinstance(service.get("details"), dict) else {} for candidate in ( details.get("valor"), details.get("value"), service.get("valor"), service.get("value"), service.get("price"), ): if candidate not in (None, ""): return candidate return None def _money_brl_preserve(value: Any) -> str: if value is None: return "" text = str(value).strip() if not text: return "" # TIM APIs may already return BRL decimal strings such as "10,00". # Normalize only when needed and never invent a value. if "," in text and "." not in text: try: return f"{float(text.replace(',', '.')):.2f}".replace(".", ",") except ValueError: return text return _money_brl(value) def render_contas_vas( *, tool_name: str, result: dict[str, Any], state: dict[str, Any], agent_label: str ) -> str | None: services = result.get("products") or result.get("services") if not isinstance(services, list) or not services: return None lines: list[str] = [] for service in services: if not isinstance(service, dict): continue name = service.get("name") or service.get("description") or service.get("billDescription") if not name: continue details = service.get("details") if isinstance(service.get("details"), dict) else {} can = service.get("can") if isinstance(service.get("can"), dict) else {} details_can = details.get("can") if isinstance(details.get("can"), dict) else {} cancelable = bool(can.get("cancel", details_can.get("cancel", False))) category = service.get("classe") or details.get("classe") or ("avulso" if cancelable else None) value = _service_value(service) line = f"- {name}" if category: line += f" ({category})" if value not in (None, ""): line += f": R$ {_money_brl_preserve(value)}" lines.append(line) if not lines: return None return f"[{agent_label}] Você possui os seguintes serviços ativos:\n" + "\n".join(lines) def register_tool_renderers() -> None: register_tool_response_renderer("contas.plan", render_contas_plan) register_tool_response_renderer("contas.vas", render_contas_vas)