File size: 3,504 Bytes
40c0886
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""Global configuration for the Unity agent.

The :class:`Settings` dataclass is the single source of truth for runtime
parameters such as the Unity installation path, optional LLM API keys, the
default output directory and project metadata used when scaffolding a new
Unity project.
"""

from __future__ import annotations

import os
from dataclasses import dataclass, field, asdict
from pathlib import Path
from typing import Optional


DEFAULT_OUTPUT_DIR = "unity_output"
DEFAULT_UNITY_VERSION = "2022.3.20f1"

# Default Unity project metadata. These values are written into
# ProjectSettings/ProjectSettings.asset so the editor knows what to display
# in the project wizard and on the splash screen.
DEFAULT_COMPANY_NAME = "UnityAgent"
DEFAULT_PRODUCT_NAME = "GeneratedGame"


@dataclass
class Settings:
    """Runtime configuration shared by every tool.

    Parameters
    ----------
    unity_path:
        Optional path to the Unity executable (``Unity.exe`` / ``Unity``).
        When provided, the agent can optionally invoke Unity in batch mode
        to validate that generated projects compile.
    unity_version:
        Target Unity version written into ``ProjectSettings.asset``.
    output_dir:
        Root directory where generated projects are written. Can be either a
        relative path (resolved against the current working directory) or an
        absolute path.
    company_name / product_name:
        Metadata written into the project settings.
    openai_api_key / anthropic_api_key / zai_api_key:
        Optional LLM provider keys. Only required if the orchestrator is
        wired up to call an LLM directly.
    overwrite:
        If ``True`` existing files are replaced; otherwise a ``FileExistsError``
        is raised when a destination file already exists.
    """

    unity_path: Optional[str] = None
    unity_version: str = DEFAULT_UNITY_VERSION
    output_dir: str = DEFAULT_OUTPUT_DIR
    company_name: str = DEFAULT_COMPANY_NAME
    product_name: str = DEFAULT_PRODUCT_NAME

    openai_api_key: Optional[str] = field(default_factory=lambda: os.environ.get("OPENAI_API_KEY"))
    anthropic_api_key: Optional[str] = field(default_factory=lambda: os.environ.get("ANTHROPIC_API_KEY"))
    zai_api_key: Optional[str] = field(default_factory=lambda: os.environ.get("ZAI_API_KEY"))

    overwrite: bool = True
    auto_create_dirs: bool = True

    # ------------------------------------------------------------------ #
    # Convenience helpers
    # ------------------------------------------------------------------ #
    @property
    def output_path(self) -> Path:
        p = Path(self.output_dir)
        return p if p.is_absolute() else (Path.cwd() / p)

    def project_path(self, project_name: str) -> Path:
        """Return the absolute path to a named project inside ``output_dir``."""
        return self.output_path / project_name

    def to_dict(self) -> dict:
        return asdict(self)

    @classmethod
    def from_env(cls) -> "Settings":
        """Build a :class:`Settings` instance populated from environment vars."""
        return cls(
            unity_path=os.environ.get("UNITY_PATH"),
            unity_version=os.environ.get("UNITY_VERSION", DEFAULT_UNITY_VERSION),
            output_dir=os.environ.get("UNITY_AGENT_OUTPUT_DIR", DEFAULT_OUTPUT_DIR),
            company_name=os.environ.get("UNITY_COMPANY_NAME", DEFAULT_COMPANY_NAME),
            product_name=os.environ.get("UNITY_PRODUCT_NAME", DEFAULT_PRODUCT_NAME),
        )