fix: keep onboard cli defaults unchanged
Remove the PR changes that made nanobot onboard default to the wizard, added --defaults, added non-TTY fallback behavior, and changed the Docker smoke command. Keep Quick Start available through nanobot onboard --wizard.
This commit is contained in:
@@ -234,7 +234,7 @@ Windows PowerShell:
|
||||
irm https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
The default command installs or upgrades `nanobot-ai` from PyPI, then starts `nanobot onboard`. It avoids system-wide pip installs by using an active virtual environment, `uv`, `pipx`, or a managed venv under `~/.nanobot/venv`. If Quick Start finishes, skip the manual initialize/configure steps below and go straight to **Test one message**.
|
||||
The default command installs or upgrades `nanobot-ai` from PyPI, then starts `nanobot onboard --wizard`. It avoids system-wide pip installs by using an active virtual environment, `uv`, `pipx`, or a managed venv under `~/.nanobot/venv`. If Quick Start finishes, skip the manual initialize/configure steps below and go straight to **Test one message**.
|
||||
|
||||
To preview the plan without changing your environment, pass `--dry-run`; combine it with `--dev` when you want to preview the main-branch install.
|
||||
|
||||
@@ -296,13 +296,13 @@ Skip this step if the one-command setup already started the wizard and Quick Sta
|
||||
nanobot onboard
|
||||
```
|
||||
|
||||
Use `nanobot onboard --defaults` if you want the old non-interactive default config.
|
||||
Use `nanobot onboard --wizard` if you prefer an interactive setup.
|
||||
|
||||
**2. Configure** (`~/.nanobot/config.json`)
|
||||
|
||||
Skip this step if you already configured provider and model settings in the wizard.
|
||||
|
||||
`nanobot onboard --defaults` creates `~/.nanobot/config.json` and `~/.nanobot/workspace/`. Configure these **two parts** in the config file. Add or merge the following blocks into the existing file instead of replacing the whole file.
|
||||
`nanobot onboard` creates `~/.nanobot/config.json` and `~/.nanobot/workspace/`. Configure these **two parts** in the config file. Add or merge the following blocks into the existing file instead of replacing the whole file.
|
||||
|
||||
The example below uses a generic OpenAI-compatible `custom` provider so the compact path does not recommend one hosted service. Provider examples are recipes, not rankings or endorsements. For copyable provider-specific setup, see [Provider Cookbook](./docs/provider-cookbook.md).
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ The key (`webhook`) becomes the config section name. The value points to your `B
|
||||
```bash
|
||||
python -m pip install -e .
|
||||
nanobot plugins list # verify "Webhook" shows as "plugin"
|
||||
nanobot onboard --defaults # auto-adds default config for detected plugins
|
||||
nanobot onboard # auto-adds default config for detected plugins
|
||||
```
|
||||
|
||||
Edit `~/.nanobot/config.json`:
|
||||
@@ -507,7 +507,7 @@ async def start(self) -> None:
|
||||
|
||||
`allowFrom` is handled automatically by `_handle_message()` — you don't need to check it yourself.
|
||||
|
||||
Override `default_config()` so `nanobot onboard --defaults` auto-populates `config.json`:
|
||||
Override `default_config()` so `nanobot onboard` auto-populates `config.json`:
|
||||
|
||||
```python
|
||||
@classmethod
|
||||
|
||||
@@ -7,8 +7,8 @@ Use this page when you know what you want to run and need the command shape. For
|
||||
| Goal | Command | Notes |
|
||||
|---|---|---|
|
||||
| Check the install | `nanobot --version` | If this fails, try `python -m nanobot --version` |
|
||||
| Use guided setup | `nanobot onboard` | Best when you prefer prompts over hand-editing JSON |
|
||||
| Create or refresh defaults | `nanobot onboard --defaults` | Creates `~/.nanobot/config.json` and `~/.nanobot/workspace/` without the wizard |
|
||||
| Create or refresh config | `nanobot onboard` | Creates `~/.nanobot/config.json` and `~/.nanobot/workspace/` |
|
||||
| Use guided setup | `nanobot onboard --wizard` | Best when you prefer prompts over hand-editing JSON |
|
||||
| Check config without calling a model | `nanobot status` | Reads the default config and summarizes the active model/provider |
|
||||
| Send one test message | `nanobot agent -m "Hello!"` | First proof that install, config, provider, model, and workspace all work |
|
||||
| Chat in the terminal | `nanobot agent` | Interactive local chat; exit with `exit`, `/exit`, `:q`, or `Ctrl+D` |
|
||||
@@ -52,13 +52,9 @@ Long-running commands keep working until you stop them. Press `Ctrl+C` in that t
|
||||
|
||||
| Command | Description |
|
||||
|---|---|
|
||||
| `nanobot onboard` | Use the interactive setup wizard |
|
||||
| `nanobot onboard --defaults` | Initialize or refresh the default config and workspace without the wizard |
|
||||
| `nanobot onboard --defaults --config <path> --workspace <path>` | Initialize or refresh a specific instance without the wizard |
|
||||
|
||||
Without `--defaults`, `nanobot onboard` opens the wizard only when stdin and stdout are attached to a terminal. In scripts, CI, and Docker non-TTY runs, it falls back to the defaults setup.
|
||||
|
||||
When `--defaults` refreshes an existing config in scripts, CI, or Docker non-TTY runs, it preserves existing values without prompting. In an interactive terminal, nanobot still asks before replacing an existing config with fresh defaults.
|
||||
| `nanobot onboard` | Initialize or refresh the default config and workspace |
|
||||
| `nanobot onboard --wizard` | Use the interactive setup wizard |
|
||||
| `nanobot onboard --config <path> --workspace <path>` | Initialize or refresh a specific instance |
|
||||
|
||||
Default paths:
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ The default instance lives under `~/.nanobot/`:
|
||||
You can override both with command flags:
|
||||
|
||||
```bash
|
||||
nanobot onboard --defaults --config ./bot-a/config.json --workspace ./bot-a/workspace
|
||||
nanobot onboard --config ./bot-a/config.json --workspace ./bot-a/workspace
|
||||
nanobot agent --config ./bot-a/config.json --workspace ./bot-a/workspace -m "Hello"
|
||||
nanobot gateway --config ./bot-a/config.json --workspace ./bot-a/workspace
|
||||
```
|
||||
|
||||
@@ -11,7 +11,7 @@ The generated `config.json` uses camelCase keys such as `apiKey` and `intervalS`
|
||||
For setup and runtime failures, follow the diagnosis order in [`troubleshooting.md`](./troubleshooting.md) before changing multiple config areas at once.
|
||||
|
||||
> [!NOTE]
|
||||
> If your config file is older than the current schema, you can refresh it without overwriting your existing values: run `nanobot onboard --defaults`, then answer `N` when asked whether to overwrite the config. nanobot will merge in missing default fields and keep your current settings.
|
||||
> If your config file is older than the current schema, you can refresh it without overwriting your existing values: run `nanobot onboard`, then answer `N` when asked whether to overwrite the config. nanobot will merge in missing default fields and keep your current settings.
|
||||
|
||||
## Quick Jump
|
||||
|
||||
|
||||
+4
-4
@@ -59,9 +59,9 @@ Restart the deployed process after editing `config.json`. Long-running processes
|
||||
### Docker Compose
|
||||
|
||||
```bash
|
||||
docker compose run --rm nanobot-cli onboard --defaults # first-time setup
|
||||
vim ~/.nanobot/config.json # add API keys
|
||||
docker compose up -d nanobot-gateway # start gateway
|
||||
docker compose run --rm nanobot-cli onboard # first-time setup
|
||||
vim ~/.nanobot/config.json # add API keys
|
||||
docker compose up -d nanobot-gateway # start gateway
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -77,7 +77,7 @@ docker compose down # stop
|
||||
docker build -t nanobot .
|
||||
|
||||
# Initialize config (first time only)
|
||||
docker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot onboard --defaults
|
||||
docker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot onboard
|
||||
|
||||
# Edit config on host to add API keys
|
||||
vim ~/.nanobot/config.json
|
||||
|
||||
@@ -10,9 +10,9 @@ If you want each instance to have its own dedicated workspace from the start, pa
|
||||
|
||||
```bash
|
||||
# Create separate instance configs and workspaces
|
||||
nanobot onboard --defaults --config ~/.nanobot-telegram/config.json --workspace ~/.nanobot-telegram/workspace
|
||||
nanobot onboard --defaults --config ~/.nanobot-discord/config.json --workspace ~/.nanobot-discord/workspace
|
||||
nanobot onboard --defaults --config ~/.nanobot-feishu/config.json --workspace ~/.nanobot-feishu/workspace
|
||||
nanobot onboard --config ~/.nanobot-telegram/config.json --workspace ~/.nanobot-telegram/workspace
|
||||
nanobot onboard --config ~/.nanobot-discord/config.json --workspace ~/.nanobot-discord/workspace
|
||||
nanobot onboard --config ~/.nanobot-feishu/config.json --workspace ~/.nanobot-feishu/workspace
|
||||
```
|
||||
|
||||
**Configure each instance:**
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ tools:
|
||||
|
||||
To allow the agent to set its configuration (e.g. switch models, adjust parameters), set `tools.my.allow_set: true`.
|
||||
|
||||
Legacy `tools.myEnabled` / `tools.mySet` keys are auto-migrated on load, and rewritten in-place the next time `nanobot onboard --defaults` refreshes the config.
|
||||
Legacy `tools.myEnabled` / `tools.mySet` keys are auto-migrated on load, and rewritten in-place the next time `nanobot onboard` refreshes the config.
|
||||
|
||||
All modifications are held in memory only — restart restores defaults.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Match the recipe to the credential or endpoint you already have:
|
||||
|
||||
## How to Use a Recipe
|
||||
|
||||
1. Install nanobot and run `nanobot onboard` once so `~/.nanobot/config.json` exists. Use `nanobot onboard --defaults` if you prefer editing JSON by hand.
|
||||
1. Install nanobot and run `nanobot onboard` once so `~/.nanobot/config.json` exists. Use `nanobot onboard --wizard` if you prefer prompts over hand-editing JSON.
|
||||
2. Put secrets in environment variables when possible.
|
||||
3. Merge the recipe snippet into `~/.nanobot/config.json`.
|
||||
4. Run `nanobot status`.
|
||||
|
||||
+4
-4
@@ -32,7 +32,7 @@ On Windows PowerShell:
|
||||
irm https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
The default command installs or upgrades `nanobot-ai` from PyPI, then starts `nanobot onboard`. It avoids system-wide pip installs by using an active virtual environment, `uv`, `pipx`, or a managed venv under `~/.nanobot/venv`. If Quick Start finishes, skip the manual initialize/configure steps and go straight to [Check the Setup](#4-check-the-setup).
|
||||
The default command installs or upgrades `nanobot-ai` from PyPI, then starts `nanobot onboard --wizard`. It avoids system-wide pip installs by using an active virtual environment, `uv`, `pipx`, or a managed venv under `~/.nanobot/venv`. If Quick Start finishes, skip the manual initialize/configure steps and go straight to [Check the Setup](#4-check-the-setup).
|
||||
|
||||
To preview the plan without changing your environment, pass `--dry-run`; combine it with `--dev` when you want to preview the main-branch install.
|
||||
|
||||
@@ -102,10 +102,10 @@ Skip this section if the one-command setup already started the wizard and Quick
|
||||
nanobot onboard
|
||||
```
|
||||
|
||||
Use the old non-interactive defaults path if you prefer editing JSON by hand:
|
||||
Use the wizard if you prefer prompts instead of editing JSON by hand:
|
||||
|
||||
```bash
|
||||
nanobot onboard --defaults
|
||||
nanobot onboard --wizard
|
||||
```
|
||||
|
||||
Initialization creates:
|
||||
@@ -115,7 +115,7 @@ Initialization creates:
|
||||
| `~/.nanobot/config.json` | Main settings file for providers, models, channels, tools, gateway, and API |
|
||||
| `~/.nanobot/workspace/` | Agent workspace for memory, sessions, heartbeat tasks, skills, and artifacts |
|
||||
|
||||
If you already have a config, `nanobot onboard --defaults` can refresh missing default fields without overwriting your existing values.
|
||||
If you already have a config, `nanobot onboard` can refresh missing default fields without overwriting your existing values.
|
||||
|
||||
## 3. Configure a Provider
|
||||
|
||||
|
||||
@@ -139,16 +139,16 @@ Use `python3 -m nanobot --version` or `py -m nanobot --version` if that is the P
|
||||
The one-command installer starts this for you after installation. If you installed manually, run:
|
||||
|
||||
```bash
|
||||
nanobot onboard
|
||||
nanobot onboard --wizard
|
||||
```
|
||||
|
||||
If `nanobot` is not found, run:
|
||||
|
||||
```bash
|
||||
python -m nanobot onboard
|
||||
python -m nanobot onboard --wizard
|
||||
```
|
||||
|
||||
Use `python3 -m nanobot onboard` or `py -m nanobot onboard` if that is the Python command that worked in step 2.
|
||||
Use `python3 -m nanobot onboard --wizard` or `py -m nanobot onboard --wizard` if that is the Python command that worked in step 2.
|
||||
|
||||
The wizard is a terminal menu. It is not a graphical app, but it lets you choose options instead of hand-editing every JSON field.
|
||||
|
||||
@@ -225,13 +225,13 @@ Merge them into one object:
|
||||
}
|
||||
```
|
||||
|
||||
Notice the comma after the `providers` block. JSON needs commas between sibling sections, but not after the last section. If this feels hard, use `nanobot onboard` whenever possible.
|
||||
Notice the comma after the `providers` block. JSON needs commas between sibling sections, but not after the last section. If this feels hard, use `nanobot onboard --wizard` whenever possible.
|
||||
|
||||
## 6. Manual Setup: Config Fallback
|
||||
|
||||
Use this only if the wizard is unavailable or you prefer opening the file yourself.
|
||||
|
||||
Run `nanobot onboard --defaults` first if `~/.nanobot/config.json` does not exist yet.
|
||||
Run `nanobot onboard` first if `~/.nanobot/config.json` does not exist yet.
|
||||
|
||||
Use one of these commands:
|
||||
|
||||
@@ -340,7 +340,7 @@ Do not change many things at once. Check the exact error:
|
||||
|---|---|
|
||||
| `JSON parse error` | The config file has a missing comma, extra comma, or mismatched brace. Copy the example again. |
|
||||
| `401`, `unauthorized`, or `invalid API key` | The API key is wrong, expired, has extra spaces, or was pasted under the wrong provider. |
|
||||
| `model not found` | Your account cannot use the default model. Return to `nanobot onboard`, choose `Advanced Settings`, then edit `Model Presets`. |
|
||||
| `model not found` | Your account cannot use the default model. Return to `nanobot onboard --wizard`, choose `Advanced Settings`, then edit `Model Presets`. |
|
||||
| `nanobot: command not found` | The install worked in Python, but your shell cannot find the script. Use `python -m nanobot ...`, `python3 -m nanobot ...`, or `py -m nanobot ...`, matching the Python command that worked earlier. |
|
||||
| No response after editing config | Restart the command. Long-running processes read config when they start. |
|
||||
|
||||
|
||||
+10
-36
@@ -432,36 +432,16 @@ def main(
|
||||
# ============================================================================
|
||||
|
||||
|
||||
def _onboard_can_prompt() -> bool:
|
||||
"""Return True when onboard can safely show interactive prompts."""
|
||||
return sys.stdin.isatty() and sys.stdout.isatty()
|
||||
|
||||
|
||||
@app.command()
|
||||
def onboard(
|
||||
workspace: str | None = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
||||
config: str | None = typer.Option(None, "--config", "-c", help="Path to config file"),
|
||||
wizard: bool = typer.Option(False, "--wizard", help="Use interactive wizard (default)"),
|
||||
defaults: bool = typer.Option(
|
||||
False,
|
||||
"--defaults",
|
||||
help="Create or refresh the default config without the wizard",
|
||||
),
|
||||
wizard: bool = typer.Option(False, "--wizard", help="Use interactive wizard"),
|
||||
):
|
||||
"""Initialize nanobot configuration and workspace."""
|
||||
from nanobot.config.loader import get_config_path, load_config, save_config, set_config_path
|
||||
from nanobot.config.schema import Config
|
||||
|
||||
can_prompt = _onboard_can_prompt()
|
||||
wants_wizard = wizard or not defaults
|
||||
use_wizard = wants_wizard and not defaults and can_prompt
|
||||
default_fallback = wants_wizard and not use_wizard and not defaults
|
||||
default_refresh_without_prompt = defaults and not can_prompt
|
||||
if default_fallback:
|
||||
console.print(
|
||||
"[yellow]No interactive terminal detected; using --defaults setup instead.[/yellow]"
|
||||
)
|
||||
|
||||
if config:
|
||||
config_path = Path(config).expanduser().resolve()
|
||||
set_config_path(config_path)
|
||||
@@ -474,20 +454,10 @@ def onboard(
|
||||
loaded.agents.defaults.workspace = workspace
|
||||
return loaded
|
||||
|
||||
def _refresh_existing_config() -> Config:
|
||||
refreshed = _apply_workspace_override(load_config(config_path))
|
||||
save_config(refreshed, config_path)
|
||||
console.print(
|
||||
f"[green]✓[/green] Config refreshed at {config_path} (existing values preserved)"
|
||||
)
|
||||
return refreshed
|
||||
|
||||
# Create or update config
|
||||
if config_path.exists():
|
||||
if use_wizard:
|
||||
if wizard:
|
||||
config = _apply_workspace_override(load_config(config_path))
|
||||
elif default_fallback or default_refresh_without_prompt:
|
||||
config = _refresh_existing_config()
|
||||
else:
|
||||
console.print(f"[yellow]Config already exists at {config_path}[/yellow]")
|
||||
console.print(
|
||||
@@ -501,16 +471,20 @@ def onboard(
|
||||
save_config(config, config_path)
|
||||
console.print(f"[green]✓[/green] Config reset to defaults at {config_path}")
|
||||
else:
|
||||
config = _refresh_existing_config()
|
||||
config = _apply_workspace_override(load_config(config_path))
|
||||
save_config(config, config_path)
|
||||
console.print(
|
||||
f"[green]✓[/green] Config refreshed at {config_path} (existing values preserved)"
|
||||
)
|
||||
else:
|
||||
config = _apply_workspace_override(Config())
|
||||
# In wizard mode, don't save yet - the wizard will handle saving if should_save=True
|
||||
if not use_wizard:
|
||||
if not wizard:
|
||||
save_config(config, config_path)
|
||||
console.print(f"[green]✓[/green] Created config at {config_path}")
|
||||
|
||||
# Run interactive wizard if enabled
|
||||
if use_wizard:
|
||||
if wizard:
|
||||
from nanobot.cli.onboard import run_onboard
|
||||
|
||||
try:
|
||||
@@ -544,7 +518,7 @@ def onboard(
|
||||
|
||||
console.print(f"\n{__logo__} nanobot is ready!")
|
||||
console.print("\nNext steps:")
|
||||
if use_wizard:
|
||||
if wizard:
|
||||
console.print(f" 1. Chat: [cyan]{agent_cmd}[/cyan]")
|
||||
console.print(f" 2. Start gateway: [cyan]{gateway_cmd}[/cyan]")
|
||||
else:
|
||||
|
||||
+10
-89
@@ -91,13 +91,12 @@ def mock_paths():
|
||||
|
||||
|
||||
def test_onboard_fresh_install(mock_paths):
|
||||
"""No existing config in non-TTY mode should fall back to defaults."""
|
||||
"""No existing config — should create from scratch."""
|
||||
config_file, workspace_dir, mock_ws = mock_paths
|
||||
|
||||
result = runner.invoke(app, ["onboard"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No interactive terminal detected" in result.stdout
|
||||
assert "Created config" in result.stdout
|
||||
assert "Created workspace" in result.stdout
|
||||
assert "nanobot is ready" in result.stdout
|
||||
@@ -108,13 +107,12 @@ def test_onboard_fresh_install(mock_paths):
|
||||
assert mock_ws.call_args.args == (expected_workspace,)
|
||||
|
||||
|
||||
def test_onboard_existing_config_refresh(mock_paths, monkeypatch):
|
||||
def test_onboard_existing_config_refresh(mock_paths):
|
||||
"""Config exists, user declines overwrite — should refresh (load-merge-save)."""
|
||||
config_file, workspace_dir, _ = mock_paths
|
||||
config_file.write_text('{"existing": true}')
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: True)
|
||||
|
||||
result = runner.invoke(app, ["onboard", "--defaults"], input="n\n")
|
||||
result = runner.invoke(app, ["onboard"], input="n\n")
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Config already exists" in result.stdout
|
||||
@@ -123,62 +121,12 @@ def test_onboard_existing_config_refresh(mock_paths, monkeypatch):
|
||||
assert (workspace_dir / "AGENTS.md").exists()
|
||||
|
||||
|
||||
def test_onboard_non_tty_existing_config_refreshes_without_prompt(mock_paths):
|
||||
"""Default onboard should not ask overwrite when falling back outside a TTY."""
|
||||
config_file, workspace_dir, _ = mock_paths
|
||||
config_file.write_text("{}")
|
||||
|
||||
result = runner.invoke(app, ["onboard"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No interactive terminal detected" in result.stdout
|
||||
assert "Config already exists" not in result.stdout
|
||||
assert "existing values preserved" in result.stdout
|
||||
assert workspace_dir.exists()
|
||||
|
||||
|
||||
def test_onboard_defaults_non_tty_existing_config_preserves_values_without_prompt(
|
||||
tmp_path, monkeypatch
|
||||
):
|
||||
"""Explicit --defaults should refresh existing configs without prompts outside a TTY."""
|
||||
config_path = tmp_path / "config.json"
|
||||
workspace_path = tmp_path / "workspace"
|
||||
config_path.write_text(
|
||||
json.dumps({"agents": {"defaults": {"model": "custom/keep"}}}),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: False)
|
||||
monkeypatch.setattr("nanobot.channels.registry.discover_all", lambda: {})
|
||||
|
||||
result = runner.invoke(
|
||||
app,
|
||||
[
|
||||
"onboard",
|
||||
"--defaults",
|
||||
"--config",
|
||||
str(config_path),
|
||||
"--workspace",
|
||||
str(workspace_path),
|
||||
],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Config already exists" not in result.stdout
|
||||
assert "Overwrite?" not in result.stdout
|
||||
assert "existing values preserved" in result.stdout
|
||||
saved = Config.model_validate(json.loads(config_path.read_text(encoding="utf-8")))
|
||||
assert saved.agents.defaults.model == "custom/keep"
|
||||
assert saved.workspace_path == workspace_path
|
||||
|
||||
|
||||
def test_onboard_existing_config_overwrite(mock_paths, monkeypatch):
|
||||
def test_onboard_existing_config_overwrite(mock_paths):
|
||||
"""Config exists, user confirms overwrite — should reset to defaults."""
|
||||
config_file, workspace_dir, _ = mock_paths
|
||||
config_file.write_text('{"existing": true}')
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: True)
|
||||
|
||||
result = runner.invoke(app, ["onboard", "--defaults"], input="y\n")
|
||||
result = runner.invoke(app, ["onboard"], input="y\n")
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Config already exists" in result.stdout
|
||||
@@ -186,14 +134,13 @@ def test_onboard_existing_config_overwrite(mock_paths, monkeypatch):
|
||||
assert workspace_dir.exists()
|
||||
|
||||
|
||||
def test_onboard_existing_workspace_safe_create(mock_paths, monkeypatch):
|
||||
def test_onboard_existing_workspace_safe_create(mock_paths):
|
||||
"""Workspace exists — should not recreate, but still add missing templates."""
|
||||
config_file, workspace_dir, _ = mock_paths
|
||||
workspace_dir.mkdir(parents=True)
|
||||
config_file.write_text("{}")
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: True)
|
||||
|
||||
result = runner.invoke(app, ["onboard", "--defaults"], input="n\n")
|
||||
result = runner.invoke(app, ["onboard"], input="n\n")
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Created workspace" not in result.stdout
|
||||
@@ -217,7 +164,6 @@ def test_onboard_help_shows_workspace_and_config_options():
|
||||
assert "--config" in stripped_output
|
||||
assert "-c" in stripped_output
|
||||
assert "--wizard" in stripped_output
|
||||
assert "--defaults" in stripped_output
|
||||
assert "--dir" not in stripped_output
|
||||
|
||||
|
||||
@@ -226,13 +172,12 @@ def test_onboard_interactive_discard_does_not_save_or_create_workspace(mock_path
|
||||
|
||||
from nanobot.cli.onboard import OnboardResult
|
||||
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: True)
|
||||
monkeypatch.setattr(
|
||||
"nanobot.cli.onboard.run_onboard",
|
||||
lambda initial_config: OnboardResult(config=initial_config, should_save=False),
|
||||
)
|
||||
|
||||
result = runner.invoke(app, ["onboard"])
|
||||
result = runner.invoke(app, ["onboard", "--wizard"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No changes were saved" in result.stdout
|
||||
@@ -248,14 +193,7 @@ def test_onboard_uses_explicit_config_and_workspace_paths(tmp_path, monkeypatch)
|
||||
|
||||
result = runner.invoke(
|
||||
app,
|
||||
[
|
||||
"onboard",
|
||||
"--defaults",
|
||||
"--config",
|
||||
str(config_path),
|
||||
"--workspace",
|
||||
str(workspace_path),
|
||||
],
|
||||
["onboard", "--config", str(config_path), "--workspace", str(workspace_path)],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
@@ -279,12 +217,11 @@ def test_onboard_wizard_preserves_explicit_config_in_next_steps(tmp_path, monkey
|
||||
"nanobot.cli.onboard.run_onboard",
|
||||
lambda initial_config: OnboardResult(config=initial_config, should_save=True),
|
||||
)
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: True)
|
||||
monkeypatch.setattr("nanobot.channels.registry.discover_all", lambda: {})
|
||||
|
||||
result = runner.invoke(
|
||||
app,
|
||||
["onboard", "--config", str(config_path), "--workspace", str(workspace_path)],
|
||||
["onboard", "--wizard", "--config", str(config_path), "--workspace", str(workspace_path)],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
@@ -295,22 +232,6 @@ def test_onboard_wizard_preserves_explicit_config_in_next_steps(tmp_path, monkey
|
||||
assert f"nanobot gateway --config {resolved_config}" in compact_output
|
||||
|
||||
|
||||
def test_onboard_wizard_non_tty_falls_back_to_defaults(mock_paths, monkeypatch):
|
||||
config_file, _workspace_dir, _ = mock_paths
|
||||
|
||||
monkeypatch.setattr("nanobot.cli.commands._onboard_can_prompt", lambda: False)
|
||||
monkeypatch.setattr(
|
||||
"nanobot.cli.onboard.run_onboard",
|
||||
lambda initial_config: (_ for _ in ()).throw(AssertionError("should not prompt")),
|
||||
)
|
||||
|
||||
result = runner.invoke(app, ["onboard", "--wizard"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No interactive terminal detected" in result.stdout
|
||||
assert config_file.exists()
|
||||
|
||||
|
||||
def test_config_matches_github_copilot_codex_with_hyphen_prefix():
|
||||
config = Config()
|
||||
config.agents.defaults.model = "github-copilot/gpt-5.3-codex"
|
||||
|
||||
@@ -8,8 +8,8 @@ echo "=== Building Docker image ==="
|
||||
docker build -t "$IMAGE_NAME" .
|
||||
|
||||
echo ""
|
||||
echo "=== Running 'nanobot onboard --defaults' ==="
|
||||
docker run --name nanobot-test-run "$IMAGE_NAME" onboard --defaults
|
||||
echo "=== Running 'nanobot onboard' ==="
|
||||
docker run --name nanobot-test-run "$IMAGE_NAME" onboard
|
||||
|
||||
echo ""
|
||||
echo "=== Running 'nanobot status' ==="
|
||||
|
||||
Reference in New Issue
Block a user