config: agent_panel block (enabled/surfaces/min_quality/daily budget)

New optional config.json block for the upcoming LLM agent-panel feature:
enabled, telegram, dashboard (per-surface toggles), min_quality,
max_panels_per_day, reuse_ttl_seconds. Absent block → {} → feature dark.
Validation mirrors the deepseek block. Module 23 opened with parse +
reject tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SisdfkxnXNL9iZsXxN3T15
This commit is contained in:
Harwinder Sekhon
2026-08-07 22:26:43 -04:00
parent da61cff509
commit 8d0bc27353
3 changed files with 75 additions and 1 deletions
+31 -1
View File
@@ -86,7 +86,7 @@ _VALID_LOG_LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")
_SCANNABLE_TFS = ("M5", "M15", "H1", "H4")
_KNOWN_TOP = {"telegram", "data_providers", "scanning", "pairs", "log_level",
"oanda", "deepseek"}
"oanda", "deepseek", "agent_panel"}
_KNOWN_OANDA = {
"account_id", "api_token", "base_url", "lot_size",
"quality_gate", "max_hold_bars",
@@ -94,6 +94,10 @@ _KNOWN_OANDA = {
_KNOWN_DEEPSEEK = {
"api_key", "model", "enabled", "timeout_seconds", "daily_request_cap",
}
_KNOWN_AGENT_PANEL = {
"enabled", "telegram", "dashboard", "min_quality",
"max_panels_per_day", "reuse_ttl_seconds",
}
_KNOWN_TELEGRAM = {"token", "chat_id", "channel_id", "alert_min_quality"}
_KNOWN_SCANNING = {"pairs", "timeframes"}
_KNOWN_PAIR_KEYS = {"blocked_hours_utc"}
@@ -118,6 +122,7 @@ class AppConfig:
pair_overrides: Dict[str, Dict[str, Any]] = field(default_factory=dict)
oanda_settings: Dict[str, Any] = field(default_factory=dict)
deepseek_settings: Dict[str, Any] = field(default_factory=dict)
agent_panel_settings: Dict[str, Any] = field(default_factory=dict)
log_level: str = "INFO"
@@ -276,6 +281,31 @@ def load_app_config(path: str = CONFIG_PATH) -> AppConfig:
"config.json: deepseek.model must be a non-empty string")
app.deepseek_settings = dict(deepseek)
panel = raw.get("agent_panel", {})
_check_keys(panel, _KNOWN_AGENT_PANEL, '"agent_panel"')
for flag in ("enabled", "telegram", "dashboard"):
if flag in panel and not isinstance(panel[flag], bool):
raise AppConfigError(
f"config.json: agent_panel.{flag} must be true or false")
if "min_quality" in panel and panel["min_quality"] not in _VALID_QUALITIES:
raise AppConfigError(
f'config.json: agent_panel.min_quality "{panel["min_quality"]}" '
f"not in {_VALID_QUALITIES}")
if "max_panels_per_day" in panel:
mpd = panel["max_panels_per_day"]
if isinstance(mpd, bool) or not isinstance(mpd, int) or mpd < 1:
raise AppConfigError(
"config.json: agent_panel.max_panels_per_day must be a "
"positive integer")
if "reuse_ttl_seconds" in panel:
ttl = panel["reuse_ttl_seconds"]
if isinstance(ttl, bool) or not isinstance(ttl, (int, float)) \
or ttl < 0:
raise AppConfigError(
"config.json: agent_panel.reuse_ttl_seconds must be a "
"non-negative number")
app.agent_panel_settings = dict(panel)
level = raw.get("log_level", app.log_level)
if level not in _VALID_LOG_LEVELS:
raise AppConfigError(