PMFlow/backend/app/services/feishu_integration_service/mixin_receive_routing.py

160 lines
6.1 KiB
Python

from __future__ import annotations
from .shared import *
class FeishuReceiveRoutingMixin:
async def _route_scene_reply(
self,
*,
scene: str,
result: Dict[str, Any],
message_content: str,
chat_id: str,
sender_open_id: Optional[str],
sender_name: str,
mentioned_bot_names: List[str],
trace_id: str,
message_id: str,
perf_t0: Optional[float],
) -> str:
reply_route = "none"
capability_reply = self._build_capability_reply(message_content)
if scene == "execute":
if self._is_duplicate_capture_result(result):
self._emit_state_transition(
trace_id=trace_id,
state="ROUTED",
route="duplicate_suppressed",
)
return reply_route
self._emit_state_transition(
trace_id=trace_id,
state="ROUTED",
route="tool_first_execute",
)
deterministic_reply = capability_reply or str(result.get("direct_reply_text") or "").strip()
if not deterministic_reply:
deterministic_reply = self._build_execution_receipt_reply(
message_content=message_content,
capture_result=result,
)
deterministic_reply, guard_reason = self._guard_execute_reply_text_with_reason(
deterministic_reply,
trace_id=trace_id,
)
if guard_reason:
asyncio.create_task(
self._record_execute_guard_alert(
trace_id=trace_id,
message_id=message_id,
message_content=message_content,
capture_result=result,
guard_reason=guard_reason,
)
)
if not deterministic_reply and str(result.get("status") or "").lower() == "error":
deterministic_reply = self._build_error_reply_text()
if chat_id and deterministic_reply:
await self._safe_reply_text(
chat_id=chat_id,
mention_open_id=sender_open_id,
mention_name=sender_name,
text=deterministic_reply,
trace_id=trace_id,
source_message_id=message_id,
perf_t0=perf_t0,
)
return "execute_template"
return reply_route
if scene == "qa":
self._emit_state_transition(
trace_id=trace_id,
state="ROUTED",
route="qa_consult",
)
if chat_id and capability_reply:
await self._safe_reply_text(
chat_id=chat_id,
mention_open_id=sender_open_id,
mention_name=sender_name,
text=capability_reply,
trace_id=trace_id,
source_message_id=message_id,
perf_t0=perf_t0,
)
return "qa_capability"
if chat_id and bool(result.get("direct_reply_required")):
await self._safe_reply_text(
chat_id=chat_id,
mention_open_id=sender_open_id,
mention_name=sender_name,
text=str(result.get("direct_reply_text") or "已收到,正在处理。"),
trace_id=trace_id,
source_message_id=message_id,
perf_t0=perf_t0,
)
return "qa_direct"
if chat_id and self._should_reply_to_mention(
mentioned_bot_names=mentioned_bot_names,
message_content=message_content,
):
await self._reply_with_active_role_prompt(
chat_id=chat_id,
sender_open_id=sender_open_id,
sender_name=sender_name,
message_content=message_content,
capture_result=result,
trace_id=trace_id,
source_message_id=message_id,
perf_t0=perf_t0,
)
return "qa_llm"
return reply_route
self._emit_state_transition(
trace_id=trace_id,
state="ERROR_REPLY",
reason="scene_error",
capture_status=str(result.get("status") or "unknown"),
)
if chat_id:
await self._safe_reply_text(
chat_id=chat_id,
mention_open_id=sender_open_id,
mention_name=sender_name,
text=self._build_error_reply_text(),
trace_id=trace_id,
source_message_id=message_id,
perf_t0=perf_t0,
)
return "error_template"
return reply_route
@staticmethod
def _classify_message_scene(*, capture_result: Dict[str, Any]) -> str:
if not isinstance(capture_result, dict):
return "error"
status = str(capture_result.get("status") or "").strip().lower()
classification = str(capture_result.get("classification") or "").strip().lower()
if status in {"captured", "ignored"}:
return "execute"
if status == "answered" or classification in {"question", "qa"}:
return "qa"
if status == "error" or classification == "error":
return "error"
return "qa"
@staticmethod
def _build_error_reply_text() -> str:
return "系统处理中出现异常,本次未执行。请稍后重试,或补充更明确的目标、对象和动作。"
@staticmethod
def _emit_state_transition(trace_id: str, state: str, **payload: Any) -> None:
safe_trace = str(trace_id or "unknown")
safe_state = str(state or "unknown")
details = ", ".join([f"{k}={v}" for k, v in payload.items()]) if payload else ""
print(f"[Feishu-SM][{safe_trace}] state={safe_state}{', ' + details if details else ''}")