"""ClientContext middleware — injects client/project background into state.""" from __future__ import annotations import json import logging from pathlib import Path from app.graph.state import ReportState from .base import Middleware logger = logging.getLogger(__name__) # Client profiles stored as JSON files CLIENTS_DIR = Path(__file__).resolve().parent.parent.parent / "clients" class ClientContextMiddleware(Middleware): """Loads client profile and injects background context into state. Client profiles are JSON files in the `clients/` directory: clients/.json { "name": "某咨询公司", "industry": "金融", "preferences": "偏好简洁的执行摘要,数据驱动", "previous_reports": ["report_001", "report_002"] } """ name = "client_context" async def before(self, state: ReportState) -> ReportState: if not state.client_id: return state profile_path = CLIENTS_DIR / f"{state.client_id}.json" if not profile_path.exists(): logger.info(f"[client_context] no profile for client '{state.client_id}'") return state try: profile = json.loads(profile_path.read_text(encoding="utf-8")) parts = [] if name := profile.get("name"): parts.append(f"客户:{name}") if industry := profile.get("industry"): parts.append(f"行业:{industry}") if prefs := profile.get("preferences"): parts.append(f"偏好:{prefs}") state.client_context = ";".join(parts) logger.info(f"[client_context] loaded profile for '{state.client_id}'") except Exception as e: logger.warning(f"[client_context] failed to load profile: {e}") return state