fix: --config flag now fully overrides ~/.strix/cli-config.json (#457)

* fix: --config flag now fully overrides ~/.strix/cli-config.json (fixes #377)

Previously, env vars applied from the default config at module import time
were not cleared when --config was later processed, causing settings from
~/.strix/cli-config.json to leak into runs that specified a custom config.

Track which vars were applied by the initial default-config load in
Config._applied_from_default. In apply_config_override, clear those vars
before applying the custom config so only the custom file's settings take effect.

* Add config override regression test

* Make config override test setup explicit

---------

Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: bearsyankees <bearsyankees@gmail.com>
This commit is contained in:
Octopus
2026-04-23 04:37:22 +08:00
committed by GitHub
parent 60abc09ff9
commit 9fb101282f
3 changed files with 48 additions and 1 deletions
+10 -1
View File
@@ -2,7 +2,7 @@ import contextlib
import json import json
import os import os
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any, ClassVar
STRIX_API_BASE = "https://models.strix.ai/api/v1" STRIX_API_BASE = "https://models.strix.ai/api/v1"
@@ -56,6 +56,10 @@ class Config:
# Config file override (set via --config CLI arg) # Config file override (set via --config CLI arg)
_config_file_override: Path | None = None _config_file_override: Path | None = None
# Tracks env vars set by the initial default-config load so they can be
# cleared when a --config override is later applied (avoids leakage).
_applied_from_default: ClassVar[dict[str, str]] = {}
@classmethod @classmethod
def _tracked_names(cls) -> list[str]: def _tracked_names(cls) -> list[str]:
return [ return [
@@ -151,6 +155,11 @@ class Config:
os.environ[var_name] = var_value os.environ[var_name] = var_value
applied[var_name] = var_value applied[var_name] = var_value
# Record what was applied from the default config so it can be cleared
# if a --config override is later provided (prevents leakage).
if cls._config_file_override is None and not force:
cls._applied_from_default = applied
return applied return applied
@classmethod @classmethod
+7
View File
@@ -6,6 +6,7 @@ Strix Agent Interface
import argparse import argparse
import asyncio import asyncio
import logging import logging
import os
import shutil import shutil
import sys import sys
from pathlib import Path from pathlib import Path
@@ -528,6 +529,12 @@ def pull_docker_image() -> None:
def apply_config_override(config_path: str) -> None: def apply_config_override(config_path: str) -> None:
# Clear env vars that were automatically applied from the default config file
# so they don't leak into the custom config context.
for var_name in Config._applied_from_default:
os.environ.pop(var_name, None)
Config._applied_from_default = {}
Config._config_file_override = validate_config_file(config_path) Config._config_file_override = validate_config_file(config_path)
apply_saved_config(force=True) apply_saved_config(force=True)
+31
View File
@@ -0,0 +1,31 @@
import json
import os
from strix.config.config import Config, apply_saved_config
def test_apply_config_override_clears_default_only_vars(monkeypatch, tmp_path) -> None:
from strix.interface.main import apply_config_override
default_cfg = tmp_path / "cli-config.json"
default_cfg.write_text(
json.dumps({"env": {"LLM_API_BASE": "https://default.api", "STRIX_LLM": "default-model"}}),
encoding="utf-8",
)
custom_cfg = tmp_path / "custom.json"
custom_cfg.write_text(json.dumps({"env": {"STRIX_LLM": "custom-model"}}), encoding="utf-8")
monkeypatch.setattr(Config, "_config_file_override", None)
monkeypatch.setattr(Config, "_applied_from_default", {})
monkeypatch.setattr(Config, "config_dir", classmethod(lambda cls: tmp_path))
for var_name in Config._llm_env_vars():
monkeypatch.delenv(var_name, raising=False)
apply_saved_config()
assert os.environ.get("LLM_API_BASE") == "https://default.api"
apply_config_override(str(custom_cfg))
assert os.environ.get("STRIX_LLM") == "custom-model"
assert "LLM_API_BASE" not in os.environ