75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
"""Application settings loaded from TOML with env-var overrides."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from pydantic import BaseModel, Field
|
|
from pydantic_settings import (
|
|
BaseSettings,
|
|
PydanticBaseSettingsSource,
|
|
SettingsConfigDict,
|
|
TomlConfigSettingsSource,
|
|
)
|
|
|
|
|
|
class MeshCoreCfg(BaseModel):
|
|
serial_port: str
|
|
baud_rate: int = 115200
|
|
|
|
|
|
class LLMCfg(BaseModel):
|
|
base_url: str
|
|
api_key: str = "not-needed"
|
|
model: str
|
|
system_prompt: str = (
|
|
"You are a concise assistant on a low-bandwidth mesh radio. "
|
|
"Replies must be brief — under 180 bytes."
|
|
)
|
|
temperature: float = 0.7
|
|
request_timeout_seconds: float = 60.0
|
|
|
|
|
|
class StorageCfg(BaseModel):
|
|
sqlite_path: Path = Path("data/meshbot.db")
|
|
|
|
|
|
class MessageCfg(BaseModel):
|
|
max_bytes: int = Field(default=184, gt=0)
|
|
|
|
|
|
def _toml_path() -> Path:
|
|
return Path(os.environ.get("MESHBOT_CONFIG", "config.toml"))
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
meshcore: MeshCoreCfg
|
|
llm: LLMCfg
|
|
storage: StorageCfg = StorageCfg()
|
|
message: MessageCfg = MessageCfg()
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_prefix="MESHBOT_",
|
|
env_nested_delimiter="__",
|
|
toml_file=_toml_path(),
|
|
extra="ignore",
|
|
)
|
|
|
|
@classmethod
|
|
def settings_customise_sources(
|
|
cls,
|
|
settings_cls: type[BaseSettings],
|
|
init_settings: PydanticBaseSettingsSource,
|
|
env_settings: PydanticBaseSettingsSource,
|
|
dotenv_settings: PydanticBaseSettingsSource,
|
|
file_secret_settings: PydanticBaseSettingsSource,
|
|
) -> tuple[PydanticBaseSettingsSource, ...]:
|
|
# Order = priority (highest first): init args > env > TOML > secrets.
|
|
return (
|
|
init_settings,
|
|
env_settings,
|
|
TomlConfigSettingsSource(settings_cls),
|
|
file_secret_settings,
|
|
)
|