Skip to content

Add Pydantic validation model for config.json#8

Closed
Copilot wants to merge 1 commit into
mainfrom
copilot/design-discord-bot-architecture
Closed

Add Pydantic validation model for config.json#8
Copilot wants to merge 1 commit into
mainfrom
copilot/design-discord-bot-architecture

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 28, 2026

config.json was loaded as a raw dict and accessed via .get() chains throughout the codebase, deferring misconfiguration errors to runtime callsites rather than surfacing them at startup.

New: hydra/config_schema.py

Typed Pydantic v2 models for every config section:

  • FrameworkConfiglog_level validated against Python's logging set
  • DashboardConfigport bounded ge=1, le=65535
  • ContextBusConfig, DatabaseConfig, ProfileConfig
  • Discriminated-union adapter configs keyed on "type" (MockAdapterConfig, DiscordAdapterConfig, OpenAIAdapterConfig, MCPAdapterConfig) — with field-level constraints (e.g. temperature capped to the OpenAI API range 0.0–2.0)
  • HydraConfig — top-level composite with safe defaults for every section
# Bad config now fails immediately at startup with a clear ValidationError
HydraConfig.model_validate({"framework": {"log_level": "VERBOSE"}})
# pydantic_core.ValidationError: log_level must be one of {'DEBUG', 'INFO', ...}

hydra/main.py

  • load_config() return type changed from dict to HydraConfig; parses via model_validate and catches ValidationError specifically
  • run() and main() use typed attribute access (config.dashboard.enabled, config.framework.log_level, etc.)

hydra/core/runtime.py

  • HydraRuntime.__init__ signature updated to HydraConfig
  • All .get() chains replaced with direct attribute access
  • Adapter configs passed to existing constructors via model_dump() to preserve the adapter interface

Agent-Logs-Url: https://github.com/HiLleywyn/Hydra/sessions/60fe845f-c411-48b8-bef0-7ffef9c2e25f

Co-authored-by: HiLleywyn <97213385+HiLleywyn@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a typed, validated configuration layer (Pydantic v2) for hydra/config.json and updates the runtime/entrypoint to use the validated model instead of raw dict access, so configuration errors surface at startup.

Changes:

  • Added hydra/config_schema.py with Pydantic models for config sections and adapter discriminated unions.
  • Updated hydra/main.py to load/validate config into a HydraConfig and use typed attribute access.
  • Updated hydra/core/runtime.py to accept HydraConfig and replace .get() chains with typed access (dumping adapter configs back to dict for existing adapter constructors).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
hydra/config_schema.py Adds Pydantic schema models for full config validation and typed access.
hydra/main.py Parses config.json into HydraConfig and uses typed config fields.
hydra/core/runtime.py Updates runtime to consume HydraConfig and uses model-backed values throughout initialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hydra/config_schema.py
Comment on lines +24 to +31
@field_validator("log_level")
@classmethod
def validate_log_level(cls, v: str) -> str:
valid = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
upper = v.upper()
if upper not in valid:
raise ValueError(f"log_level must be one of {valid}, got '{v}'")
return upper
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FrameworkConfig.validate_log_level() hard-codes a limited set of level names. This will reject valid logging level aliases like WARN/FATAL (and NOTSET), which were previously accepted by setup_logging() and are part of Python’s logging level name mapping. Consider validating against logging._nameToLevel (or a curated list derived from it) and make the error message deterministic (avoid embedding a set, whose ordering is not stable).

Copilot uses AI. Check for mistakes.
Comment thread hydra/config_schema.py
Comment on lines +109 to +115
class HydraConfig(BaseModel):
framework: FrameworkConfig = FrameworkConfig()
database: DatabaseConfig = DatabaseConfig()
dashboard: DashboardConfig = DashboardConfig()
context_bus: ContextBusConfig = ContextBusConfig()
profiles: list[ProfileConfig] = []
adapters: dict[str, AdapterConfig] = {}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new schema models don’t forbid unknown/extra keys, so typos in config.json (e.g., dashbaord) will be silently ignored by Pydantic’s default extra handling, which undermines the goal of surfacing misconfiguration early. Consider setting model_config = ConfigDict(extra="forbid") on HydraConfig (and/or the section models) so unexpected keys produce a ValidationError.

Copilot uses AI. Check for mistakes.
Comment thread hydra/main.py
Comment on lines 41 to +47
with open(path) as f:
return json.load(f)
raw = json.load(f)
try:
return HydraConfig.model_validate(raw)
except ValidationError as exc:
logging.error("Invalid configuration: %s", exc)
sys.exit(1)
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_config() now catches ValidationError, but invalid JSON (e.g., a trailing comma) will still raise json.JSONDecodeError and crash with a stack trace rather than a clear startup error. Consider catching json.JSONDecodeError (and potentially OSError) to log a concise message including the config path before exiting.

Copilot uses AI. Check for mistakes.
@HiLleywyn HiLleywyn closed this Mar 28, 2026
@HiLleywyn HiLleywyn deleted the copilot/design-discord-bot-architecture branch March 28, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants