#!/usr/bin/env python3 """ Game LLM behavior configuration loader. Loads YAML configuration that defines: - system_prompt: Injected as the first "system" message for chat completions - scenario, rules: Arbitrary metadata available to the app if needed - start_message: Initial assistant message shown to the user """ from __future__ import annotations from dataclasses import dataclass, field from pathlib import Path from typing import Any, Dict, Optional, Union import yaml @dataclass class GameConfig: system_prompt: str = "" scenario: Dict[str, Any] = field(default_factory=dict) rules: list[str] = field(default_factory=list) start_message: str = "" @classmethod def from_dict(cls, data: Dict[str, Any]) -> "GameConfig": return cls( system_prompt=str(data.get("system_prompt", "") or ""), scenario=dict(data.get("scenario", {}) or {}), rules=list(data.get("rules", []) or []), start_message=str(data.get("start_message", "") or ""), ) def load_game_config(path: Union[str, Path] = "config/game_config.yaml") -> GameConfig: """ Load the game configuration from YAML. Returns defaults if the file is missing or invalid. Args: path: Path to the YAML config file. Returns: GameConfig: Parsed configuration or defaults. """ p = Path(path) if not p.exists(): # Return defaults if config is missing return GameConfig() try: with p.open("r", encoding="utf-8") as f: raw = yaml.safe_load(f) or {} if not isinstance(raw, dict): return GameConfig() return GameConfig.from_dict(raw) except Exception: # Fail-closed to defaults to keep the app usable return GameConfig()