fix(cli): allow oauth login to set main provider

This commit is contained in:
hamb1y
2026-06-30 23:02:42 +08:00
committed by Xubin Ren
parent f9b02496c8
commit 58cce14a07
2 changed files with 114 additions and 0 deletions
+49
View File
@@ -1744,6 +1744,11 @@ _PROVIDER_DISPLAY: dict[str, str] = {
"github_copilot": "GitHub Copilot",
}
_OAUTH_PROVIDER_DEFAULT_MODELS: dict[str, str] = {
"openai_codex": "openai-codex/gpt-5.1-codex",
"github_copilot": "github-copilot/gpt-4.1",
}
def _register_login(name: str):
"""Register an OAuth login handler."""
@@ -1775,9 +1780,51 @@ def _resolve_oauth_provider(provider: str):
return spec
def _set_oauth_provider_as_main(
provider_name: str,
*,
model: str | None = None,
config_path: str | None = None,
) -> None:
"""Persist an OAuth provider as the active agent provider."""
from nanobot.config.loader import get_config_path, load_config, save_config, set_config_path
resolved_config_path = Path(config_path).expanduser().resolve() if config_path else None
if resolved_config_path is not None:
set_config_path(resolved_config_path)
console.print(f"[dim]Using config: {resolved_config_path}[/dim]")
config = load_config(resolved_config_path)
selected_model = (model or "").strip() or _OAUTH_PROVIDER_DEFAULT_MODELS[provider_name]
config.agents.defaults.model_preset = None
config.agents.defaults.provider = provider_name
config.agents.defaults.model = selected_model
save_config(config, resolved_config_path)
saved_path = resolved_config_path or get_config_path()
console.print(
f"[green]✓ Set {provider_name.replace('_', '-')} as the main provider[/green] "
f"[dim]{selected_model}[/dim]"
)
console.print(f"[dim]Saved: {saved_path}[/dim]")
@provider_app.command("login")
def provider_login(
provider: str = typer.Argument(..., help="OAuth provider (e.g. 'openai-codex', 'github-copilot')"),
set_main: bool = typer.Option(
False,
"--set-main",
"--main",
help="Set this OAuth provider as the active agent provider after login",
),
model: str | None = typer.Option(
None,
"--model",
"-m",
help="Model to use when setting this provider as the active provider",
),
config: str | None = typer.Option(None, "--config", "-c", help="Path to config file"),
):
"""Authenticate with an OAuth provider."""
spec = _resolve_oauth_provider(provider)
@@ -1789,6 +1836,8 @@ def provider_login(
console.print(f"{__logo__} OAuth Login - {spec.label}\n")
handler()
if set_main or model:
_set_oauth_provider_as_main(spec.name, model=model, config_path=config)
@provider_app.command("logout")
+65
View File
@@ -435,6 +435,71 @@ def test_provider_login_rejects_unknown_provider():
assert "Unknown OAuth provider" in result.stdout
def test_provider_login_can_set_openai_codex_as_main_provider(tmp_path):
config_path = tmp_path / "config.json"
called = False
original = cli_commands._LOGIN_HANDLERS["openai_codex"]
def fake_login() -> None:
nonlocal called
called = True
cli_commands._LOGIN_HANDLERS["openai_codex"] = fake_login
try:
result = runner.invoke(
app,
[
"provider",
"login",
"openai-codex",
"--set-main",
"--config",
str(config_path),
],
)
finally:
cli_commands._LOGIN_HANDLERS["openai_codex"] = original
assert result.exit_code == 0
assert called is True
assert "Set openai-codex as the main provider" in result.stdout
saved = Config.model_validate(json.loads(config_path.read_text(encoding="utf-8")))
assert saved.agents.defaults.provider == "openai_codex"
assert saved.agents.defaults.model == "openai-codex/gpt-5.1-codex"
assert saved.agents.defaults.model_preset is None
assert make_provider(saved).__class__.__name__ == "OpenAICodexProvider"
def test_provider_login_model_implies_set_main_provider(tmp_path):
config_path = tmp_path / "config.json"
original = cli_commands._LOGIN_HANDLERS["github_copilot"]
cli_commands._LOGIN_HANDLERS["github_copilot"] = lambda: None
try:
result = runner.invoke(
app,
[
"provider",
"login",
"github-copilot",
"--model",
"github-copilot/gpt-5.4-mini",
"--config",
str(config_path),
],
)
finally:
cli_commands._LOGIN_HANDLERS["github_copilot"] = original
assert result.exit_code == 0
assert "Set github-copilot as the main provider" in result.stdout
saved = Config.model_validate(json.loads(config_path.read_text(encoding="utf-8")))
assert saved.agents.defaults.provider == "github_copilot"
assert saved.agents.defaults.model == "github-copilot/gpt-5.4-mini"
assert make_provider(saved).__class__.__name__ == "GitHubCopilotProvider"
def test_provider_login_openai_codex_passes_configured_proxy(monkeypatch):
proxy = "http://127.0.0.1:23458"
monkeypatch.setattr(