from __future__ import annotations from typing import Any, Optional import re def _normalize_token(value: Any) -> str: text = re.sub(r"\s+", "", str(value or "").strip()) return text[:128] def extract_thread_anchor(thread_context: Optional[dict[str, Any]] = None) -> str: if not isinstance(thread_context, dict): return "" for key in ("root_message_id", "thread_id", "reply_to_message_id"): value = _normalize_token(thread_context.get(key)) if value: return value return "" def build_feishu_thread_key( *, source_chat_id: Optional[str], source_sender_open_id: Optional[str], sender: Optional[str], source_message_id: Optional[str] = None, thread_context: Optional[dict[str, Any]] = None, ) -> str: chat = _normalize_token(source_chat_id) anchor = extract_thread_anchor(thread_context) if anchor: return f"feishu:{chat}:{anchor}" if chat else f"feishu:{anchor}" message_id = _normalize_token(source_message_id) if message_id: return f"feishu:{chat}:{message_id}" if chat else f"feishu:{message_id}" actor = _normalize_token(source_sender_open_id) if not actor: actor = _normalize_token(sender).lower() if actor: return f"feishu:{chat}:{actor}" if chat else f"feishu:{actor}" return ""