""" 意图:海运协同群里补协同字段。 本文件职责:群聊文字 → 只抽协同六字段 → 静默写主账。 禁止:回「已记下」;把闲聊/报价金额写成报价版本;改工单六态。 """ from __future__ import annotations import logging from agent.channel.wecom.models import InboundMessage from agent.llm.extract_text import extract_collab_fields from agent.policy.sea_text_flow import get_sea_text_flow from agent.schema.field_validate import SEA_COLLAB_FIELDS logger = logging.getLogger(__name__) def handle_group_collab( message: InboundMessage, *, flow=None, ledger=None, ) -> str: """ 处理一条群聊文字。 必须能对上已绑定工单,且发言人是被拉进来的销售或产品。 识别到协同字段才写库;否则忽略。不回复。 """ if (message.chat_type or "") != "group": return "group_ignore" if not message.has_sender(): return "reject_no_sender" engine = flow or get_sea_text_flow() book = ledger or engine.ledger chat_id = (message.chat_id or "").strip() if not chat_id: return "group_ignore" ticket = _find_ticket(book, chat_id) if ticket is None: return "group_ignore" if not _sender_allowed(ticket, message.sender_id): logger.info("group_collab 忽略非成员 sender=%s chat=%s", message.sender_id, chat_id) return "group_ignore" facts = extract_collab_fields(message.content or "") if not facts: return "group_ignore" if isinstance(ticket, dict): wo = str(ticket.get("work_order_no") or "") else: wo = str(getattr(ticket, "work_order_no", "") or "") if not wo: return "group_ignore" engine.apply_collab_facts( work_order_no=wo, facts=facts, sender_id=message.sender_id, ) logger.info( "group_collab 写入 wo=%s keys=%s sender=%s", wo, sorted(k for k in facts if k in SEA_COLLAB_FIELDS), message.sender_id, ) return "collab_field_saved" def _find_ticket(book: object, chat_id: str): finder = getattr(book, "find_by_collab_chat", None) if callable(finder): return finder(chat_id=chat_id) return None def _sender_allowed(ticket: object, sender_id: str) -> bool: uid = (sender_id or "").strip() if not uid: return False if isinstance(ticket, dict): sales = str(ticket.get("sales_wecom_id") or ticket.get("salesWecomId") or "") members = ticket.get("collab_member_ids") or ticket.get("memberIds") or [] else: sales = str(getattr(ticket, "sales_wecom_id", "") or "") members = list(getattr(ticket, "collab_member_ids", []) or []) if uid == sales: return True return uid in {str(x) for x in members}