from __future__ import annotations from typing import Any, Dict from ..core.reply_formatter import preview_text def build_log_summary(event: str, data: Dict[str, Any]) -> str: room = short_id(data.get("room_id", "")) sender_name = data.get("sender_name", "") or short_id(data.get("sender", "")) sender = short_id(data.get("sender", "")) if event == "recv": return ( f"[XIAONIU] RECV room={room} user={sender_name}/{sender} " f"at={yn(data.get('is_at'))} " f"style={style_mark(data.get('humor_style', ''), data.get('sharpness_style', ''))} " f"quote={data.get('quote_type', '-') or '-'} " f"msg={data.get('content_preview', '')}" ).strip() if event == "memory": return ( f"[XIAONIU] MEMORY room={room} user={sender} " f"ctx={yn(data.get('has_member_context'))} " f"follow={yn(data.get('is_followup'))} " f"return={data.get('returning_state', 'none')} " f"links={data.get('social_links', 0)} " f"facts={data.get('group_facts', 0)}" ).strip() if event == "decision": return ( f"[XIAONIU] DECIDE room={room} user={sender} " f"trigger={data.get('trigger_type', 'none')} " f"dir={data.get('directed', '-') or '-'} " f"flow={data.get('flow_state', '')}:{data.get('flow_score', '')} " f"topic={data.get('topic', '-') or '-'} " f"reasons={data.get('reasons', '-') or '-'}" ).strip() if event == "skip": age_text = "" if data.get("age_sec") not in (None, ""): age_text = f" age={data.get('age_sec')}" return ( f"[XIAONIU] SKIP room={room} user={sender} " f"reason={data.get('reason', '')} " f"trigger={data.get('trigger_type', 'none')} " f"mode={data.get('reply_mode', '')} " f"topic={data.get('topic', '-') or '-'} " f"acc={data.get('acceptance_state', '-') or '-'} " f"solver={data.get('solver', '-') or '-'}" f"{age_text}" ).strip() if event == "context": return ( f"[XIAONIU] CTX room={room} user={sender} " f"mode={data.get('reply_mode', '')} " f"acc={data.get('acceptance_state', '-') or '-'} " f"recent={data.get('recent_message_count', 0)} " f"vector={data.get('vector_hit_count', 0)} " f"mem={data.get('member_focus_count', 0)} " f"social={data.get('social_hit_count', 0)} " f"facts={data.get('group_fact_hit_count', 0)} " f"img={data.get('image_input_count', 0)} " f"rank={preview_text(str(data.get('memory_rank_summary', '') or '-'), 108)}" ).strip() if event == "model_empty": return ( f"[XIAONIU] MODEL_EMPTY room={room} user={sender} " f"model={data.get('model', '')} " f"mode={data.get('reply_mode', '')} " f"err={data.get('last_error', '')}" ).strip() if event == "sent": return ( f"[XIAONIU] SENT room={room} user={sender_name}/{sender} " f"trigger={data.get('trigger_type', 'none')} " f"mode={data.get('reply_mode', '')} " f"topic={data.get('topic', '-') or '-'} " f"chunks={data.get('chunk_count', 1)} " f"len={data.get('response_len', 0)} " f"reply={data.get('response_preview', '')}" ).strip() if event == "memory_upsert": return ( f"[XIAONIU] MEM_UPSERT room={room} user={sender} " f"type={data.get('memory_type', '')} " f"ok={yn(data.get('ok'))} " f"trigger={data.get('trigger_type', '-') or '-'} " f"err={preview_text(str(data.get('error', '') or '-'), 72)}" ).strip() compact = " ".join(f"{key}={data[key]}" for key in sorted(data) if data.get(key) not in (None, "")) return f"[XIAONIU] {event.upper()} {compact}".strip() def yn(value: Any) -> str: return "Y" if bool(value) else "N" def short_id(value: str) -> str: value = str(value or "") if len(value) <= 10: return value return value[:4] + "..." + value[-4:] def style_mark(humor_style: str, sharpness_style: str) -> str: humor = "humor" if "中等" in str(humor_style) or "偏上" in str(humor_style) else "plain" sharp = "sharp" if "毒舌" in str(sharpness_style) or "嘴欠" in str(sharpness_style) else "soft" return f"{humor}/{sharp}"