fix(cli): honor env precedence for LLM and run config
Interactive selections and flag defaults overrode TRADINGAGENTS_* env vars. Rule: an explicit env value or CLI flag wins; otherwise the env-applied default is kept. - Research depth: skip the prompt when both round-count env vars are set, and stop overwriting them (#977). - Checkpoint: --checkpoint/--no-checkpoint is tri-state; omitting it keeps TRADINGAGENTS_CHECKPOINT_ENABLED (#976). - Docker ollama: use TRADINGAGENTS_LLM_PROVIDER + OLLAMA_BASE_URL, not a bare LLM_PROVIDER the overlay never reads (#975). - Reasoning/thinking knobs: settable via env; the prompt is skipped when set. - Effort gating: forward effort only to models that accept it (Anthropic Opus 4.5+/Sonnet 4.6+, OpenAI reasoning models); drop it elsewhere. - Boolean env values: raise a named error on invalid input instead of silently becoming False.
This commit is contained in:
11 files changed
+363
-59
No files matched your search
@@ -18,13 +18,35 @@ _ENV_OVERRIDES = {
|
||||
"TRADINGAGENTS_CHECKPOINT_ENABLED": "checkpoint_enabled",
|
||||
"TRADINGAGENTS_BENCHMARK_TICKER": "benchmark_ticker",
|
||||
"TRADINGAGENTS_TEMPERATURE": "temperature",
|
||||
# Provider-specific reasoning/thinking knobs (None = each provider's own
|
||||
# default). Settable here for non-interactive runs; the CLI also offers an
|
||||
# interactive choice, which is skipped when the matching var is set.
|
||||
"TRADINGAGENTS_GOOGLE_THINKING_LEVEL": "google_thinking_level",
|
||||
"TRADINGAGENTS_OPENAI_REASONING_EFFORT": "openai_reasoning_effort",
|
||||
"TRADINGAGENTS_ANTHROPIC_EFFORT": "anthropic_effort",
|
||||
}
|
||||
|
||||
|
||||
_BOOL_TRUE = ("true", "1", "yes", "on")
|
||||
_BOOL_FALSE = ("false", "0", "no", "off")
|
||||
|
||||
|
||||
def _coerce(value: str, reference):
|
||||
"""Coerce env-var string to the type of the existing default value."""
|
||||
"""Coerce env-var string to the type of the existing default value.
|
||||
|
||||
Invalid values raise ``ValueError`` rather than silently falling back to a
|
||||
default — a misspelled boolean (e.g. ``treu``) or non-numeric int should fail
|
||||
loudly at startup, not quietly misconfigure an unattended run.
|
||||
"""
|
||||
if isinstance(reference, bool):
|
||||
return value.strip().lower() in ("true", "1", "yes", "on")
|
||||
normalized = value.strip().lower()
|
||||
if normalized in _BOOL_TRUE:
|
||||
return True
|
||||
if normalized in _BOOL_FALSE:
|
||||
return False
|
||||
raise ValueError(
|
||||
f"expected a boolean ({'/'.join(_BOOL_TRUE + _BOOL_FALSE)}), got {value!r}"
|
||||
)
|
||||
if isinstance(reference, int) and not isinstance(reference, bool):
|
||||
return int(value)
|
||||
if isinstance(reference, float):
|
||||
@@ -38,7 +60,10 @@ def _apply_env_overrides(config: dict) -> dict:
|
||||
raw = os.environ.get(env_var)
|
||||
if raw is None or raw == "":
|
||||
continue
|
||||
config[key] = _coerce(raw, config.get(key))
|
||||
try:
|
||||
config[key] = _coerce(raw, config.get(key))
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"Invalid value for {env_var}: {exc}") from exc
|
||||
return config
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user