QUELLCODE / PY
config.py
src/hardware_box/config.py
1# OpenAss: nur privater, experimenteller Gebrauch; auf eigene Verantwortung.2# Niemals Unternehmensrechner, Produktivsysteme, Industrieanlagen oder3# sicherheitskritische Systeme anschließen oder bedienen.4# Haftungshinweis und gesetzliche Grenzen: ../../DISCLAIMER.txt.5import os6import tomllib7from pathlib import Path8from typing import Literal910from pydantic import BaseModel, ConfigDict, Field, field_validator111213class Settings(BaseModel):14 model_config = ConfigDict(extra="forbid", validate_assignment=True)15 demo: bool = True16 model: str = "gpt-6-astra"17 capture_device: str = "/dev/video0"18 capture_width: int = Field(1920, ge=320, le=4096)19 capture_height: int = Field(1080, ge=240, le=2160)20 capture_fps: int = Field(60, ge=60, le=120)21 capture_format: Literal["YUYV", "MJPG", "RGB3"] = "YUYV"22 screenshot_width: int = Field(1920, ge=320, le=4096)23 screenshot_height: int = Field(1080, ge=240, le=2160)24 target_width: int = Field(3840, ge=320, le=8192)25 target_height: int = Field(2160, ge=240, le=8192)26 serial_port: str = "/dev/ttyAMA0"27 keyboard_layout: Literal["us", "de", "at"] = "de"28 calibration_confirmed: bool = False29 allow_screenshot_upload: bool = False30 session_seconds: int = Field(600, ge=10, le=3600)31 max_actions: int = Field(150, ge=1, le=1000)32 max_api_calls: int = Field(40, ge=1, le=200)33 max_total_tokens: int = Field(200000, ge=1000, le=2000000)34 max_actions_per_second: float = Field(4, ge=0.2, le=10)35 approval_timeout_seconds: int = Field(60, ge=5, le=120)36 max_text_chars: int = Field(250, ge=1, le=1000)37 extra_denied_keypresses: list[list[str]] = Field(default_factory=list, max_length=32)38 allowed_keypresses: list[list[str]] = Field(default_factory=list, max_length=32)39 settle_seconds: float = Field(0.35, ge=0.1, le=3)40 log_dir: str = "data/sessions"41 log_screenshots: bool = False42 log_api_responses: bool = False4344 @field_validator("extra_denied_keypresses", "allowed_keypresses")45 @classmethod46 def valid_combinations(cls, value):47 if any(not 1 <= len(combo) <= 6 or any(not key.strip() for key in combo) for combo in value):48 raise ValueError("Key combinations must contain 1..6 nonempty key names")49 return value505152def load_settings() -> Settings:53 path = Path(os.environ.get("BOX_CONFIG", "config/local.toml"))54 return Settings(**tomllib.loads(path.read_text())) if path.is_file() else Settings()