- stock-lab /news/summarize 응답에 top 8 기사(title/link/press) 포함 - agent-office stock.py: _build_briefing_body() 헬퍼 분리 — LLM 요약 + 📰 주요 뉴스 섹션(HTML <a> 링크). 향후 본문 고도화 시 이 함수만 수정 - telegram 포맷터/메시징에 body_is_html 플래그 추가 (링크 포함 메시지는 이중 escape 회피) - 아내 전송도 동일 본문 재사용 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
"""에이전트 메시지 포맷팅."""
|
||
from html import escape as _h
|
||
from typing import Literal, Optional
|
||
|
||
from .agent_registry import get_agent_meta
|
||
|
||
MessageKind = Literal["report", "alert", "approval", "error", "info"]
|
||
|
||
KIND_ICONS = {
|
||
"report": "📊",
|
||
"alert": "🔔",
|
||
"approval": "✋",
|
||
"error": "⚠️",
|
||
"info": "ℹ️",
|
||
}
|
||
|
||
|
||
def format_agent_message(
|
||
agent_id: str,
|
||
kind: MessageKind,
|
||
title: str,
|
||
body: str,
|
||
metadata: Optional[dict] = None,
|
||
body_is_html: bool = False,
|
||
) -> str:
|
||
meta = get_agent_meta(agent_id)
|
||
icon = KIND_ICONS.get(kind, "")
|
||
header = f"{icon} <b>[{_h(meta['emoji'])} {_h(meta['display_name'])}]</b> {_h(title)}"
|
||
|
||
# Telegram 단일 메시지 4096자 제한 대응 (헤더/푸터 여유 512자 확보)
|
||
# body_is_html=True 면 호출자가 이미 HTML-safe하게 구성한 것으로 간주 (예: <a> 링크 포함)
|
||
safe_body = body if body_is_html else _h(body)
|
||
if len(safe_body) > 3500:
|
||
safe_body = safe_body[:3500] + "\n…(생략)"
|
||
|
||
lines = [header, "━" * 20, safe_body]
|
||
|
||
if metadata:
|
||
footer_parts = []
|
||
if "tokens" in metadata:
|
||
footer_parts.append(f"🧮 {metadata['tokens']:,} tokens")
|
||
if "duration_ms" in metadata:
|
||
seconds = metadata["duration_ms"] / 1000
|
||
footer_parts.append(f"⏱ {seconds:.1f}s")
|
||
if "model" in metadata:
|
||
footer_parts.append(f"🤖 {metadata['model']}")
|
||
if footer_parts:
|
||
lines.append("")
|
||
lines.append(f"<i>{_h(' · '.join(footer_parts))}</i>")
|
||
|
||
return "\n".join(lines)
|