fix(v3): config_resolver — remove dead engine param, add input validation
- Remove unused `engine` parameter from `_resolve_engine()` signature and call sites - Warn on unknown engine in `_has_api_key()` instead of silently returning True - Warn when budget value from profile is not in BUDGET_ENGINE_MAP - Validate `platforms` type in `_resolve_platforms()`, wrap non-list values Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,13 @@ Missing API key → auto-downgrade to free alternative
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Base directory of the project (one level up from bots/)
|
# Base directory of the project (one level up from bots/)
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
@@ -107,10 +110,10 @@ class ConfigResolver:
|
|||||||
engine = self._load('config/engine.json')
|
engine = self._load('config/engine.json')
|
||||||
|
|
||||||
resolved = {
|
resolved = {
|
||||||
'writing': self._resolve_engine('writing', profile, engine),
|
'writing': self._resolve_engine('writing', profile),
|
||||||
'tts': self._resolve_engine('tts', profile, engine),
|
'tts': self._resolve_engine('tts', profile),
|
||||||
'video': self._resolve_engine('video', profile, engine),
|
'video': self._resolve_engine('video', profile),
|
||||||
'image': self._resolve_engine('image', profile, engine),
|
'image': self._resolve_engine('image', profile),
|
||||||
'platforms': self._resolve_platforms(profile),
|
'platforms': self._resolve_platforms(profile),
|
||||||
'budget': profile.get('budget', 'free'),
|
'budget': profile.get('budget', 'free'),
|
||||||
'level': profile.get('level', 'beginner'),
|
'level': profile.get('level', 'beginner'),
|
||||||
@@ -143,12 +146,17 @@ class ConfigResolver:
|
|||||||
env_var = ENGINE_API_KEY_MAP.get(engine_name)
|
env_var = ENGINE_API_KEY_MAP.get(engine_name)
|
||||||
if env_var is None:
|
if env_var is None:
|
||||||
# Unknown engine — treat as available (graceful degradation)
|
# Unknown engine — treat as available (graceful degradation)
|
||||||
|
logger.warning(
|
||||||
|
"Unknown engine '%s': not in ENGINE_API_KEY_MAP or ENGINE_REGISTRY as local; "
|
||||||
|
"treating as available.",
|
||||||
|
engine_name,
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
value = os.environ.get(env_var, '').strip()
|
value = os.environ.get(env_var, '').strip()
|
||||||
return len(value) > 0
|
return len(value) > 0
|
||||||
|
|
||||||
def _resolve_engine(self, category: str, profile: dict, engine: dict) -> dict:
|
def _resolve_engine(self, category: str, profile: dict) -> dict:
|
||||||
"""
|
"""
|
||||||
Resolve the active engine for a category.
|
Resolve the active engine for a category.
|
||||||
|
|
||||||
@@ -161,7 +169,13 @@ class ConfigResolver:
|
|||||||
Returns dict with 'provider' and 'auto_selected' flag.
|
Returns dict with 'provider' and 'auto_selected' flag.
|
||||||
"""
|
"""
|
||||||
budget = profile.get('budget', 'free')
|
budget = profile.get('budget', 'free')
|
||||||
candidate_list = BUDGET_ENGINE_MAP.get(budget, BUDGET_ENGINE_MAP['free']).get(category, [])
|
if budget not in BUDGET_ENGINE_MAP:
|
||||||
|
logger.warning(
|
||||||
|
"Invalid budget value '%s' from profile; falling back to 'free'.",
|
||||||
|
budget,
|
||||||
|
)
|
||||||
|
budget = 'free'
|
||||||
|
candidate_list = BUDGET_ENGINE_MAP[budget].get(category, [])
|
||||||
|
|
||||||
# Determine user's preferred provider
|
# Determine user's preferred provider
|
||||||
engines_section = profile.get('engines', {})
|
engines_section = profile.get('engines', {})
|
||||||
@@ -193,7 +207,10 @@ class ConfigResolver:
|
|||||||
|
|
||||||
def _resolve_platforms(self, profile: dict) -> list:
|
def _resolve_platforms(self, profile: dict) -> list:
|
||||||
"""Return the list of target publishing platforms from user profile."""
|
"""Return the list of target publishing platforms from user profile."""
|
||||||
return profile.get('platforms', [])
|
platforms = profile.get('platforms', [])
|
||||||
|
if not isinstance(platforms, list):
|
||||||
|
return [str(platforms)] if platforms else []
|
||||||
|
return platforms
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user