from __future__ import annotations import os from collections.abc import Mapping from dataclasses import dataclass DEFAULT_DIVERGENCE_TOLERANCE = 0.0 DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small" DEFAULT_TOP_K = 5 ENABLED_ENV = "SKILL_AUTHORING_ENABLED" DIVERGENCE_TOLERANCE_ENV = "SKILL_DIVERGENCE_TOLERANCE" EMBEDDING_MODEL_ENV = "SKILL_EMBEDDING_MODEL" TOP_K_ENV = "SKILL_RETRIEVAL_TOP_K" @dataclass(frozen=True) class SkillAuthoringConfig: enabled: bool = False divergence_tolerance: float = DEFAULT_DIVERGENCE_TOLERANCE embedding_model: str = DEFAULT_EMBEDDING_MODEL top_k: int = DEFAULT_TOP_K def load_config(env: Mapping[str, str] | None = None) -> SkillAuthoringConfig: values = env or os.environ return SkillAuthoringConfig( enabled=_parse_bool(values.get(ENABLED_ENV), default=False), divergence_tolerance=_parse_float( values.get(DIVERGENCE_TOLERANCE_ENV), default=DEFAULT_DIVERGENCE_TOLERANCE, ), embedding_model=values.get(EMBEDDING_MODEL_ENV) or DEFAULT_EMBEDDING_MODEL, top_k=_parse_int(values.get(TOP_K_ENV), default=DEFAULT_TOP_K), ) def _parse_bool(value: str | None, *, default: bool) -> bool: if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on", "enabled"} def _parse_float(value: str | None, *, default: float) -> float: if value is None: return default try: parsed = float(value) except ValueError: return default return parsed if parsed >= 0 else default def _parse_int(value: str | None, *, default: int) -> int: if value is None: return default try: parsed = int(value) except ValueError: return default return parsed if parsed > 0 else default