Parse a JSON dict → SceneConfig. Returns None on invalid data.
(data: dict[str, Any])
| 106 | |
| 107 | |
| 108 | def _deserialize_scene(data: dict[str, Any]) -> SceneConfig | None: |
| 109 | """Parse a JSON dict → SceneConfig. Returns None on invalid data.""" |
| 110 | try: |
| 111 | name = str(data.get("name", "")).strip().lower() |
| 112 | primary = str(data.get("primary", "")).strip() |
| 113 | if not name or not primary: |
| 114 | return None |
| 115 | |
| 116 | fallback_raw = data.get("fallback", []) |
| 117 | fallback = ( |
| 118 | [str(f).strip() for f in fallback_raw] |
| 119 | if isinstance(fallback_raw, list) |
| 120 | else [str(fallback_raw).strip()] |
| 121 | ) |
| 122 | |
| 123 | tier_floor = None |
| 124 | if "tier_floor" in data and data["tier_floor"]: |
| 125 | try: |
| 126 | tier_floor = Tier(str(data["tier_floor"]).upper()) |
| 127 | except ValueError: |
| 128 | pass |
| 129 | |
| 130 | tier_cap = None |
| 131 | if "tier_cap" in data and data["tier_cap"]: |
| 132 | try: |
| 133 | tier_cap = Tier(str(data["tier_cap"]).upper()) |
| 134 | except ValueError: |
| 135 | pass |
| 136 | |
| 137 | allowed_providers = data.get("allowed_providers", []) |
| 138 | if not isinstance(allowed_providers, list): |
| 139 | allowed_providers = [] |
| 140 | |
| 141 | return SceneConfig( |
| 142 | name=name, |
| 143 | primary=primary, |
| 144 | fallback=[f for f in fallback if f], |
| 145 | hard_pin=bool(data.get("hard_pin", False)), |
| 146 | description=str(data.get("description", "")), |
| 147 | tier_floor=tier_floor, |
| 148 | tier_cap=tier_cap, |
| 149 | allowed_providers=[str(p).strip() for p in allowed_providers if str(p).strip()], |
| 150 | max_cost_per_request=data.get("max_cost_per_request"), |
| 151 | ) |
| 152 | except Exception: |
| 153 | logger.warning("Failed to deserialize scene: %s", data, exc_info=True) |
| 154 | return None |
| 155 | |
| 156 | |
| 157 | class SceneStore: |