from __future__ import annotations from .shared import * class FeishuTraceMixin: async def _record_ingress_trace( self, *, ingress_source: str, trace_id: str, message_id: str, event: Dict[str, Any], message_content: str, ) -> None: try: message = event.get("message", {}) if isinstance(event.get("message", {}), dict) else {} chat = event.get("chat", {}) if isinstance(event.get("chat", {}), dict) else {} sender = event.get("sender", {}) if isinstance(event.get("sender", {}), dict) else {} sender_id = sender.get("sender_id", {}) if isinstance(sender.get("sender_id", {}), dict) else {} sender_name = ( str(sender.get("sender_name") or sender.get("name") or "").strip() or str(sender_id.get("open_id") or "").strip() or "unknown" ) chat_id = str(chat.get("chat_id") or message.get("chat_id") or "").strip() or None chat_type = str(chat.get("chat_type") or message.get("chat_type") or "").strip() or None async with AsyncSessionLocal() as db: db.add( AIProcessingLog( tenant_id=int(self.tenant_id or 1), feishu_message_id=(message_id or "")[:128] or None, feishu_item_id=None, raw_message=(message_content or "")[:8000] or None, ai_raw_output=json.dumps( { "trace_id": trace_id, "ingress_source": ingress_source, "event_type": str(event.get("type") or "")[:120], "chat_id": chat_id, "chat_type": chat_type, "sender_name": sender_name[:200], }, ensure_ascii=False, )[:120000], project_score=None, signal_confidence=None, level="ingress", normalized_text=(message_content or "")[:8000] or None, route=ingress_source[:80], intent=None, executor="feishu_ingress", operation_code=None, operation_result={ "message_type": str(message.get("message_type") or "")[:80], "chat_id": chat_id, "chat_type": chat_type, "sender_name": sender_name[:200], }, reply_source=None, routing_decision="event_received", routing_reason=f"Feishu ingress via {ingress_source}", reasoning_bullets=[ f"trace_id={trace_id}", f"message_id={message_id}", f"source={ingress_source}", ], processing_status="success", error_message=None, duration_ms=0, ) ) await db.commit() except Exception as exc: print(f"[Feishu] ingress trace write failed: trace_id={trace_id}, error={exc}") async def _record_message_trace( self, *, trace_id: str, message_id: str, chat_type: str, message_content: str, capture_result: Dict[str, Any], reply_source: str, ) -> None: try: async with AsyncSessionLocal() as db: db.add( AIProcessingLog( tenant_id=int(self.tenant_id or 1), feishu_message_id=(message_id or "")[:128] or None, feishu_item_id=None, raw_message=(str(capture_result.get("normalized_text") or message_content) or "")[:8000] or None, ai_raw_output=json.dumps( { "trace_id": trace_id, "chat_type": chat_type, "normalized_text": str(capture_result.get("normalized_text") or message_content)[:2000], "route": capture_result.get("route"), "db_mutations": capture_result.get("db_mutations") or [], "reply_source": reply_source or "none", "reply_text": str(capture_result.get("direct_reply_text") or "")[:500], }, ensure_ascii=False, )[:120000], project_score=None, signal_confidence=None, level="reply_trace", routing_decision=str(capture_result.get("route") or "reply_trace")[:64], routing_reason="飞书消息 reply trace", reasoning_bullets=[ f"chat_type={chat_type}", f"reply_source={reply_source or 'none'}", f"trace_id={trace_id}", ], processing_status="success", error_message=None, duration_ms=0, ) ) await db.commit() except Exception as exc: print(f"[Feishu] message trace write failed: trace_id={trace_id}, error={exc}")