from __future__ import annotations from datetime import datetime from typing import Any from core.quote_state_machine import QuoteStateMachine def refresh_quote_phase(state: Any, phase_hint: str = "") -> None: """统一维护收图报价状态机。""" QuoteStateMachine().refresh(state, phase_hint=phase_hint) def sync_pending_quote_state(agent: Any, customer_id: str, state: Any) -> None: """把待报价队列同步到客户库,避免重启丢失。""" try: refresh_quote_phase(state) from db.customer_db import db db.update_pending_quote_state( customer_id, state.pending_image_urls, state.pending_requirements, ) except Exception: pass def restore_pending_quote_state(customer_id: str, state: Any) -> None: """从客户库恢复待报价队列。""" try: from db.customer_db import db profile = db.get_customer(customer_id) state.pending_image_urls = list(getattr(profile, "pending_quote_images", []) or []) state.pending_requirements = list(getattr(profile, "pending_quote_requirements", []) or []) state.image_count = len(state.pending_image_urls) refresh_quote_phase(state) except Exception: pass def cleanup_inactive(conversations: dict, message_histories: dict, now: datetime) -> None: """清理超过 7 天没有消息的对话状态,释放内存。""" if len(conversations) % 100 != 0: return expired = [ cid for cid, state in conversations.items() if state.last_update and (now - datetime.fromisoformat(state.last_update)).days > 7 ] for cid in expired: conversations.pop(cid, None) message_histories.pop(cid, None) def get_conversation_state(agent: Any, customer_id: str) -> Any: """获取或创建对话状态,超时自动重置。""" now = datetime.now() if customer_id in agent.conversations: state = agent.conversations[customer_id] if state.last_update: try: last = datetime.fromisoformat(state.last_update) hours = (now - last).total_seconds() / 3600 if hours > agent.CONVERSATION_TIMEOUT_HOURS: state.stage = "售前" state.discount_count = 0 agent.message_histories.pop(customer_id, None) except Exception: pass if not state.pending_image_urls and not state.pending_requirements: restore_pending_quote_state(customer_id, state) else: agent.conversations[customer_id] = agent.ConversationStateClass( customer_id=customer_id, last_update=now.isoformat(), ) restore_pending_quote_state(customer_id, agent.conversations[customer_id]) cleanup_inactive(agent.conversations, agent.message_histories, now) return agent.conversations[customer_id] def should_defer_batch_quote(agent: Any, state: Any, mark_ready: bool = False) -> bool: """批量报价延后控制。""" agent.quote_state_machine.delay_turns = max(0, int(agent.batch_quote_delay_turns)) return agent.quote_state_machine.should_defer_batch_quote(state, mark_ready=mark_ready) def mark_quote_ready(agent: Any, state: Any) -> None: """仅标记 ready 状态,不消费等待轮次。""" agent.quote_state_machine.delay_turns = max(0, int(agent.batch_quote_delay_turns)) agent.quote_state_machine.mark_ready(state)