fix: make quick start rollback on websocket failure

maintainer edit: stage Quick Start edits on a draft config so declining WebSocket/password setup cannot leave saveable provider defaults behind. Align beginner WebUI docs with the password-protected setup.
This commit is contained in:
chengyongru
2026-06-22 13:04:05 +08:00
committed by Xubin Ren
parent 9713fe2a3b
commit 9b52202f4a
5 changed files with 59 additions and 9 deletions
+9 -1
View File
@@ -400,7 +400,15 @@ The WebUI ships **inside the published wheel** — no extra build step. It is th
Merge this block into your existing config:
```json
{ "channels": { "websocket": { "enabled": true } } }
{
"channels": {
"websocket": {
"enabled": true,
"tokenIssueSecret": "your-webui-password",
"websocketRequiresToken": true
}
}
}
```
**2. Start the gateway**
+1 -1
View File
@@ -280,7 +280,7 @@ Tell me exactly what changed and whether I need to run /restart.
Exit interactive mode with `exit`, `quit`, `/exit`, `/quit`, `:q`, or `Ctrl+D`.
## 6. Choose Your Next Step
## 7. Choose Your Next Step
| Want to... | Go to |
|---|---|
+8 -4
View File
@@ -225,7 +225,9 @@ Merge them into one object:
},
"channels": {
"websocket": {
"enabled": true
"enabled": true,
"tokenIssueSecret": "your-webui-password",
"websocketRequiresToken": true
}
}
}
@@ -286,13 +288,15 @@ If this is a brand-new install and you have not configured anything else yet, re
},
"channels": {
"websocket": {
"enabled": true
"enabled": true,
"tokenIssueSecret": "your-webui-password",
"websocketRequiresToken": true
}
}
}
```
Replace `your-api-key`, `https://api.example.com/v1`, and `model-id-from-your-provider` with values from your provider.
Replace `your-api-key`, `https://api.example.com/v1`, `model-id-from-your-provider`, and `your-webui-password` with your own values.
For copyable provider-specific examples, use [`provider-cookbook.md`](./provider-cookbook.md).
@@ -316,7 +320,7 @@ Start the local browser UI:
nanobot gateway
```
Leave that terminal open, then open `http://127.0.0.1:8765` in your browser. If Quick Start enabled the WebSocket channel, enter the WebUI password you set in the wizard.
Leave that terminal open, then open `http://127.0.0.1:8765` in your browser. Enter the WebUI password you set in the wizard or the `tokenIssueSecret` value from your manual config.
Send this first message in the browser:
+6 -3
View File
@@ -1700,14 +1700,17 @@ def _configure_quick_start(config: Config) -> bool:
"Quick Start",
"Choose provider endpoint, add credentials and model, then enable the local WebUI channel.",
)
if not _configure_quick_start_provider(config):
draft = config.model_copy(deep=True)
if not _configure_quick_start_provider(draft):
_pause()
return False
if not _enable_quick_start_websocket_defaults(config):
if not _enable_quick_start_websocket_defaults(draft):
_pause()
return False
_show_quick_start_summary(config)
_show_quick_start_summary(draft)
_pause("Press Enter to save and exit...")
for field_name in type(config).model_fields:
setattr(config, field_name, getattr(draft, field_name))
return True
+35
View File
@@ -983,6 +983,41 @@ class TestMainMenuUpdate:
assert websocket["websocketRequiresToken"] is True
assert websocket["tokenIssueSecret"] == "webui-secret"
def test_quick_start_websocket_decline_rolls_back_provider_defaults(self, monkeypatch):
"""A failed WebSocket step should not leave saveable Quick Start defaults behind."""
config = Config()
original = config.model_dump(by_alias=True)
class FakePrompt:
def __init__(self, response):
self.response = response
def ask(self):
return self.response
monkeypatch.setattr(onboard_wizard.console, "clear", lambda: None)
monkeypatch.setattr(onboard_wizard.console, "print", lambda *a, **kw: None)
monkeypatch.setattr(onboard_wizard, "_show_section_header", lambda *a, **kw: None)
monkeypatch.setattr(onboard_wizard, "_show_quick_start_progress", lambda *a, **kw: None)
monkeypatch.setattr(onboard_wizard, "_select_with_back", lambda *a, **kw: "DeepSeek")
monkeypatch.setattr(onboard_wizard, "_input_text", lambda *a, **kw: "sk-ds-test")
monkeypatch.setattr(
onboard_wizard,
"_input_model_with_autocomplete",
lambda *a, **kw: "deepseek-v4-flash",
)
monkeypatch.setattr(
onboard_wizard,
"questionary",
SimpleNamespace(confirm=lambda *a, **kw: FakePrompt(False)),
)
monkeypatch.setattr(onboard_wizard, "_pause", lambda message="": None)
assert onboard_wizard._configure_quick_start(config) is False
assert config.model_dump(by_alias=True) == original
assert getattr(config.channels, "websocket", None) is None
def test_quick_start_provider_choice_asks_for_model_id(self, monkeypatch):
"""Known providers should ask users for the model instead of fetching one."""
config = Config()