feat(providers): add xAI Grok OAuth with capability-gated X Search (#5035)

This commit is contained in:
chengyongru
2026-07-23 11:55:16 +08:00
committed by GitHub
parent c22efb5f7a
commit c7393c785e
38 changed files with 3881 additions and 104 deletions
+68 -1
View File
@@ -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