Skip to content

fix(cli): verify onboard models with real probes and harden the wizard#102

Open
0xKT wants to merge 9 commits into
mainfrom
feat/onboard_verify_hardening
Open

fix(cli): verify onboard models with real probes and harden the wizard#102
0xKT wants to merge 9 commits into
mainfrom
feat/onboard_verify_hardening

Conversation

@0xKT

@0xKT 0xKT commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Harden the raven onboard wizard, which reported false "connected" results,
could trap or crash mid-flow, and billed silently in CI. One file
(raven/cli/onboard_commands.py) plus its tests; no schema/config changes.

  • Real verification instead of a connectivity check: memory LLM and embedding
    send a real POST /chat/completions / /embeddings probe (was GET /models,
    which greenlit models the endpoint doesn't serve); custom providers are probed
    too. Embedding takes the model id directly instead of showing a misleading
    chat-model list. A malformed base_url no longer crashes (catches InvalidURL).
  • No dead ends: test-message failure offers Re-enter key / Switch provider; a
    required EverOS role can give up EverOS (keep Markdown) instead of looping;
    the main-model empty submit uses the default instead of exiting; Ctrl+C exits
    every menu; Step 1 requires at least one provider and a default model;
    required channel fields re-prompt on empty; scancode reverts the enable on any
    non-login exit.
  • Config safety: a failed provider config is cleared or restored on switch;
    _memory_enabled requires both llm and embedding; key / URL / channel inputs
    are stripped.
  • --skip-test skips the billed test call (connectivity is still checked); the
    capability hint no longer renders like an error; --reset help and setup
    warnings clarified.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

  • uv run pytest tests/test_cli_onboard_commands.py -q -> 88 passed; ruff
    check/format clean.

  • Real DeepSeek: probes reject wrong / chat-only models (HTTP 400 / 404) and
    pass a valid one; send_probe returns a real reply and raises on a bad model;
    a malformed base_url returns no list without crashing; --skip-test skips the
    chat call while a control run sends one.

  • Relevant tests pass locally

  • Relevant lint / type checks pass locally

  • User-facing docs or screenshots are updated when needed

Risk

  • Security impact considered
  • Backward compatibility considered
  • Rollback path is clear for risky changes

--skip-test defaults off, so non-interactive behavior is unchanged; no
schema/config changes; rollback is reverting the branch.

Related Issues

Fixes #81

0xKT and others added 8 commits July 8, 2026 19:58
Onboard's EverOS memory setup reported a false green whenever an endpoint
answered GET /models but could not serve the picked model (reusing a
DeepSeek chat endpoint for embedding, or a memory-LLM model the endpoint
does not offer). It also had inescapable navigation loops and an
unstripped API key that could build an illegal Authorization header.

- Replace the connectivity-only _probe_everos_endpoint with real capability
  probes: _probe_everos_chat (POST /chat/completions) for the memory LLM and
  _probe_everos_embedding (POST /embeddings) for embedding. Guard the JSON
  shape and catch httpx.InvalidURL so a malformed base_url never crashes the
  wizard; apply the same InvalidURL guard to _fetch_everos_models.
- Embedding no longer fetches/shows the /models list (chat models on a
  reused chat endpoint mislead as embedding candidates); the id is entered
  directly, guided by an example and a capability hint, with the real probe
  as the arbiter.
- Strip api_key / base_url / channel fields on input.
- Gate _memory_enabled on both required models (llm and embedding).
- Navigation: the model picker's empty submit falls back to the default
  instead of exiting the wizard; a required EverOS role offers a bounded
  "give up EverOS" exit (falls back to Markdown) instead of looping; reprint
  switch-provider guidance when the embedding step bounces back.
- Render the capability hint with highlight=False so it does not read as an
  error.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
…lure

Custom OpenAI-compatible providers skipped the test message entirely (the
highest-typo-risk case: a hand-typed base_url/model passed with no real
request). They now get the same one-shot probe as every other provider,
built from the stored config so a wrong base_url/model fails at setup, not
at first chat.

- _run_test_probe: on failure, offer Re-enter key and Switch provider (not
  just retry/repick/continue), matching the connectivity-failure menu; add
  allow_repick to drop the model option for custom (Switch re-enters both).
- _resolve_model_with_test: run the probe for custom too; handle rekey/switch
  in both the custom and picked-model loops.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Onboard let several required gates slip: deleting every provider still
advanced past the required Step 1; a required channel credential could be
left empty and the channel enabled half-configured; and Ctrl+C on the
Step 1/3 menus (and the memory enable/skip prompts) counted as
"done"/"skip" rather than the documented "exit at any point".

- Step 1 "Done" now requires at least one provider AND a default model.
- Channel required fields re-prompt on empty instead of being dropped.
- Ctrl+C (questionary None) exits at every menu, per the module contract.
- Align the navigation docstring: Steps 3 and 4 are forward-only.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
- A brand-new provider whose key was written but then failed verification is
  cleared when the user switches away, so a dead provider is not left listed
  as configured (a pre-existing provider is preserved).
- Clarify --reset help: it re-runs the wizard over an existing config and does
  not erase it.
- Recap warnings now point at re-running onboard (covers provider and memory)
  instead of raven doctor, which has no EverOS memory checks.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Non-interactive onboard always sent a real (billed) chat test message with no
way to opt out, so CI / scripted installs incurred a call. Add --skip-test to
skip the one-shot probe; connectivity (GET /models via test_provider) is still
checked. Threaded from the CLI option through run_wizard -> _step1_provider ->
_configure_one_provider -> _resolve_model_with_test.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
_scancode_login enables the channel before driving the QR login and reverts
on every failure/skip path. But KeyboardInterrupt (Ctrl+C mid-scan) is not an
Exception subclass, so it skipped the revert and left the channel enabled but
unauthenticated. Catch BaseException at the login call to disable it before
letting the interrupt propagate.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Address the full-branch review (2 BLOCKs plus untested paths):
- _scancode_login: wrap the whole flow in try/finally + a logged_in flag so
  ANY non-login exit reverts the enable, including Ctrl+C in the node-missing
  or retry/skip submenus (raises typer.Exit) which the prior narrow fix missed.
- Thread --skip-test into Step 4: interactively enabling memory no longer fires
  the billed EverOS chat/embeddings probes when --skip-test is set.
- A required EverOS role that already has a value returns to its keep/redo menu
  on back-out instead of being forced into the give-up exit.
- Restore an existing provider's prior key when a re-configuration fails and the
  user switches away, so a failed edit no longer clobbers a working key.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Follow-up to the key rollback: snapshot and restore api_base alongside
api_key, so reconfiguring an existing custom provider with a bad base_url and
switching away doesn't leave the stale/broken base_url behind.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
@0xKT 0xKT requested a review from arelchan July 8, 2026 14:02
- Thread skip_test into _verify_provider so the pre-check skip note no longer
  promises a test message when --skip-test has skipped it.
- Thread non_interactive through _scancode_login / _handle_missing_node /
  _add_one_channel instead of hardcoding False, so the node-missing and
  retry/skip submenus honor non-interactive mode.

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat:Setup wizard gets confusing when configuring EverOS memory embedding with DeepSeek

1 participant