from __future__ import annotations import json from typing import Any try: from . import route_metadata as route_metadata_policy except ImportError: # Allows local smoke tests with top-level imports. import route_metadata as route_metadata_policy PAIR_SIDES = ("softcore", "hardcore") def route_trace_json(**values: Any) -> str: trace: dict[str, Any] = {} for key, value in values.items(): if value is None: continue if isinstance(value, str): value = value.strip() if not value: continue trace[key] = value return json.dumps(trace, ensure_ascii=True, sort_keys=True) def _pair_selected_side(target: Any, selected_side: Any = "") -> str: side = str(selected_side or "").strip().lower() if side in PAIR_SIDES: return side target_side = str(target or "").strip().lower() return target_side if target_side in PAIR_SIDES else "softcore" def _add_if_value(trace: dict[str, Any], key: str, value: Any) -> None: if value is None: return if isinstance(value, str): value = value.strip() if not value: return if isinstance(value, (list, tuple, set)) and not value: return trace[key] = value def metadata_trace_fields(row: Any, *, target: Any = "", selected_side: Any = "") -> dict[str, Any]: """Return compact row metadata fields for formatter route traces. The trace intentionally carries routing/debug identifiers, not full prompt prose or cast descriptors. """ if not isinstance(row, dict): return {} trace: dict[str, Any] = {} source_row = row if isinstance(row.get("softcore_row"), dict) or isinstance(row.get("hardcore_row"), dict): side = _pair_selected_side(target, selected_side) source_row = row.get(f"{side}_row") if isinstance(row.get(f"{side}_row"), dict) else {} trace["metadata_kind"] = "pair" trace["selected_side"] = side else: trace["metadata_kind"] = "row" if not isinstance(source_row, dict): return trace _add_if_value(trace, "metadata_category", source_row.get("main_category") or source_row.get("category")) _add_if_value(trace, "metadata_subcategory", source_row.get("subcategory")) _add_if_value(trace, "action_family", route_metadata_policy.row_action_family(source_row)) _add_if_value(trace, "position_family", route_metadata_policy.row_position_family(source_row)) _add_if_value(trace, "position_key", source_row.get("position_key")) _add_if_value(trace, "position_keys", route_metadata_policy.row_position_keys(source_row, include_unknown=True)) _add_if_value(trace, "scene_profile", source_row.get("scene_camera_profile_key")) _add_if_value(trace, "pov_labels", source_row.get("pov_character_labels")) return trace