feat(providers): add xAI Grok OAuth with capability-gated X Search (#5035)
This commit is contained in:
@@ -111,6 +111,7 @@ class TestResolveConfig:
|
||||
"agents": {"defaults": {"dream": {"cron": "0 */4 * * *"}}},
|
||||
"providers": {
|
||||
"openaiCodex": {"apiKey": "codex-secret"},
|
||||
"xaiGrok": {"apiKey": "xai-secret"},
|
||||
"githubCopilot": {"apiKey": "copilot-secret"},
|
||||
"groq": {"apiKey": "groq-secret"},
|
||||
},
|
||||
@@ -125,6 +126,7 @@ class TestResolveConfig:
|
||||
saved = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
assert saved["agents"]["defaults"]["dream"]["cron"] == "0 */4 * * *"
|
||||
assert "openaiCodex" not in saved["providers"]
|
||||
assert "xaiGrok" not in saved["providers"]
|
||||
assert "githubCopilot" not in saved["providers"]
|
||||
assert saved["providers"]["groq"]["apiKey"] == "groq-secret"
|
||||
|
||||
@@ -137,6 +139,7 @@ class TestResolveConfig:
|
||||
"openaiCodex": {
|
||||
"apiKey": "codex-secret",
|
||||
"proxy": proxy,
|
||||
"extraBody": {"service_tier": "priority"},
|
||||
},
|
||||
"groq": {"apiKey": "groq-secret"},
|
||||
}
|
||||
@@ -146,13 +149,77 @@ class TestResolveConfig:
|
||||
save_config(config, config_path)
|
||||
|
||||
saved = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
assert saved["providers"]["openaiCodex"] == {"proxy": proxy}
|
||||
assert saved["providers"]["openaiCodex"] == {
|
||||
"extraBody": {"service_tier": "priority"},
|
||||
"proxy": proxy,
|
||||
}
|
||||
assert saved["providers"]["groq"]["apiKey"] == "groq-secret"
|
||||
|
||||
reloaded = load_config(config_path)
|
||||
assert reloaded.providers.openai_codex.proxy == proxy
|
||||
assert reloaded.providers.openai_codex.extra_body == {"service_tier": "priority"}
|
||||
assert reloaded.providers.openai_codex.api_key is None
|
||||
|
||||
def test_save_preserves_xai_grok_proxy_but_never_credentials(self, tmp_path):
|
||||
config_path = tmp_path / "config.json"
|
||||
proxy = "http://127.0.0.1:23458"
|
||||
config = Config.model_validate(
|
||||
{
|
||||
"providers": {
|
||||
"xaiGrok": {
|
||||
"apiKey": "must-not-be-saved",
|
||||
"proxy": proxy,
|
||||
"extraBody": {"parallel_tool_calls": False},
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
save_config(config, config_path)
|
||||
|
||||
saved = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
assert saved["providers"]["xaiGrok"] == {
|
||||
"extraBody": {"parallel_tool_calls": False},
|
||||
"proxy": proxy,
|
||||
}
|
||||
assert "must-not-be-saved" not in config_path.read_text(encoding="utf-8")
|
||||
|
||||
reloaded = load_config(config_path)
|
||||
assert reloaded.providers.xai_grok.proxy == proxy
|
||||
assert reloaded.providers.xai_grok.extra_body == {"parallel_tool_calls": False}
|
||||
assert reloaded.providers.xai_grok.api_key is None
|
||||
|
||||
def test_save_preserves_settings_across_oauth_provider_blocks(self, tmp_path):
|
||||
config_path = tmp_path / "config.json"
|
||||
config = Config.model_validate(
|
||||
{
|
||||
"providers": {
|
||||
"openaiCodex": {
|
||||
"apiKey": "codex-secret",
|
||||
"extraBody": {"service_tier": "${CODEX_SERVICE_TIER}"},
|
||||
},
|
||||
"xaiGrok": {
|
||||
"apiKey": "xai-secret",
|
||||
"proxy": "http://127.0.0.1:7890",
|
||||
"extraBody": {"parallel_tool_calls": False},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
save_config(config, config_path)
|
||||
|
||||
saved = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
assert saved["providers"]["openaiCodex"] == {
|
||||
"extraBody": {"service_tier": "${CODEX_SERVICE_TIER}"}
|
||||
}
|
||||
assert saved["providers"]["xaiGrok"] == {
|
||||
"extraBody": {"parallel_tool_calls": False},
|
||||
"proxy": "http://127.0.0.1:7890",
|
||||
}
|
||||
assert "codex-secret" not in config_path.read_text(encoding="utf-8")
|
||||
assert "xai-secret" not in config_path.read_text(encoding="utf-8")
|
||||
|
||||
def test_preserves_excluded_fields_when_no_env_refs(self, tmp_path):
|
||||
"""Regression: fields with ``exclude=True`` (e.g. ProviderConfig.openai_codex)
|
||||
must survive ``resolve_config_env_vars`` when the config has no
|
||||
|
||||
Reference in New Issue
Block a user