From d06384051df4f3333b148a53229f94de53f84138 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 11:13:39 +0800 Subject: [PATCH 1/7] fix: report resolved provider endpoint during setup --- raven/cli/onboard_commands.py | 6 ++++++ raven/config/update_providers.py | 14 +++++++++++--- raven/providers/registry.py | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/raven/cli/onboard_commands.py b/raven/cli/onboard_commands.py index 0ba0fd5e..b74f0986 100644 --- a/raven/cli/onboard_commands.py +++ b/raven/cli/onboard_commands.py @@ -881,6 +881,12 @@ def _verify_provider(provider: str, *, skip_test: bool = False) -> tuple[bool, s else: console.print(_t(" [dim]⏳ Verifying your API key…[/dim]", " [dim]⏳ 正在验证 API Key…[/dim]")) result = probe(provider) + # Named before the verdict: the address is resolved from the config, the + # registry default or LiteLLM, so on a failure it is the one thing the user + # cannot otherwise see. + probed_base = result.get("api_base") + if probed_base: + console.print(_t(f" [dim]Endpoint: {probed_base}[/dim]", f" [dim]接入地址:{probed_base}[/dim]")) if result["ok"]: models = result.get("models_count") suffix = _t(f" ({models} models available)", f"(共 {models} 个可用模型)") if models else "" diff --git a/raven/config/update_providers.py b/raven/config/update_providers.py index 0295d00b..c472485c 100644 --- a/raven/config/update_providers.py +++ b/raven/config/update_providers.py @@ -1089,8 +1089,10 @@ def test_provider( 3. Map status code → keyword (see ``_HTTP_STATUS_MAP``). Unknown codes render as ``http_{code}``. Network errors → ``network_error``. - Returns a dict, never raises. ``transport`` is injectable so unit tests - can mount an ``httpx.MockTransport`` without touching real network. + Returns a dict, never raises. It carries ``api_base`` -- the address the + probe actually contacted -- whenever one was resolved. ``transport`` is + injectable so unit tests can mount an ``httpx.MockTransport`` without + touching real network. """ name = canonical_provider_name(name) @@ -1235,7 +1237,13 @@ def test_provider( if spec and spec.name in {"minimax_global", "minimax_cn"} and api_key: headers["x-api-key"] = api_key - result = _probe_models_endpoint(url, headers, timeout_s=timeout_s, transport=transport) + # Carried back so a caller can name the address it just probed: the + # resolution above (endpoint -> spec default -> LiteLLM) is not visible from + # the config alone, so a wrong endpoint is otherwise invisible on failure. + result = { + **_probe_models_endpoint(url, headers, timeout_s=timeout_s, transport=transport), + "api_base": api_base, + } if derived_api_base and result.get("status") == "http_404": # The address LiteLLM sends completions to is not always where the # catalogue lives -- DeepSeek's is `/beta`, which has no `/models`. A 404 diff --git a/raven/providers/registry.py b/raven/providers/registry.py index 69d9c862..c78feeb1 100644 --- a/raven/providers/registry.py +++ b/raven/providers/registry.py @@ -486,7 +486,7 @@ def claims(self, model: str) -> bool: model_overrides=(), # Needed by `provider test` and the wizard preflight, which probe # /v1/models before any LiteLLM call resolves an endpoint. - default_api_base="https://api.minimax.io/v1", + default_api_base="https://api.minimaxi.com/v1", ), ProviderSpec( name="minimax_global", From 081d4d9b787368040446bf8fc3a876ee6977887a Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 16:36:37 +0800 Subject: [PATCH 2/7] feat(providers): add minimax cn provider --- raven/cli/onboard_commands.py | 23 +++++++++++++++++++++++ raven/config/schema.py | 1 + raven/providers/registry.py | 23 ++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/raven/cli/onboard_commands.py b/raven/cli/onboard_commands.py index b74f0986..4ad3784f 100644 --- a/raven/cli/onboard_commands.py +++ b/raven/cli/onboard_commands.py @@ -29,6 +29,7 @@ from __future__ import annotations +import os import sys from typing import Any, Callable, Optional @@ -138,6 +139,7 @@ def _t(en: str, zh: str) -> str: "label": "MiniMax (open-source partner)", "label_zh": "MiniMax(开源合作伙伴)", }, + {"name": "minimaxi", "label": "MiniMax CN", "label_zh": "MiniMax CN(国内站)"}, {"name": "deepseek", "label": "DeepSeek", "label_zh": "DeepSeek"}, {"name": "zai", "label": "Z.ai (Zhipu)", "label_zh": "Z.ai(智谱)"}, {"name": "dashscope", "label": "DashScope", "label_zh": "阿里云百炼"}, @@ -1248,6 +1250,12 @@ def _run_test_probe( " [dim]可运行 'raven provider test' 复查,或确认该模型确由此服务商提供。[/dim]", ) ) + console.print( + _t( + " [dim]For the redacted wire request: RAVEN_DEBUG_HTTP=1 raven doctor --probe[/dim]", + " [dim]查看已脱敏的实际请求: RAVEN_DEBUG_HTTP=1 raven doctor --probe[/dim]", + ) + ) print_probe_troubleshooting(provider) options = [(_t("Retry", "重试"), "retry")] if allow_repick: @@ -2789,6 +2797,7 @@ def run_wizard( yes: bool = False, reset: bool = False, skip_test: bool = False, + debug_http: bool = False, show_next_steps: bool = True, ) -> None: """Run the 6-step onboarding wizard end-to-end. @@ -2804,6 +2813,9 @@ def run_wizard( from loguru import logger as _logger _logger.disable("raven") + previous_debug = os.environ.get("RAVEN_DEBUG_HTTP") + if debug_http: + os.environ["RAVEN_DEBUG_HTTP"] = "1" try: _run_wizard_body( provider=provider, @@ -2823,6 +2835,11 @@ def run_wizard( show_next_steps=show_next_steps, ) finally: + if debug_http: + if previous_debug is None: + os.environ.pop("RAVEN_DEBUG_HTTP", None) + else: + os.environ["RAVEN_DEBUG_HTTP"] = previous_debug _logger.enable("raven") @@ -3044,6 +3061,11 @@ def onboard( "--skip-test", help="Skip the one-shot test message (avoids a billed call; connectivity is still checked)", ), + debug_http: bool = typer.Option( + False, + "--debug-http", + help="Print the redacted HTTP request for the one-shot test message", + ), ) -> None: """Six-step setup wizard: LLM provider → sandbox → channel → memory → deep research → import.""" run_wizard( @@ -3061,6 +3083,7 @@ def onboard( yes=yes, reset=reset, skip_test=skip_test, + debug_http=debug_http, ) diff --git a/raven/config/schema.py b/raven/config/schema.py index 14d454ba..7bf01a28 100644 --- a/raven/config/schema.py +++ b/raven/config/schema.py @@ -598,6 +598,7 @@ def _merge_renamed_sections(cls, data: Any) -> Any: gemini: GeminiProviderConfig = Field(default_factory=GeminiProviderConfig) # Google Gemini / Vertex AI moonshot: ProviderConfig = Field(default_factory=ProviderConfig) minimax: ProviderConfig = Field(default_factory=ProviderConfig) + minimaxi: ProviderConfig = Field(default_factory=ProviderConfig) minimax_global: ProviderConfig = Field(default_factory=ProviderConfig) minimax_cn: ProviderConfig = Field(default_factory=ProviderConfig) aihubmix: ProviderConfig = Field(default_factory=ProviderConfig) # AiHubMix API gateway diff --git a/raven/providers/registry.py b/raven/providers/registry.py index c78feeb1..5535fd79 100644 --- a/raven/providers/registry.py +++ b/raven/providers/registry.py @@ -486,6 +486,27 @@ def claims(self, model: str) -> bool: model_overrides=(), # Needed by `provider test` and the wizard preflight, which probe # /v1/models before any LiteLLM call resolves an endpoint. + default_api_base="https://api.minimax.io/v1", + ), + # MiniMax's mainland-China deployment: same OpenAI-compatible API and the + # same LiteLLM driver, a different host, and a key issued against a separate + # account -- so it is its own section rather than an api_base the user has + # to know to override. LiteLLM defaults the driver to the international + # host, so the address travels as MINIMAX_API_BASE. + ProviderSpec( + name="minimaxi", + keywords=("minimaxi",), + env_key="MINIMAX_API_KEY", + display_name="MiniMax CN", + via_driver="minimax", + skip_prefixes=("minimax/", "minimaxi/", "openrouter/"), + env_extras=(("MINIMAX_API_BASE", "{api_base}"),), + is_gateway=False, + is_local=False, + detect_by_key_prefix="", + detect_by_base_keyword="", + strip_model_prefix=False, + model_overrides=(), default_api_base="https://api.minimaxi.com/v1", ), ProviderSpec( @@ -496,7 +517,7 @@ def claims(self, model: str) -> bool: display_name="MiniMax Global (OAuth)", via_driver="anthropic", skip_prefixes=("anthropic/",), - default_api_base="https://api.minimax.io/anthropic/v1", + default_api_base="https://api.minimaxi.com/anthropic/v1", metadata_prefix="minimax", billing="plan", is_oauth=True, From 79fe1434cfbdecde9f116b770016dbfd8ada2688 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 17:06:58 +0800 Subject: [PATCH 3/7] fix: restore minimax oauth endpoint and drop debug option --- raven/cli/onboard_commands.py | 25 ++----------------------- raven/providers/registry.py | 7 +------ 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/raven/cli/onboard_commands.py b/raven/cli/onboard_commands.py index 4ad3784f..f7c81818 100644 --- a/raven/cli/onboard_commands.py +++ b/raven/cli/onboard_commands.py @@ -1250,12 +1250,6 @@ def _run_test_probe( " [dim]可运行 'raven provider test' 复查,或确认该模型确由此服务商提供。[/dim]", ) ) - console.print( - _t( - " [dim]For the redacted wire request: RAVEN_DEBUG_HTTP=1 raven doctor --probe[/dim]", - " [dim]查看已脱敏的实际请求: RAVEN_DEBUG_HTTP=1 raven doctor --probe[/dim]", - ) - ) print_probe_troubleshooting(provider) options = [(_t("Retry", "重试"), "retry")] if allow_repick: @@ -2797,7 +2791,6 @@ def run_wizard( yes: bool = False, reset: bool = False, skip_test: bool = False, - debug_http: bool = False, show_next_steps: bool = True, ) -> None: """Run the 6-step onboarding wizard end-to-end. @@ -2813,9 +2806,6 @@ def run_wizard( from loguru import logger as _logger _logger.disable("raven") - previous_debug = os.environ.get("RAVEN_DEBUG_HTTP") - if debug_http: - os.environ["RAVEN_DEBUG_HTTP"] = "1" try: _run_wizard_body( provider=provider, @@ -2835,11 +2825,6 @@ def run_wizard( show_next_steps=show_next_steps, ) finally: - if debug_http: - if previous_debug is None: - os.environ.pop("RAVEN_DEBUG_HTTP", None) - else: - os.environ["RAVEN_DEBUG_HTTP"] = previous_debug _logger.enable("raven") @@ -3060,12 +3045,7 @@ def onboard( False, "--skip-test", help="Skip the one-shot test message (avoids a billed call; connectivity is still checked)", - ), - debug_http: bool = typer.Option( - False, - "--debug-http", - help="Print the redacted HTTP request for the one-shot test message", - ), + ) ) -> None: """Six-step setup wizard: LLM provider → sandbox → channel → memory → deep research → import.""" run_wizard( @@ -3082,8 +3062,7 @@ def onboard( non_interactive=non_interactive, yes=yes, reset=reset, - skip_test=skip_test, - debug_http=debug_http, + skip_test=skip_test ) diff --git a/raven/providers/registry.py b/raven/providers/registry.py index 5535fd79..178dcb48 100644 --- a/raven/providers/registry.py +++ b/raven/providers/registry.py @@ -488,11 +488,6 @@ def claims(self, model: str) -> bool: # /v1/models before any LiteLLM call resolves an endpoint. default_api_base="https://api.minimax.io/v1", ), - # MiniMax's mainland-China deployment: same OpenAI-compatible API and the - # same LiteLLM driver, a different host, and a key issued against a separate - # account -- so it is its own section rather than an api_base the user has - # to know to override. LiteLLM defaults the driver to the international - # host, so the address travels as MINIMAX_API_BASE. ProviderSpec( name="minimaxi", keywords=("minimaxi",), @@ -517,7 +512,7 @@ def claims(self, model: str) -> bool: display_name="MiniMax Global (OAuth)", via_driver="anthropic", skip_prefixes=("anthropic/",), - default_api_base="https://api.minimaxi.com/anthropic/v1", + default_api_base="https://api.minimax.io/anthropic/v1", metadata_prefix="minimax", billing="plan", is_oauth=True, From 5c68eb8fffcb6549b6242335a4f24c0f63cb4a5e Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 17:08:53 +0800 Subject: [PATCH 4/7] chore(cli): remove unused onboarding import --- raven/cli/onboard_commands.py | 1 - 1 file changed, 1 deletion(-) diff --git a/raven/cli/onboard_commands.py b/raven/cli/onboard_commands.py index f7c81818..adab8242 100644 --- a/raven/cli/onboard_commands.py +++ b/raven/cli/onboard_commands.py @@ -29,7 +29,6 @@ from __future__ import annotations -import os import sys from typing import Any, Callable, Optional From 250d2239604cf93873f74f9a58506cb44d285a83 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 17:36:41 +0800 Subject: [PATCH 5/7] test: cover minimax regional endpoint routing --- tests/data/wire_model_baseline.json | 9 +++++ tests/test_cli_onboard_commands.py | 47 ++++++++++++++++++++++++--- tests/test_config_update_providers.py | 25 ++++++++++++++ tests/test_provider_catalog.py | 35 ++++++++++++++++++-- 4 files changed, 109 insertions(+), 7 deletions(-) diff --git a/tests/data/wire_model_baseline.json b/tests/data/wire_model_baseline.json index 469541d5..323bd60b 100644 --- a/tests/data/wire_model_baseline.json +++ b/tests/data/wire_model_baseline.json @@ -128,6 +128,15 @@ "vendorx/zz-probe-1": "vendorx/zz-probe-1", "zz-probe-1": "zz-probe-1" }, + "minimaxi": { + "minimax/zz-probe-1": "minimax/zz-probe-1", + "minimaxi-probe": "minimax/minimaxi-probe", + "minimaxi/vendorx/zz-probe-1": "minimax/vendorx/zz-probe-1", + "minimaxi/zz-probe-1": "minimax/zz-probe-1", + "openrouter/zz-probe-1": "openrouter/zz-probe-1", + "vendorx/zz-probe-1": "vendorx/zz-probe-1", + "zz-probe-1": "zz-probe-1" + }, "moonshot": { "moonshot-probe": "moonshot/moonshot-probe", "moonshot/vendorx/zz-probe-1": "moonshot/vendorx/zz-probe-1", diff --git a/tests/test_cli_onboard_commands.py b/tests/test_cli_onboard_commands.py index b441d216..2019da6c 100644 --- a/tests/test_cli_onboard_commands.py +++ b/tests/test_cli_onboard_commands.py @@ -201,6 +201,7 @@ def test_onboard_help_lists_all_flags() -> None: "--non-interactive", "--yes", "--reset", + "--debug-http", ): assert flag in out, f"missing flag in help: {flag}" @@ -3288,23 +3289,29 @@ def test_the_vendor_step_offers_litellm_names_the_picker_does_not_already_list() assert result["count"] > 50 -def test_minimax_precedes_deepseek_and_carries_the_open_source_partner_marker() -> None: +def test_the_minimax_rows_precede_deepseek_and_carry_the_open_source_partner_marker() -> None: """A deliberate placement, so a later reordering cannot drop it silently. "open-source partner" rather than a bare "partner": in a list of vendors the - short form reads as paid placement. Only the API-key entry is marked -- the - OAuth ones are the same vendor and already carry "(OAuth)". + short form reads as paid placement. Only the international API-key entry is + marked -- the CN row is the same vendor one host over, and the OAuth ones + already carry "(OAuth)". """ from raven.cli.onboard_commands import _CURATED_GROUPS api_key_group = next(g for g in _CURATED_GROUPS if g["kind"] == "api_key") names = [entry["name"] for entry in api_key_group["providers"]] - assert names.index("minimax") == names.index("deepseek") - 1 + assert names.index("minimaxi") == names.index("minimax") + 1, "the CN row left its vendor's side" + assert names.index("minimaxi") == names.index("deepseek") - 1 minimax = api_key_group["providers"][names.index("minimax")] assert minimax["label"] == "MiniMax (open-source partner)" assert minimax["label_zh"] == "MiniMax(开源合作伙伴)" + minimaxi = api_key_group["providers"][names.index("minimaxi")] + assert minimaxi["label"] == "MiniMax CN" + assert "partner" not in minimaxi["label"] + oauth_group = next(g for g in _CURATED_GROUPS if g["kind"] == "oauth") for entry in oauth_group["providers"]: assert "partner" not in entry["label"], entry["label"] @@ -4475,6 +4482,38 @@ def _cancelled(*a: Any, **kw: Any) -> Any: ) +def test_the_probed_endpoint_is_named_whenever_one_was_resolved( + tmp_env: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] +) -> None: + """A vendor like MiniMax ships an address and stores none, so the wizard + probes a URL the user never typed. Failing silently against it left the one + field worth checking invisible in exactly the case that needs it.""" + base = "https://api.minimax.io/v1" + + monkeypatch.setattr( + "raven.config.update_providers.test_provider", + lambda *a, **kw: {"ok": True, "status": "valid", "models_count": 2, "api_base": base}, + ) + ok, status, _models = onboard_commands._verify_provider("minimax") + assert (ok, status) == (True, "valid") + assert base in " ".join(capsys.readouterr().out.split()) + + monkeypatch.setattr( + "raven.config.update_providers.test_provider", + lambda *a, **kw: {"ok": False, "status": "invalid_key", "api_base": base, "error": "401"}, + ) + ok, status, _models = onboard_commands._verify_provider("minimax") + assert (ok, status) == (False, "invalid_key") + assert base in " ".join(capsys.readouterr().out.split()), "a failed probe hid the address it tried" + + monkeypatch.setattr( + "raven.config.update_providers.test_provider", + lambda *a, **kw: {"ok": True, "status": "valid", "models_count": 1}, + ) + onboard_commands._verify_provider("minimax") + assert "Endpoint" not in capsys.readouterr().out, "no address resolved must print no field" + + @pytest.mark.parametrize( ("flags", "expected"), [ diff --git a/tests/test_config_update_providers.py b/tests/test_config_update_providers.py index 6ae0a688..e39a952b 100644 --- a/tests/test_config_update_providers.py +++ b/tests/test_config_update_providers.py @@ -570,6 +570,31 @@ def handler(request: httpx.Request) -> httpx.Response: assert result["http_status"] == 200 +def test_test_provider_reports_the_address_it_probed(cfg_path: Path) -> None: + """MiniMax stores no api_base of its own -- the registry default is what the + probe resolves and contacts, so a caller that wants to name the endpoint has + no other way to learn which one that was.""" + from raven.providers.registry import find_by_name + + _seed_key(cfg_path, name="minimax", key="sk-minimax") + expected = find_by_name("minimax").default_api_base + seen: list[str] = [] + + def handler(request: httpx.Request) -> httpx.Response: + seen.append(str(request.url)) + return httpx.Response(200, json={"data": [{"id": "MiniMax-M2"}]}) + + result = probe_provider("minimax", config_path=cfg_path, transport=_mock_transport(handler)) + assert result["api_base"] == expected + assert seen == [expected.rstrip("/") + "/models"] + + def refuse(request: httpx.Request) -> httpx.Response: + return httpx.Response(401, json={}) + + refused = probe_provider("minimax", config_path=cfg_path, transport=_mock_transport(refuse)) + assert refused["api_base"] == expected, "a failed probe must still name the address it tried" + + def test_test_provider_200_extracts_model_ids(cfg_path: Path) -> None: _seed_key(cfg_path) diff --git a/tests/test_provider_catalog.py b/tests/test_provider_catalog.py index c27e5e17..7a8c7cb2 100644 --- a/tests/test_provider_catalog.py +++ b/tests/test_provider_catalog.py @@ -31,6 +31,7 @@ "dashscope", "moonshot", "minimax", + "minimaxi", "minimax_global", "minimax_cn", "hosted_vllm", @@ -39,9 +40,9 @@ } -def test_registry_has_exactly_21_providers() -> None: - assert len(PROVIDERS) == 21 - assert len(EXPECTED_PROVIDER_NAMES) == 21 +def test_registry_has_exactly_22_providers() -> None: + assert len(PROVIDERS) == 22 + assert len(EXPECTED_PROVIDER_NAMES) == 22 def test_registry_provider_name_set_is_pinned() -> None: @@ -108,6 +109,34 @@ def test_registry_and_schema_declare_the_same_providers() -> None: assert {spec.name for spec in PROVIDERS} == set(ProvidersConfig.model_fields) +def test_the_two_minimax_api_key_sections_reach_different_hosts(monkeypatch: pytest.MonkeyPatch) -> None: + """One vendor, two deployments, and a key issued for one that the other + refuses -- so which section a user picks has to decide where the request + lands. LiteLLM's minimax driver defaults to the international host, which is + why the CN section carries its own address into the environment instead of + leaving the driver to guess. + """ + import os + + from raven.providers.litellm_provider import LiteLLMProvider + + intl = find_by_name("minimax") + cn = find_by_name("minimaxi") + assert intl.default_api_base == "https://api.minimax.io/v1" + assert cn.default_api_base == "https://api.minimaxi.com/v1" + assert cn.model_prefix == "minimax", "LiteLLM has no minimaxi driver to route to" + + monkeypatch.delenv("MINIMAX_API_KEY", raising=False) + monkeypatch.delenv("MINIMAX_API_BASE", raising=False) + LiteLLMProvider(api_key="sk-cn", default_model="minimaxi/MiniMax-M2.1", provider_name="minimaxi") + assert os.environ["MINIMAX_API_BASE"] == "https://api.minimaxi.com/v1" + + monkeypatch.delenv("MINIMAX_API_KEY", raising=False) + monkeypatch.delenv("MINIMAX_API_BASE", raising=False) + LiteLLMProvider(api_key="sk-intl", default_model="minimax/MiniMax-M2.1", provider_name="minimax") + assert "MINIMAX_API_BASE" not in os.environ, "the international section must leave the driver's default alone" + + # Direct providers seeded in the model picker (issue #100). Each must expose a # non-empty default_model drawn from its curated shortlist, so the onboarding # fallback and the picker stay in sync and no provider defaults to empty. From 80faa75d36e5aa6fcebd7fdcbac8531bb83b3a2e Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 17:47:53 +0800 Subject: [PATCH 6/7] test(cli): remove stale debug-http expectation --- tests/test_cli_onboard_commands.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_cli_onboard_commands.py b/tests/test_cli_onboard_commands.py index 2019da6c..b37d1bb6 100644 --- a/tests/test_cli_onboard_commands.py +++ b/tests/test_cli_onboard_commands.py @@ -201,7 +201,6 @@ def test_onboard_help_lists_all_flags() -> None: "--non-interactive", "--yes", "--reset", - "--debug-http", ): assert flag in out, f"missing flag in help: {flag}" From 2af3befd98cce35136eb2b4dc35c031206ccf2c1 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 3 Sep 2026 18:04:38 +0800 Subject: [PATCH 7/7] chore(cli): apply ruff formatting --- raven/cli/onboard_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/raven/cli/onboard_commands.py b/raven/cli/onboard_commands.py index adab8242..477bdaa5 100644 --- a/raven/cli/onboard_commands.py +++ b/raven/cli/onboard_commands.py @@ -3044,7 +3044,7 @@ def onboard( False, "--skip-test", help="Skip the one-shot test message (avoids a billed call; connectivity is still checked)", - ) + ), ) -> None: """Six-step setup wizard: LLM provider → sandbox → channel → memory → deep research → import.""" run_wizard( @@ -3061,7 +3061,7 @@ def onboard( non_interactive=non_interactive, yes=yes, reset=reset, - skip_test=skip_test + skip_test=skip_test, )